2009-04-13 20 views
7

¿Cuáles son las mejores prácticas para la programación de diseño por contrato?¿Cuáles son las mejores prácticas para la programación de diseño por contrato?

En la universidad aprendí el diseño de paradigma contrato (en un entorno orientado a objetos) Hemos aprendido tres maneras de abordar el problema:

1) Programación Total: Cubre todos los posibles casos excepcionales en su efecto (cf. Matemáticas)

2) Programación nominal: Sólo promesas '' los efectos adecuados cuando se cumplan las condiciones previas. (De lo contrario el efecto no está definido)

3) La programación defensiva: Utilice excepciones para señalar las invocaciones de métodos ilegales

Ahora, nos hemos centrado en diferentes escenarios OO sobre el uso correcto en cada situación, pero no hemos aprendido CUÁNDO usar CUAL ... (La mayoría de las tácticas son informadas por el ejercicio ...)

Ahora pienso que es muy extraño que no le haya preguntado a mi profesor (pero de nuevo, durante las clases, nadie lo ha hecho)

Personalmente, nunca uso nominales ahora, y tiendo a reemplazar condiciones previas s con excepciones (así que prefiero usar: throws IllegalDivisionByZero, que declarar 'condición previa: el divisor debe diferir de cero) y solo programa lo que tiene sentido (por lo que no devolvería un valor convencional en la división por cero), pero este método es solo basado en hallazgos personales y me gusta.

por lo que les pido chicos:

¿Hay algún mejores prácticas ??

Respuesta

5

No sabía de esta división, y realmente no refleja mi experiencia.

Programación total es prácticamente imposible. No puede garantizar que cubra todos los casos excepcionales. Así que, básicamente, usted debe limitar su alcance y rechazar las situaciones que están fuera de alcance (que es el papel de las condiciones previas )

no se desea la programación nominal. El efecto indefinido debe ser prohibido.

Programación defensiva es una necesidad. Siempre debe señalar invocaciones ilegales de métodos.

estoy a favor de la aplicación de los elementos completos de diseño por contrato, que es, en mi opinión una versión práctica y affortable de la programación total

Condiciones previas (una especie de Programación defensiva) para señalar la invocación ilegal del método. Intenta limitar tu alcance tanto como puedas para que puedas simplificar el código. Evite la implementación compleja si es posible al reducir un poco el alcance.

Postconditions para generar un error si no se obtiene el efecto deseado. Incluso si es su culpa, debe notificar a la persona que llama que ha perdido su objetivo.

Invariantes para comprobar que se mantiene la coherencia del objeto.

+0

realmente me gusta la afirmación obvia pero pertinente que limita el alcance para que pueda simplificar el código ... ¡excelente consejo! – Rob

1

Todo se reduce a las responsabilidades que desea asignar al cliente y al ejecutor del contrato.

En la programación defensiva, obliga al implementador a verificar las condiciones de error que, en algunos casos, pueden ser costosas o incluso imposibles. Imagine un contrato especificado por binarySearch, por ejemplo, su matriz de entrada debe ser ordenada. no puedes detectar esto mientras ejecutas el algoritmo. tienes que hacer una comprobación manual que realmente afectará el tiempo de ejecución en un orden de magnitud. para respaldar mi opinión es la firma del método del javadocs.

Otro punto es Las personas y los marcos ahora tienden a implementar mecanismos de traducción de excepción que se utilizan principalmente para traducir las excepciones comprobadas (estilo defensivo) a las excepciones de tiempo de ejecución que aparecerán si ocurre algo incorrecto. De esta forma, el cliente y el ejecutor del contrato tiene menos de qué preocuparse mientras se trata el uno con el otro.

De nuevo, esto es mi opinión personal respaldada sólo con lo que la limitada experiencia que tengo, me encantaría saber más sobre este tema.

+0

Puede verificar que cualquiera de las matrices esté ordenada como condición previa. Hacemos esto en el C++ con afirmaciones. –

+0

comprobar que todo el conjunto está ordenado lleva más tiempo que realizar una búsqueda binaria en él :) – MahdeTo

