design by contract - ¿Las condiciones previas SIEMPRE deben ser verificadas?
design-by-contract (9)
En estos días estoy acostumbrado a verificar cada condición previa para cada función, ya que adquirí el hábito de un curso de programación de SO en la universidad.
Por otro lado, en el curso de ingeniería de software se nos enseñó que una condición previa común solo debe verificarse una vez, por ejemplo, si una función está delegando a otra función, la primera función debería verificarlos pero volver a verificarlos en la segunda. es redundante
Veo el punto de redundancia, pero ciertamente creo que es más seguro verificarlos, además, no tiene que hacer un seguimiento de dónde se verificaron anteriormente.
¿Cuál es la mejor práctica aquí?
Si una función está delegando a otra función, la primera función debería verificarlas, pero verificarlas nuevamente en la segunda es redundante.
¿Qué pasa si cambias la forma en que esas funciones se llaman entre sí? ¿O introduces nuevos requisitos de validación en la segunda función, a los que la primera delega? Yo diría que es más seguro revisarlos siempre.
Al igual que con todo, evalúe sus requisitos para encontrar la mejor solución para cada situación.
Cuando las condiciones previas son más fáciles de verificar ("el puntero no es nulo"), también puede hacerlo a menudo. Las condiciones previas que son difíciles de verificar ("apunta a una cadena válida terminada en nulo") o son costosas en tiempo, la memoria u otros recursos pueden manejarse de una manera diferente. Usa el principio de Pareto y recoge la fruta de baja altura.
// C, C++:
void example(char const* s) {
// precondition: s points to a valid null-terminated string
assert(s); // tests that s is non-null, which is required for it to point to
// a valid null-terminated string. the real test is nearly impossible from
// within this function
}
Garantizar condiciones previas es responsabilidad de la persona que llama . Debido a esto, varios idiomas ofrecen una construcción "asertiva" que puede omitirse opcionalmente (por ejemplo, definir NDEBUG para C / C ++, interruptor de línea de comandos para Python) para que pueda probar más ampliamente las condiciones previas en construcciones especiales sin afectar el rendimiento final. Sin embargo, el uso de asert puede ser un debate acalorado; una vez más, determine sus requisitos y sea consistente.
Creo que depende de cómo esté organizado el equipo: verifique las entradas que provienen de fuera de su equipo.
- Compruebe las entradas de los usuarios finales
- Verifique las entradas de los componentes de software escritos por otros equipos.
- Confíe en las entradas recibidas desde su propio componente / dentro de su propio equipo.
La razón de esto es para soporte y mantenimiento (es decir, corrección de errores): cuando hay un informe de error, desea poder saber lo más rápido posible qué componente tiene la culpa, es decir, a qué equipo asignar el error.
Creo que la mejor práctica es hacer estas comprobaciones solo si van a fallar algún día. Si te ayudará cuando hagas lo siguiente.
Depuración
No tiene sentido verificarlas cuando varias funciones privadas en un módulo, que tiene un único mantenedor, intercambian datos. Por supuesto, hay excepciones, especialmente si su idioma no tiene un sistema de tipo estático, o sus datos están " escritos rigurosamente ".
Sin embargo, si expone la API pública, un día, alguien fallará su condición previa. Cuanto más lejos esté la persona que mantiene su módulo de llamada (en la estructura organizativa y en la ubicación física), más probable será que suceda. Y cuando sucede, una declaración clara de falla de condición previa, con una especificación donde ocurrió, puede ahorrar horas de depuración. La Ley de abstracciones con fugas sigue siendo cierta ...
QA
El fallo de condición previa ayuda al control de calidad a depurar sus pruebas. Si una prueba de unidad para un módulo hace que el módulo produzca una falla de condición previa, significa que la prueba es incorrecta, no su código. (O bien, que su verificación de condición previa es incorrecta, pero eso es menos probable).
Si uno de los medios para realizar el control de calidad es el análisis estático , entonces las comprobaciones de condición previa, si tienen una notación específica (por ejemplo, solo estas comprobaciones utilizan la macro assert_precondition
), también ayudarán. En el análisis estático es muy importante distinguir errores de entrada y código fuente incorrectos.
Documentación
Si no tiene mucho tiempo para crear documentación, puede hacer que su código ayude al texto que lo acompaña. Las verificaciones de condición previa claras y visibles, que se perciben de forma separada del resto de la implementación, "documentan" posibles aportes hasta cierto punto. (Otra forma de documentar su código de esta manera es escribiendo pruebas unitarias).
En mi experiencia, depende de su encapsulación. Si la función interna es privada, puede estar bastante seguro de que sus condiciones previas están establecidas.
Supongo que todo se trata de la Ley de Deméter, habla solo con tus amigos y demás.
Como base para las mejores prácticas, si la llamada es pública, debe verificar sus entradas.
Es una pregunta un poco vieja, pero no, las condiciones previas no tienen que ser verificadas cada vez. Realmente depende.
Por ejemplo, qué pasa si tiene búsqueda binaria sobre vector. La condición previa es un vector ordenado. Ahora, si comprueba cada vez que el vector se ordena, esto toma un tiempo lineal (para cada vector), por lo que no es eficiente. El cliente debe conocer la condición previa y asegurarse de cumplirla.
La mejor práctica es comprobarlos siempre.
Me he acostumbrado a distinguir entre verificar y hacer valer las condiciones previas, dependiendo (como lo señala la gente en los comentarios) sobre si una llamada proviene del exterior (puede suceder una excepción no verificada) o del interior (afirmar, no debería ocurrir) ).
Idealmente, el sistema de producción no tendrá la penalización de las afirmaciones, e incluso podría utilizar un mecanismo similar a Design By Contract (TM) para descargar las aseveraciones de forma estática.
No he visto ninguna regla "dura y rápida" sobre cómo verificar las condiciones previas, pero generalmente la trato como la documentación del método. Si tiene un alcance público, afirmo que se cumplen las condiciones previas. La lógica detrás de esto sería que el alcance dicta que está esperando un consumo en una escala más amplia y con menos influencia.
Personalmente, el esfuerzo por establecer afirmaciones en torno a los métodos privados es algo que reservo para los métodos de "misión crítica", que básicamente serían los que realizan una tarea crítica, están sujetos a requisitos de cumplimiento externos o no son recuperables en caso de una excepción. Estas son en gran parte "llamadas de juicio".
El tiempo ahorrado se puede reinvertir en una mejora completa de la prueba de la unidad y la integración para tratar de solucionar estos problemas y poner las herramientas en su lugar para ayudar a hacer cumplir la calidad de las aserciones de entrada, ya que sería consumido por un cliente, ya sea una clase en Su control o no.