2008-08-25 13 views
23

¿Utiliza el diseño por contrato profesionalmente? ¿Es algo que tienes que hacer desde el comienzo de un proyecto, o puedes cambiar de marcha y comenzar a incorporarlo en tu ciclo de desarrollo de software? ¿Cuáles crees que son los pros/contras del enfoque de diseño?¿El diseño por contrato funciona para usted?

Me encontré con el enfoque Design by Contract en un curso de la escuela de posgrado. En el ámbito académico, parecía ser una técnica bastante útil. Pero actualmente no utilizo Design by Contract de forma profesional, y no conozco a otros desarrolladores que lo estén usando. Sería bueno escuchar acerca de su uso real de la multitud SO.

+0

Esta pregunta es ideal para programmers.stackexchange.com. Ver http://programmers.stackexchange.com/q/128717/1282 –

Respuesta

13

No puedo recomendarlo lo suficiente. Es particularmente bueno si usted tiene una suite que lleva a las especificaciones del contrato de documentación en línea, así:

// @returns null iff x = 0 
public foo(int x) { 
    ... 
} 

y las convierte en las pruebas de unidad generados, así:

public test_foo_returns_null_iff_x_equals_0() { 
    assertNull foo(0); 
} 

De esta manera, se puede ver realmente las pruebas que está ejecutando, pero se generan automáticamente. Por cierto, las pruebas generadas no se deben verificar en el control de la fuente.

+7

¿Alguna recomendación de software de código abierto que haga esto para C# /. NET? –

+8

No veo cómo se supone que este caso de prueba de ejemplo pruebe la parte "y solo si" de "iif". –

+0

@NiklasB: dado que no se realizan otras pruebas, 0 es la única entrada posible;);) –

2

Es absolutamente tonto no diseñar por contrato cuando se hace algo en un ámbito SOA, y siempre es útil si se trabaja en cualquier tipo de trabajo modular, donde las piezas & pueden intercambiarse más adelante, especialmente si hay alguna Black Boxen están involucrados.

+0

Esta respuesta no es muy buena. SOA, el trabajo modular, etc. son habilidades básicas de programación, entonces lo que está diciendo es que Design By Contract es aplicable y útil en * todas las situaciones de programación. –

+0

"al hacer cualquier cosa en un reino SOA"! = "Siempre", pero débilmente acoplado> fuertemente acoplado. Siempre. –

+1

@GregHurlman Odio cuando las personas hablan así – Pacerier

1

En lugar de sistemas de tipo más expresivo, yo usaría absolutamente diseño por contrato en proyectos de grado militar.

Para idiomas débilmente tipados o idiomas con alcance dinámico (PHP, JavaScript), los contratos funcionales también son muy útiles.

Para todo lo demás, lo descartaría confiando en los probadores beta y las pruebas unitarias.

Gaius: El motor de ejecución arroja una excepción de puntero nulo, no hay beneficio para probar eso en el prólogo de la función. Si está más interesado en la documentación, entonces usaría anotaciones que pueden usarse con analizadores estáticos y similares (para asegurarse de que el código no esté rompiendo sus anotaciones, por ejemplo).

Un sistema de tipo más fuerte junto con Design by Contract parece ser el camino a seguir. Eche un vistazo a Spec# para un ejemplo:

El lenguaje de programación SpeC#. SpeC# es una extensión del lenguaje orientado a objetos C#. Extiende el tipo de sistema para incluir tipos no nulos y excepciones marcadas . Proporciona contratos de método en forma de pre- y postcondiciones, así como objetos invariantes.

+2

¿Puedes justificar tu primera oración (particularmente "en lugar de")? Ciertamente parece lo suficientemente controvertido, lo que con el ejército de Estados Unidos tomar la ruta exactamente opuesta (que nos trajo Ada ...). Tu última oración también parece contradecirla. También quiero señalar que los sistemas de tipo expresivo se pueden aprovechar perfectamente para * proporcionar * contratos, a través de la comprobación de tipos estáticos. –

0

Realmente no utilizo Design by Contract, todos los días. Sí, sé que se ha incorporado al lenguaje D, como parte del lenguaje.

+1

Desafortunadamente no se ha incorporado a las bibliotecas estándar D, lo que hace que todo el DbC sea casi inútil en la práctica. – Lothar

2

Si observa STL, boost, MFC, ATL y muchos proyectos de código abierto, puede ver que hay muchas declaraciones ASSERTION y que hace que el proyecto vaya más allá de forma más segura.

¡Diseño por contrato! Realmente funciona en producto real.

+3

El STL probablemente no sea el mejor ejemplo de diseño por contrato. Básicamente, la política de STL es que "si el usuario hizo algo incorrecto, todas las garantías se anulan, puede destruir el sistema". Las aserciones que mencionó solo se activan en el modo de depuración. El manejo de errores en el código optimizado de C++ es notoriamente voluble. –

+1

+1 No creo que las aserciones de depuración sean contratos. – rpattabi

+2

"el usuario hizo algo mal, todas las garantías son anuladas, puede arruinar el sistema" que * es * el enfoque DbC: el incumplimiento de una precondición da como resultado un comportamiento indefinido. – Raedwald

3

Frank Krueger escribe:

Gayo: A excepción de puntero nulo se tira de forma automática por el tiempo de ejecución, no hay ningún beneficio a probar esas cosas en el prólogo función.

