Especificación [<>] [\/] [/\]

      Dice un conocido adagio que quien no sabe adónde va llega a otro lado. También es bien sabido que es necesario apuntar antes de disparar. ¿Cómo se puede construir programas sin especificarlos primero? Sin la especificación, no es posible asegurar que se ha obtenido lo que se necesita. En la práctica se recurre al método de prueba y error para determinar si la funcionalidad de una pieza de programación es adecuada. Aunque esta estrategia pospone la etapa de documentación de los módulos construidos, muchas veces no sirve para lograr producir sus especificaciones correctas y completas porque al final del proyecto se recorta el presupuesto para documentar el código [Boehm-1981].

      La especificación puede verse como un contrato en el que están definidos todos los servicios que la implementación del módulo es capaz de dar. La firma o prototipo del módulo siempre forma parte de la especificación, pues si no se definen los tipos y parámetros con que trabaja el módulo es imposible compilarlo o reutilizarlo. Algunos autores consideran que una especificación correcta debe estar escrita en un lenguaje formal, matemático. Pero otros sólo requieren de la especificación un alto rigor, con estas tres cualidades:

      En pocas palabras, en la especificación no debe sobrar ni faltar nada. Debe estar toda la información esencial para implementar un módulo, y también para usarlo. Además, es conveniente que la especificación sea clara y sencilla de entender, de forma que para usarla el programador no requiera hacer un esfuerzo intelectual más grande de lo necesario.

{ 1 }
template< class T>
void list<T>::insert(
    list<T>::iterator  p,
    const value_type & v
)
{ 2 }
Agrega una copia del valor "v" al contenedor.
{ 3 }
- El valor agregado queda antes de la posición "p" en el contenedor.
- Si p==this->end() el valor queda al final de la lista.

Precondición: <<< no tiene >>>
Complejidad: O ( this->size() )
{ 4 }
{{  // test::insert()
    list<long> L = makeList_long( "(3)" );

    L.push_front( 2 ); assertTrue( L == makeList_long( "(2 3)" ) );
    L.push_front( 1 ); assertTrue( L == makeList_long( "(1 2 3)" ) );
    L.push_back(  4 ); assertTrue( L == makeList_long( "(1 2 3 4)" ) );
    L.push_back(  5 ); assertTrue( L == makeList_long( "(1 2 3 4 5)" ) );

    L.insert( L.begin() , 0 );
    L.insert( L.end()   , 6 );
    assertTrue( L == makeList_long( "(0 1 2 3 4 5 6)" ) );

    list<long>::iterator it = L.begin();
    while ( it != L.end() && (*it != 4) ) { ++it; }
    L.insert(it,4);
    assertTrue( L == makeList_long( "(0 1 2 3 4 4 5 6)" ) );
}}
Figura 1: list<T>::insert()

      En la Figura 1 está una especificación bastante completa porque incluye las partes que generalmente forma parte de un buen sistema de documentación:

{ 1 }   Encabezado, firma o prototipo.
{ 2 }   Descripción corta de la funcionalidad.
{ 3 }   Descripción detallada.
{ 4 }   Ejemplo de uso.

      { 1 } El encabezado, firma o prototipo de un módulo contiene la información que necesita el compilador para traducir el programa. Incluye: (1) el tipo del valor retornado, (2) el tipo de los parámetros y (3) el nombre calificado del módulo. En el ejemplo de la Figura 1 el nombre calificado de la rutina es list<T>::insert() por lo que el compilador deduce que insert() es un método de la clase parametrizada list<T>. Como el valor retornado por insert() es void el compilador reconoce que este método no retorna ningún valor, que recibe una copia del objeto list::iterator<T> pero que, aunque recibe por referencia el parámetro "v", no puede modificarlo porque "v" es un parámetro const. El nombre calificado del tipo "value_type" es list<T>::value_type pues el lenguaje C++ permite usar abreviaciones en muchos contextos.

      { 2 } La descripción corta de la funcionalidad del módulo generalmente cabe en un solo renglón y dice qué hace el módulo. Usualmente con esta descripción se define o refleja la abstracción o esencia del componente de programación, pero debido a que es una descripción concisa usualmente no es suficientes para reutilizarlo. En el ejemplo de la Figura 1 la descripción corta dice que "Agrega una copia del valor "v" al contenedor".

      { 3 } La descripción detallada contiene la documentación que los programadores necesitan para usar el módulo. Ahí se indican todos los detalles y reglas que deben respetarse para que obtener los resultados correctos al usarlo. Este es el sitio en donde el programador indica cuáles son las pre-condiciones que deben cumplir los valores antes de usar el módulo y también deben quedar indicados cuáles son los resultado o post-condiciones. En el ejemplo de la Figura 1 es en la descripción detallada de la funcionalidad de la rutina en donde se aclara que la inserción se realiza antes de la posición "p", pues sin esta aclaración esta lista no funcionaría como lista sino que sería más bien un conjunto (std::set<>).

      { 4 } El ejemplo de uso le permite al programador apreciar inmediatamente la funcionalidad del módulo. También le permite copiar el texto del ejemplo para reutilizarlo inmediatamente. Cuando los programadores usan una biblioteca están acostumbrados a ponerle más atención a los ejemplos de uso que a la narrativa que define el comportamiento de cada módulo. Dice un conocido adagio que una imagen vale por mil palabras; en computación, un ejemplo vale más o menos eso mismo. Si la especifiación no incluye ejemplos, en muchos casos los programadores encuentran difícil utilizarla.

      Cualquier programador tiene el entrenamiento necesario para producir los ítemes { 1 } y { 2 } (prototipo + descripción corta). Para producir el ejemplo de uso { 4 } se requiere usar alguna herramienta que permita sirva para construir pruebas unitarias de módulos. En un contexto universitario, conviene usar un el módulo C++ BUnit que tiene la gran ventaja de que su implementación completa cabe en un único archivo de encabezado [DiM-2008c]. La implementación C++ BUnit.h es un sencillo marco de prueba unitaria de módulos basado en la herramienta JUnit para Java [BG-1998].


Copyright © 2010 Adolfo Di Mare
Derechos de autor reservados © 2010 Adolfo Di Mare <adolfo@di-mare.com>
[home] [<>] [/\]