Materia: #algoritmos_y_estructuras_de_datos
Tags:
Especificación
Dentro del mundo de la programación, siempre trabajamos bajo la idea de contrato, en la que alguien nos solicita que diseñemos un programa que lo ayude a realizar una operación concreta. Bajo estos términos, necesitamos aclarar que tipo de problema queremos solucionar y como vamos a poder hacerlo.
Es en este contexto donde nace la idea de especificación, con la cual queremos dejar bien en claro, de manera formal y sin lugar a dudas o interpretaciones, que es lo que hay que resolver. No nos va a decir como hacerlo, pero si nos indica que tipo de parámetros de entrada vamos a utilizar, que salida esperamos, y, sin mas vueltas, que proceso queremos hacer. Esta escritura formal nos será útil a la hora de testear el programa y verificar su correctitud.
Cada parámetro que tenga una especificación va a tener un tipo de dato, lo cual es un conjunto de valores y operaciones que se pueden aplicar sobre esos mismos valores.
Retomando lo del contrato, siempre vamos a tener esta perspectiva. Vamos a trabajar en términos de un usuario que nos solicita a nosotros, los programadores, que diseñemos un programa para solucionar un problema.
Sintaxis
Una especificación consta de varias partes, en particular, se ven mas o menos así:
proc nombreDeLaFuncion(parametros) {
requiere {precondición}
asegura {postcondición}
/*Esto es un comentario, y va a ser ignorado*/
}
Donde proc
es una palabra reservada para referirnos a procedimiento, es para iniciar la definición de la especificación. El nombre es el nombre que le damos a nuestra especificación, el cual podemos elegir nosotros. Recomendamos usar nombres claros y que indiquen cual es la operación a resolver. Luego, los parámetros son los valores de entrada o salida que nuestra especificación va a necesitar para realizar su evaluación, suelen escribirse tipados.
Luego, el renglón de requiere
, la cual es una palabra reservada para iniciar las precondiciones. Estas van a ser nuestras condiciones que el usuario deberá cumplir con sus valores de entrada. Es decir, nosotros (los programadores) vamos a dar por hecho que estas condiciones se van a cumplir. Es obligación del usuario cumplir siempre con los requiere de nuestro programa.
Finalmente, llegamos a la parte del asegura
, que también es una palabra reservada, en este caso inicia las postcondiciones. A diferencia del anterior punto, estas serán las condiciones que nuestro programa deberá cumplir para obtener la correcta salida o solución. Es decir, es obligación del programador asegurar que las postcondiciones se cumplan, y que el programa concluya lo que es correcto.
Por ultimo, y no por eso menos importante, esta el comentario. A la hora de evaluar una especificación esos son ignorados, pero pueden hacer la lectura mucho mas amena.
Una cosa a tener en cuenta es acerca de los parámetros, los cuales tienen tres formas de entrar:
Algo útil a tener en cuenta a la hora de trabajar con funciones que tengan parámetros
Otra cosa importante, es que a la hora de especificar problemas no podemos utilizar otros procedimientos para la solución del mismo. Solo podemos utilizar predicados y funciones auxiliares, obviamente definiéndolos previamente. A su vez, dentro de las funciones auxiliares no podemos definir instrucciones recursivas, ya que solo se tratan de un reemplazo sintáctico.
Funciones auxiliares, predicados y condicionales
Existen ocasiones en las que hay una o mas operaciones que utilizamos reiteradas veces, y puede ser molesto repetirlas, aparte de hacer difícil la futura lectura de la especificación. Para estos casos, tenemos las funciones auxiliares, que son especificaciones mucho mas básicas y sencillas, las cuales hacen una operación exclusiva. La sintaxis de las funciones auxiliares se ve así:
aux nombre (parámetros) : resultado = procedimiento
Se asemeja bastante a lo visto antes, lo único nuevo es aquella parte de procedimiento. Aquí es donde escribiremos la operación a realizar o el resultado a dar. Fíjense que no tenemos ni requiere
ni asegura
, lo cual hace mucho mas básica esta estructura. Un ejemplo habitual puede ser obtener un valor aproximado de alguna constante matemática, como:
aux pi () : R = 3.14159
Noten que acá hicimos una función que no tiene parámetros de entrada, lo cual también podría aplicarse a las especificaciones habituales.
También, podemos definir predicados, que son operaciones básicas como las funciones auxiliares de antes, pero que exclusivamente evalúan una fórmula lógica, es decir, su resultado es únicamente un valor de verdad. Un ejemplo común de esto puede ser:
pred esPar(n : Z) {
n mod 2 = 0
}
Finalmente, tenemos las expresiones condicionales, las cuales son funciones que elige entre dos elementos del mismo tipo, según una fórmula lógica. En particular, si la fórmula es verdadera, elije la primera opción, y en caso contrario, la segunda. La estructura de una expresión condicional es del tipo:
if condicion then primer_resultado else segundo_resultado fi