Beruflich Dokumente
Kultur Dokumente
El uso de una construcción de este tipo anularía el propósito de tener una condición previa
(Requerir cláusula). Esta es una regla absoluta: o tienes la condición
en el Requerir, o lo tienes en un If
instrucción en el cuerpo de la rutina,
pero nunca en ambos.
Este principio es exactamente lo contrario de
la idea de programación defensiva, ya que
dirige a los programadores para evitar pruebas redundantes. Tal enfoque es posible
y fructífero porque el uso de aserciones alienta a escribir software para deletrear
las condiciones de coherencia que podrían
salir mal en tiempo de ejecución. Luego, en lugar de verificar a ciegas, como con la
programación defensiva, puede usar claramente definido
contratos que asignan la responsabilidad
para cada condición de consistencia a uno de
las fiestas. Si el contrato es preciso y
explícito, no hay necesidad de redundancia
cheques.
Cuanto más fuerte es la condición previa, el
Más pesada la carga sobre el cliente. y
Más fácil para el proveedor. El asunto
de quién debería tratar con valores anormales es esencialmente una decisión pragmática
sobre la división del trabajo: la mejor solución es la que logra la más simple
arquitectura. Si cada rutina y persona que llama
comprobado por cada posible error de llamada,
Las rutinas nunca realizarían ningún trabajo útil.
En muchos programas existentes, uno puede
Difícilmente encontrar las islas de procesamiento útil en los océanos de código de verificación
de errores.
En ausencia de afirmaciones, defensivas
La programación puede ser el único enfoque razonable. Pero con técnicas para
definiendo con precisión la responsabilidad de cada parte, según lo dispuesto por las
afirmaciones, tales
la redundancia (tan perjudicial para la consistencia y simplicidad de la estructura) es
innecesario.
Para que la teoría del contrato funcione correctamente y conduzca a sistemas correctos,
el cliente
los programadores deben contar con un
Descripción adecuada de las propiedades de interfaz de una clase y sus rutinas: el
contratos
Aquí las afirmaciones pueden jugar un papel clave.
ya que ayudan a expresar el propósito de un
elemento de software como una rutina sin referencia a su implementación.
El breve comando del entorno Eiffel sirve para documentar una clase.
mediante la extracción de información de la interfaz. En
Este enfoque. documentación de software
no se trata como un producto para ser desarrollado y mantenido por separado de
el código real: en cambio, es el más
parte abstracta de ese código y puede ser
extraído por herramientas informáticas.
El comando corto retiene solo el
características exportadas de una clase y. por un
rutina exportada, suelta el cuerpo de rutina
y cualquier otra implementación relacionada
detalles. Sin embargo. Se mantienen las condiciones previas y posteriores. (Así es el
comentario del encabezado si está presente). Por ejemplo, Figura 6
muestra lo que produce el comando corto
para la rutina del plct. Se expresa simplemente
y concisamente el propósito de la rutina. sin referencia a un particular
implementación.
Toda la documentación sobre los detalles de
Clases de Eiffel (por ejemplo, la clase
especificaciones en el libro sobre lo básico
bibliotecas ") se produce automáticamente en
esta moda Para clases que heredan de
otros, el comando corto debe combinarse con otra herramienta.flar. que aplana la
jerarquía de clases al incluir características heredadas en el mismo nivel que
Los "inmediatos" (los declarados en
la clase misma).
Seguimiento de afirmaciones
Qué pasa si. durante la ejecución una
Qué sistema viola una de sus propias afirmaciones?
En el entorno de desarrollo. el
La respuesta depende de una opción de compilación. Para cada clase puedes elegir
desde varios niveles de control de aserciones: sin verificación de aserciones.
precondiciones solamente (el valor predeterminado). condiciones previas
y postcondiciones. todo lo anterior más
invariantes de clase. o todas las afirmaciones. (Los
diferencia entre los dos últimos sigue
de la existencia de otras afirmaciones.
como loop in \ ariants. no cubierto en
la discusión actual)
Para una clase compilada bajo el "no
opción de monitoreo de aserciones ”. afirmaciones
no tiene efecto en la ejecución del sistema. los
opciones posteriores causan evaluación de
aserciones en varias etapas: entrada de rutina para condiciones previas, salida de rutina
para
condiciones posteriores y ambos pasos para invariantes.
Bajo las opciones de monitoreo, el
efecto de una violación de afirmación es elevar
una excepción. Las posibles respuestas a
Una excepción se discute más adelante.
¿Por qué monitorear?
Como se señaló, las violaciones de afirmación no son
casos especiales (pero esperados); resultan
de bichos. La aplicación principal de la supervisión de aserción de tiempo de ejecución.
entonces, se está depurando. Activando la comprobación de afirmaciones
(en cualquiera de los niveles enumerados anteriormente)
hace posible detectar errores.
Al escribir software. desarrolladores
hacer muchas suposiciones sobre las propiedades que se mantendrán en varias etapas de
la ejecución del software, especialmente la entrada y el retorno de rutina. En los
enfoques habituales para la construcción de software. Estos supuestos siguen siendo
informales e implícitos. Aquí el mecanismo de afirmación
permite a los desarrolladores expresarlos explícitamente. El control de la afirmación,
entonces, es un
manera de llamar al fanfarrón del desarrollador comprobando qué hace el software
contra qué
su autor cree que sí. Esto produce un
enfoque productivo para la depuración, prueba. y garantía de calidad, en la cual
la búsqueda de errores no es ciega sino basada
en condiciones de consistencia proporcionadas por
los propios desarrolladores
Particularmente interesante aquí es el uso
de precorzditions en clases de biblioteca. En
Según el enfoque general para la construcción de software sugerido por el método
Eiffel, los desarrolladores crean sucesivos "grupos" de clases en un orden ascendente.
de más general (reutilizable) a más
específico (dependiente de la aplicación). Esta
es el "modelo de clúster" del software
ciclo de vida "." Decidir lanzar una biblioteca
el grupo 1 para uso general normalmente implica un grado razonable de confianza
en su calidad: la creencia de que no hay errores
permanecer en 1. Por lo tanto, puede ser innecesario
supervisar las condiciones posteriores de las rutinas
en las clases de 1. Pero las clases de un
clúster de aplicaciones que es un cliente de I
(ver Figura 7) puede ser "joven" y
contener errores: dichos errores pueden aparecer como
argumentos erróneos en llamadas a rutinas de las clases de 1. Supervisar condiciones
previas para clases de Ayudé a encontrar
ellos. esta es una de las razones del porque
la comprobación previa es el valor predeterminado
Opción de compilación.
Invariantes y
enlace dinámico
Además de las reglas sobre condiciones previas y posteriores, otra restricción vincula
las afirmaciones con la herencia:
Las invariantes siempre se transmiten a los descendientes.
Este es un resultado directo de la opinión de que
La herencia es (entre otras cosas) clasificación. Si queremos considerar cada
instancia de una clase B como siendo también un
instancia de los antepasados de R. debemos aceptar que las restricciones de coherencia
en un
el padre A también se aplica a las instancias de B.
Por ejemplo, si el invariante para un
clase TREE, que describe nodos de árbol, incluye la cláusula
child.parent = Current
expresando que el padre de un nodo
El hijo actualmente activo es el nodo en sí,
esta cláusula se aplicará automáticamente a
instancias de una clase BINARY-TREE,
que hereda de TREE. Como resultado,
la especificación del lenguaje define "el
invariante de una clase "como la afirmación
obtenido mediante la concatenación de la afirmación en la cláusula invariante de la
clase
a los invariantes de todos los padres (obtenido
recursivamente bajo esta definición) ".
Como resultado, la invariante de una clase es
siempre más fuerte o igual que el
invariantes de cada uno de sus padres.
Estas reglas conducen a una mejor comprensión de por qué sería vinculante estático,
como se dijo anteriormente, tal desastre.
Asuma nuevamente la declaración y llame
u: A:
.
u.r
donde un descendiente B de A redefine r.
Llame a rA y r ,,, las dos implementaciones.
Entonces r, debe preservar INV ,, el invariante de A, y rg debe preservar INV ,, el
invariante de B, que es más fuerte que o
igual a INV.
No hay, por supuesto, ningún requisito.
que ra preservar INV. De hecho, clase A
puede haber sido escrito mucho antes de B,
y el autor de A no necesita
saber algo sobre eventuales descendientes de esta clase.
Si LL se une dinámicamente a
una instancia de B, el enlace dinámico requiere la ejecución de rH para esta llamada.
La unión estática provocaría ra. Ya que
esta versión de la rutina no es necesaria para preservar INV, el resultado sería
producir una situación catastrófica: un objeto
de tipo B que no satisface la restricción de consistencia -la invariante -of
su propia clase En tales casos, cualquier intento
para comprender textos de software o razonar sobre su comportamiento en tiempo de
ejecución
se vuelve inútil.
Un simple ejemplo hará que la situación sea más concreta. Asume una clase
CUENTA que describe cuentas bancarias,
con los atributos mostrados en la Figura Ya
y un procedimiento para registrar un nuevo depósito
mostrado en la Figura 9b.