robustness - traduccion - Mejores prácticas para robustez
robustness synonym (10)
Acabo de encontrar esta pregunta sobre la inicialización de variables locales. Muchas de las respuestas debatieron simplicidad / legibilidad vs. robustez. Como desarrollador de sistemas embebidos (implementados de forma remota), siempre estoy a favor de la solidez y tiendo a seguir varias reglas aparentemente contradictorias:
Maneje cada error lo mejor que pueda de una manera que permita que el dispositivo continúe funcionando.
Diseñe el código para que falle tan pronto como sea posible después de una programación o un error fatal.
Todos hemos sido entrenados para validar la entrada para evitar que el dispositivo se rompa como resultado de la entrada del usuario (u otra fuente externa); siempre asuma que los datos pueden ser inválidos y pruébelo en consecuencia.
¿Qué otras prácticas específicas sigues para garantizar la solidez? Los ejemplos son útiles, pero también me interesan las técnicas que son universalmente aplicables.
Cuando es posible, solicito la opinión de alguien que se especialice en otra cosa. Eso a menudo descubre una o más formas completamente nuevas de romper las cosas.
Intento usar Diseño por contrato tanto como sea posible. Pero me parece que rara vez es práctico en mi campo de trabajo.
Me gusta el método del segundo par de ojos : después de haber escrito y probado algunos códigos críticos, a veces le pido a un compañero de trabajo que lo revise específicamente con la intención de buscar formas de romperlo.
Es divertido resaltar la creatividad de las personas de esta manera. :-)
Parece que ya tienes estos dos abajo:
Fallar rapido. http://en.wikipedia.org/wiki/Fail-fast
A prueba de fallos. http://en.wikipedia.org/wiki/Fail-safe
Estos tres probablemente me sirvan mejor que cualquier otro:
Evita el estado siempre que sea posible. Cree y use objetos inmutables: son más fáciles de probar y menos propensos a traicionarlo.
No escriba código innecesario. Este es difícil. Consulte la reciente proliferación de artículos relacionados con " Los elementos del estilo " de Strunk and White para la programación.
Pregúntate a ti mismo cada 10 minutos más o menos: "¿Esto es tonto?" Se honesto. Este es más difícil.
-Jason
Ser paranoico es un rasgo de supervivencia para los programadores. Constantemente pregúntese cómo puede fallar esto. Luego intente descubrir cómo prevenir esa falla.
Soy fanático de no inicializar variables locales. Deben establecerse cuando sea necesario. De lo contrario, los programadores que lean su código podrían confundirse como en "hmm why is this 0 at the beginning..."
. Si no lo inicializa, está claro que aún no se utilizó.
Soy un fanático de las técnicas descritas en " The Pragmatic Programmer ". También uso TDD , en lugar de DBC, ya que lo encuentro más flexible y productivo. Por ejemplo, algunas de las técnicas descritas en ''pragprog'' incluyen:
- Prueba a menudo. Prueba temprano. Prueba Automáticamente
- No te repitas
- Usa Sabotuers para probar tus pruebas
- Use Excepciones para problemas excepcionales
- No vivas con ventanas rotas
- No use procedimientos manuales
Todos parecen tener sentido común, pero es sorprendente la rapidez con que los equipos se desvían de estos principios subyacentes cuando se enfrentan a fechas límite.
Implemento una variedad de métodos para prevenir y recuperar errores:
1) Maneje todas las excepciones. Como dijiste, "maneja cada error". Si un usuario hace clic en un botón en un formulario, no debería haber ninguna posibilidad de que la aplicación simplemente desaparezca ("poof") de una excepción no controlada. Por esa razón, envuelvo a los manejadores de eventos con una captura de prueba genérica.
2) Errores de registro con seguimiento de pila completo. Cuando vuelvo a lanzar una excepción, siempre creo una nueva y agrego la excepción atrapada como una excepción interna. Mi código de registro desenrolla los mensajes recursivamente, lo que da un poco más de detalle de lo que hubiera hecho de otra manera.
3) Decida si sus clases serán reutilizables o no. Si no documentarlo. Considere implementar una interfaz en su código, algo como IRestartable
o IReusable
. Cualquier objeto que no lo implemente debe desecharse después de que se haya usado una vez.
4) Nunca asuma la seguridad del hilo. Aprendí por las malas que .NET es extremadamente multi-hilo. Muchos eventos se manejan en hilos arbitrarios. Una aplicación determinada escrita en .NET podría tener muchos subprocesos simultáneos ejecutándose y no tener una sola línea de código creando explícitamente uno.
5) Mantenga el alcance variable lo más estrecho posible. Crea una instancia de objetos cerca de donde se usan en lugar de en un bloque grande al comienzo de un método. Posiblemente acortarás la vida útil de los objetos y no te olvidarás de las variables innecesarias o reutilizadas que se encuentran en un bloque enorme en la parte superior de la clase o método.
5) Simple, pero todavía veo que está sucediendo. Evita los globales como la peste. He visto código con cientos de variables no utilizadas / reutilizadas. Fue un desastre descubrir y refactorizar.
Los sistemas que escribo (en C) tienen altos requisitos en cuanto a rendimiento y confiabilidad. Diseñar para el fracaso está bien. Cuando se trata de diseño, las cosas seguras se vuelven más complicadas.
El hardware siempre puede fallar y, aparte de eso, tiene el problema de que los datos no válidos ingresen al sistema desde afuera. Mis soluciones en esas áreas generalmente serán elaboradas (diseño seguro) y en prácticamente todas las demás áreas el diseño falla, ya que básicamente tiene un código extremadamente simple y no tiene validación de datos.
Por lo tanto, podría decir que diseño para el fracaso cuando los riesgos son pequeños y son seguros cuando están altos.
Para la depuración, a veces escribo un código condicional que nunca se debe ingresar, que contiene una división por cero o algo así para que cuando el procesamiento ingrese allí, el depurador se invocará inmediatamente.
Por lo general, no inicializo las variables de la pila local, ya que el compilador me dice cuáles deben inicializarse y cuáles pueden omitirse por completo.
Las revisiones de código son geniales pero no a prueba de tontos. Una vez pasé varias horas mirando un ciclo pequeño (infinito) (embarazoso, ¿no?) Y no pude ver que el índice no se incrementó. Mi colega tampoco lo vio. Cuando finalmente miré la lista del código generado, vi que las pruebas de bucle habían sido optimizadas para un solo salto incondicional y solo entonces entendí cuál era el problema.
Me gusta ... documentar los valores límite en (java) doc . (¿Puede un parámetro estar vacío? ¿Ser nulo?)
De esa manera, cuando se usa mi código (o cuando uso mi propio código), sé lo que puedo esperar. Recomendación simple, pero tan rara vez implementada;)
Esa documentación también incluye una clara separación de excepciones estáticas y de tiempo de ejecución . De esta forma, si el programa falla tan pronto como sea posible para mejorar la robustez, sé si falla debido a una excepción prevista (estática, debe tratarse en el momento de la codificación a través de un catch o un re-throw), o si se debe a parámetros incorrectos (excepciones de tiempo de ejecución, que solo se detectan durante la vida útil de la aplicación).
Si ambos tipos de excepción están claramente documentados (especialmente cuando se trata de valores límite para los parámetros), la solidez general es más fácil de aplicar.