Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Introducción al Diseño por Contrato

Documentación estructurada, precondiciones, postcondiciones e invariantes informales

Universidad Nacional de Río Negro

Introducción

El Diseño por Contrato (Design by Contract, DbC) es una metodología de desarrollo de software formalizada por Bertrand Meyer. Propone que la interacción entre diferentes partes de un sistema (por ejemplo, el código que llama a una función y la función misma) se debe modelar como un contrato formal entre clientes y proveedores.

Un contrato establece derechos y obligaciones mutuas. En el contexto de las funciones, los componentes clave de este acuerdo son las precondiciones, postcondiciones e invariantes.


Desarrollo

Precondiciones y Postcondiciones Informales

Precondiciones (El Derecho del Proveedor, Obligación del Cliente)

Una precondición especifica las condiciones que deben ser obligatoriamente verdaderas antes de que una función comience su ejecución.

// Precondición: 'b' no debe ser cero.
int dividir(int a, int b) {
    // Si b es cero, la división por cero provocará un fallo físico en el hardware.
    return a / b;
}

Postcondiciones (El Derecho del Cliente, Obligación del Proveedor)

Una postcondición describe las garantías lógicas que la función promete cumplir después de terminar su ejecución, siempre y cuando la precondición haya sido satisfecha al inicio.

// Precondición: 'radicando' >= 0
// Postcondición: El valor retornado es 'r' tal que r * r <= radicando y (r+1)*(r+1) > radicando
int raiz_entera(int radicando) {
    // Implementación del algoritmo
}

Invariantes Elementales e Invariantes de Lazo

Invariantes de Lazo (Loop Invariants)

Un invariante de lazo es una condición lógica (una afirmación sobre las variables del programa) que es verdadera:

  1. Antes de ingresar al lazo de control.

  2. Antes y después de cada iteración individual del lazo.

  3. Inmediatamente después de salir del lazo de control.

Los invariantes de lazo son la herramienta didáctica fundamental para razonar lógicamente sobre la correctitud de los algoritmos iterativos. Nos permiten verificar de forma inductiva que un lazo de control realmente cumple su objetivo paso a paso.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Precondición: arr != NULL y n >= 0
// Postcondición: retorna la suma de todos los elementos de arr[0] a arr[n-1]
int sumar_arreglo(const int arr[], int n) {
    int suma = 0;
    int i = 0;
    
    // Invariante: suma es la suma acumulada de arr[0] a arr[i-1] AND 0 <= i <= n
    while (i < n) {
        suma += arr[i];
        i++;
    }
    
    return suma;
}

Ejercicios de Autoevaluación

Precondiciones y Postcondiciones

Solution to Exercise 1

La precondición formal de la función es:

Pre(b0)\text{Pre} \equiv (b \neq 0)

El Diseño por Contratos establece que si el cliente viola la precondición (llamando a la función con b=0b = 0), el proveedor queda completamente liberado de sus obligaciones de cumplimiento de la postcondición. El comportamiento del programa pasa a ser indefinido (undefined behavior), pudiendo crashearse, retornar basura o corromper la memoria del sistema.

Solution to Exercise 2

La postcondición formal asociando el valor de retorno rr de la función es:

Post(x,r)(x0r=x)(x<0r=x)\text{Post}(x, r) \equiv (x \geq 0 \rightarrow r = x) \land (x < 0 \rightarrow r = -x)

Invariantes de Lazo

Solution to Exercise 3

El invariante de lazo formal para la búsqueda lineal es:

I(0in)(j. 0j<iarr[j]elem)I \equiv (0 \leq i \leq n) \land \left(\forall j.\ 0 \leq j < i \rightarrow \text{arr}[j] \neq \text{elem}\right)

Este invariante establece dos condiciones:

  1. El índice de control i se mantiene dentro del rango válido de control [0,n][0, n].

  2. Para cualquier elemento recorrido previamente (índices menores a i), su valor es diferente al del elemento buscado elem.

Al terminar el lazo, si salimos porque i == n, el invariante nos garantiza de forma inductiva que elem no se encuentra en ninguna posición del arreglo.


Glosario

Diseño por Contrato (DbC)
Metodología de diseño de software que formaliza las interfaces entre componentes mediante derechos y obligaciones mutuas (contratos lógicos).

Síntesis y Resumen

En esta unidad te introdujiste en el formalismo del Diseño por Contrato y su aplicación en la verificación de algoritmos:


Referencias y Lecturas Complementarias