+0

Solo algunos pensamientos: puede verificar las condiciones previas solo en ciertos modos, digamos para la prueba de unidad no? Además, una condición previa puede ser establecida y no probada, por supuesto – Peter

1

... pero no hemos aprendido CUANDO usar que ...

Creo que la mejor práctica es a ser "tan defensiva como sea posible". Haga los controles de tiempo de ejecución si puede. Como @MahdeTo ha mencionado a veces eso es imposible por razones de rendimiento; en tales casos recurrir a un comportamiento indefinido o no satisfactorio.

Dicho esto, explíquese en su documentación en cuanto a qué controles de tiempo de ejecución y qué no.

0

Como gran parte de la informática "depende" es probablemente la mejor respuesta.

El diseño por contrato/programación por contrato puede ayudar al desarrollo en gran medida documentando explícitamente las condiciones para una función. Solo la documentación puede ser una ayuda sin siquiera convertirla en código (compilado).

Siempre que sea posible, recomiendo la defensa, verificando todas las condiciones. PERO solo para construcciones de desarrollo y depuración. De esta forma, la mayoría de los supuestos no válidos se detectan cuando se rompen las condiciones. Un buen sistema de compilación le permitiría activar y desactivar las diferentes clases de condición a nivel de módulo o archivo, así como globalmente.

Las acciones tomadas en las versiones de lanzamiento del software dependen entonces del sistema y de cómo se activa la condición (distinción habitual entre las interfaces externas e internas). La versión de lanzamiento podría ser 'programación total' - todas las condiciones dan un resultado definido (que puede incluir errores o NaN)

Para mí, la "programación nominal" es un callejón sin salida en el mundo real. Usted asume que si pasó los valores correctos en (que por supuesto lo hizo), entonces el valor que recibe es bueno. Si tu suposición fue incorrecta, te derrumbas.

0

Creo que la programación basada en pruebas es la respuesta. Antes de implementar realmente el módulo, primero crea una prueba unitaria (llámalo un contrato). Luego, implemente gradualmente la funcionalidad y asegúrese de que el contrato siga siendo válido a medida que avanza. Por lo general, empiezo con trozos simples y prototipos, y poco a poco llenando el resto reemplazando las pinchaduras con cosas reales. Sigue mejorando y haciendo la prueba más fuerte. Al final, terminas con una implementación robusta de dicho módulo y además tienes una fantástica implementación codificada en el lecho de prueba del contrato. Más adelante, si alguien modifica el módulo, primero verá si todavía puede ajustarse al banco de pruebas. Si no lo hace, el contrato está roto: rechace los cambios. O bien, el contrato está desactualizado, - corrige las pruebas unitarias. Y así sucesivamente ... Ciclo aburrido del desarrollo de software :)

+0

Si bien es una buena idea, no creo que responda la pregunta. No puede escribir pruebas para valores no válidos si no ha decidido primero cómo debe responder el sistema a los valores no válidos. – Mark

+0

@Mark No puedes. Entonces, 1) decidir, 2) comenzar a escribir la prueba para el valor inválido más básico 3) cuando falla la prueba debido a falta de código, iterar el código hasta el pase de prueba, 4) pruebas de refactorización y código de producción 5) decidir sobre el siguiente valor inválido y hacer otro rojo -refrigerar iteración hasta que te quedes sin grupos de valores no válidos para probar y luego comenzar a escribir pruebas para casos felices, comenzando con los más básicos, como consejos del tío Bob :) – Tom

+0

@Tom Eso es solo una explicación más de TDD y aún no lo hace responde la pregunta Se trata de elegir entre los enfoques de Diseño por contrato. Tienes que elegir el enfoque antes de poder escribir las pruebas. Por ejemplo, si elige nominal, usando la definición en la pregunta, no probaría los valores inválidos. – Mark

Cuestiones relacionadas