Tengo dos respuestas a esta:

  1. nula es sólo un ejemplo. Para square (x), me gustaría probar que la raíz cuadrada del resultado es (aproximadamente) el valor del parámetro. Para los instaladores, me gustaría probar que el valor realmente cambió. Para las operaciones atómicas, me gustaría comprobar que todas las operaciones de componentes tuvieron éxito o que todas fallaron (en realidad, una prueba para el éxito yn pruebas para la falla). Para los métodos de fábrica en lenguajes de tipo débil, quiero verificar que se devuelva el tipo correcto de objeto. La lista sigue y sigue. Básicamente, todo lo que se puede probar en una línea de código es un candidato muy bueno para un contrato de código en un comentario de prólogo.

  2. No estoy de acuerdo con que no deba probar cosas porque generan excepciones de tiempo de ejecución. En todo caso, debería probar cosas que podrían generar excepciones de tiempo de ejecución. Me gustan las excepciones de tiempo de ejecución porque hacen que el sistema fail fast, que ayuda a la depuración. Pero el null en el ejemplo fue un valor de resultado para alguna entrada posible. Hay un argumento para nunca volver null, pero si lo vas a hacer, debes probarlo.

+0

"En todo caso, debe probar cosas que puedan generar excepciones de tiempo de ejecución". - En particular, en el punto exacto en el que una excepción de tiempo de ejecución se vuelve inevitable, al menos se debe registrar una violación de la afirmación. El problema con Gaius es que la falla en tiempo de ejecución ocurre en algún caso aleatorio de la violación de supuesto, en lugar de en el punto exacto donde la suposición fue violada por primera vez. Si al llamar a f (x) se produce un bloqueo cuando x == NULL, entonces el log/fail en este problema debe ocurrir en la llamada a f (x) - en lugar de en el interior de una ubicación aleatoria. – Rob

7

Realmente aprecias el diseño por contrato cuando tienes una interfaz entre aplicaciones que tienen que hablar entre ellas.

Sin contratos, esta situación se convierte rápidamente en un juego de culpar al tenis. Los equipos siguen tirando acusaciones de un lado a otro y se desperdician grandes cantidades de tiempo.

Con un contrato, la culpa es clara.

¿Cumplió la persona que llama las condiciones previas? Si no es así, el equipo del cliente debe arreglarlo.

Dada una solicitud válida, ¿el receptor cumplió con las condiciones de publicación? Si no, el equipo del servidor necesita arreglar eso.

¿Ambas partes se adhirieron al contrato, pero el resultado es insatisfactorio? El contrato es insuficiente y el problema debe ser escalado.

Para esto no necesita tener los contratos implementados en forma de afirmaciones, solo necesita asegurarse de que estén documentadas y aceptadas por todas las partes.

1

Tanto las pruebas unitarias como Design by Contract son valiosos enfoques de prueba en mi experiencia.

He intentado utilizar Design by Contract en un sistema de pruebas automáticas y mi experiencia es que ofrece una flexibilidad y posibilidades que no se obtienen fácilmente mediante pruebas unitarias. Por ejemplo, es posible ejecutar una secuencia más larga y verificar que los tiempos de respuesta están dentro de los límites cada vez que se ejecuta una acción.

Al observar las presentaciones en InfoQ, parece que el diseño por contrato es una valiosa adición a las pruebas unitarias convencionales en la fase de integración de componentes. Por ejemplo, es posible crear primero una interfaz simulada y luego usar el componente después de o cuando se lanza una nueva versión de un componente.

No he encontrado un kit de herramientas que cubra todos mis requisitos de diseño para diseñar mediante prueba de contrato en la plataforma .Net/Microsoft.

0

Sí, lo hace! En realidad, hace unos años, diseñé un pequeño marco para la Validación de Argumentos. Estaba haciendo un proyecto SOA, en el que el sistema de back-end diferente, hizo todo tipo de validación y comprobación. Pero para aumentar los tiempos de respuesta (en los casos en que la entrada no era válida y para reducir la carga de esos sistemas de fondo), comenzamos a validar los parámetros de entrada de los servicios proporcionados. No solo para Not Null, sino también para los patrones String. O valores de dentro de conjuntos. Y también los casos donde los parámetros tenían dependencias entre ellos.

Ahora se dan cuenta de que implementamos en ese momento un pequeño diseño de marco contrato :)

Aquí está el enlace para aquellos que estén interesados ​​en el pequeño Java Argument Validation marco. Que se implementa como una solución Java simple.

0

Me resulta revelador que el lenguaje de programación Go no tenga construcciones que hagan posible el diseño por contrato. pánico/aplazar/recuperar no son exactamente eso, ya que la lógica de posponer y recuperar permite ignorar el pánico, IOW ignora el contrato roto. Lo que se necesita al menos es alguna forma de pánico irrecuperable, que es afirmar realmente. O, en el mejor de los casos, soporte de lenguaje directo del diseño mediante construcciones de contrato (condiciones previas y posteriores, implementaciones e invariantes de clase). Pero dada la firmeza de los puristas del lenguaje al mando de Go ship, doy un pequeño cambio en todo esto.

Se puede implementar un comportamiento de afirmación comprobando el error de aserción especial en la última función de aplazamiento en la función de pánico y llamando al tiempo de ejecución.Breakpoint() para volcar la pila durante la recuperación. Para ser afirmativo, al igual que el comportamiento debe ser condicional. Por supuesto, este enfoque se desmorona cuando se agrega una nueva función de aplazamiento después de hacer una afirmación. Lo cual sucederá en un gran proyecto exactamente en el momento equivocado, lo que resultará en errores perdidos.

Mi punto es que es que afirmar es útil de tantas maneras que tener que bailar alrededor puede ser un dolor de cabeza.

Cuestiones relacionadas