¿Cómo saben ustedes que está escribiendo el código más robusto posible sin ingeniería excesiva?
Me encuentro pensando demasiado en cada camino posible que puede tomar mi código, y a veces parece una pérdida de tiempo. Supongo que depende del tipo de programa que esté escribiendo, pero no quiero usar mucho de mi tiempo teniendo en cuenta situaciones que nunca sucederán.
self-improvement
programming-practices
Fran Sevillano
fuente
fuente
Respuestas:
¿Qué consideras código robusto? ¿Código que ya es prueba de futuro y tan poderoso que puede manejar cualquier situación? ¡Incorrecto, nadie puede predecir el futuro! Y mal otra vez, porque será un desastre complicado e imposible de mantener.
Sigo varios principios: en primer lugar, YAGNI (todavía) y KISS , por lo que no escribo código innecesario. Eso también previene eficazmente la sobreingeniería. Refactorizo la aplicación cuando se necesitan extensiones. Las modernas herramientas de refactorización le permiten crear interfaces e intercambiar implementaciones con bastante facilidad cuando las necesite.
Luego trato de hacer que el código que escribo sea lo más robusto posible, eso incluye eliminar tantas rutas que el programa pueda tomar (y también estados) como sea posible y un poco de programación espartana . Una gran ayuda son las funciones / métodos "atómicos" que no dependen de estados externos o al menos no dejan el programa en un estado inconsistente cuando fallan. Si lo haces bien, también es muy poco probable que alguna vez termines con un código de espagueti y también es una bendición para el mantenimiento. Además, en el diseño orientado a objetos, los principios SÓLIDOS son una gran guía para un código robusto.
Realmente descubrí que muchas veces puedes reducir la complejidad, por ejemplo, las explosiones combinatorias de las rutas o estados del programa, al pensar profundamente en cómo podrías diseñarlo como la ruta más directa posible. Intente mantener las combinaciones posibles al mínimo eligiendo el mejor orden de sus subrutinas y diseñándolas para este propósito.
El código robusto es siempre un código simple y limpio, pero la simplicidad es un rasgo que no siempre se logra fácilmente. Sin embargo, debes luchar por ello. Siempre escriba el código más simple posible y solo agregue complejidad cuando no tenga otra opción.
La simplicidad es robusta, la complejidad es frágil.
La complejidad mata.
fuente
Intento mantener un equilibrio, centrándome en
Es un área fronteriza borrosa: a veces logro hacer un trabajo innecesario, a veces no puedo hacer algo que resulta necesario más tarde. Si las fallas no son grandes, estoy bien. En cualquier caso, me esfuerzo por aprender de mis errores.
fuente
La diferencia entre robustez y sobre ingeniería es la diferencia entre manejar con gracia todos los casos de uso posibles, incluso los casos de uso extraños y marginales que NO DEBEN suceder. Cuando digo con gracia quiero decir, el usuario ingresa en un extraño caso de excepción o se encuentra con una situación que requiere una característica no admitida o no especificada que no se definió y el código sale sin fallar o informa al usuario de la funcionalidad no admitida.
La sobreingeniería, por otro lado, podría caer en el ámbito de la implementación completa de características que no fueron necesarias o solicitadas (¡algunas características que el cliente NECESITA pero nunca fueron solicitadas!) O puede definirse derivando un diseño demasiado complejo o demasiado complejo código para manejar un problema relativamente simple.
fuente
1) Obtenga requisitos.
2) Escriba el código mínimo para cumplir con los requisitos. Si algo es ambiguo, haga una suposición educada. Si es super ambiguo, regrese a 1.
3) Enviar a prueba.
4) Si los evaluadores dicen que es bueno, documente la aprobación. Si algo está apagado, regrese a 1.
Concéntrese en aprobar las pruebas, no en predecir las pruebas. Si no tienes probadores ... ¡obtén probadores! Son esenciales no solo para verificar la corrección del código, sino para todo el proceso de desarrollo.
fuente
En primer lugar, mantenga los datos normalizados (no redundantes) tanto como pueda. Si los datos están completamente normalizados, ninguna actualización única de los datos puede hacer que sean inconsistentes.
No siempre puede mantener los datos normalizados, en otras palabras, es posible que no pueda eliminar la redundancia, en cuyo caso puede tener estados inconsistentes. Lo que hay que hacer es tolerar la inconsistencia y repararla periódicamente con algún tipo de programa que lo abarque y lo repare.
Existe una fuerte tendencia a tratar de gestionar la redundancia de manera estricta mediante notificaciones. No solo es difícil asegurarse de que sean correctos, sino que pueden conducir a enormes ineficiencias. (Parte de la tentación de escribir notificaciones surge porque en OOP prácticamente se les alienta).
En general, cualquier cosa que dependa de la secuencia temporal de eventos, mensajes, etc., será vulnerable y requerirá toneladas de codificación defensiva. Los eventos y mensajes son característicos de los datos con redundancia, ya que están comunicando cambios de una parte a otra, tratando de evitar inconsistencias.
Como dije, si debe tener redundancia (y es muy probable que deba hacerlo), lo mejor es poder a) tolerar y b) repararlo. Si intenta evitar inconsistencias únicamente mediante mensajes, notificaciones, disparadores, etc., le resultará muy difícil hacerlo robusto.
fuente
aparecerán errores en el camino, pero (afortunadamente) serán localizados y (en la mayoría de los casos) aparecerán muy temprano en las pruebas. El otro beneficio de la reutilización es que el cliente / llamante puede guardar la mayor parte de la comprobación / andamiaje de errores utilizando lo que implica la implicación.
sus pruebas luego definirán las capacidades de su programa y qué tan robustas son: continúe agregando pruebas hasta que esté satisfecho con las tasas de éxito y las entradas; mejorando, extendiendo y fortificando según sea necesario.
fuente
Hago esta distinción escribiendo código con un comportamiento bien definido, pero no necesariamente óptimo, para pases de ejecución muy improbables. Por ejemplo, cuando estoy bastante seguro (probado, pero no probado) de que una matriz será positiva definida, inserto una aserción o excepción en el programa para probar el estado, pero no escribo una ruta de código propia para ella. De este modo, el comportamiento se define, pero subóptimo.
fuente
Robustez: El grado en que un sistema continúa funcionando en presencia de entradas inválidas o condiciones ambientales estresantes. (Código completo 2, p464)
La pregunta importante aquí es preguntar qué tan importante es la robustez para usted. Si es Facebook, es realmente importante que su sitio web continúe funcionando cuando alguien ingrese caracteres especiales en la entrada, y que su servidor permanezca activo cuando 100 millones de usuarios inicien sesión simultáneamente. Si está escribiendo un script para realizar una operación común que solo usted hace, no le importa mucho. En el medio hay muchos niveles. Juzgar sobre cuánta robustez necesitas es una de las habilidades importantes que un desarrollador debe aprender.
El principio de YAGNI se aplica a la adición de características que un programa podría necesitar. Pero ese principio no se aplica a la robustez. Los programadores tienden a sobreestimar la probabilidad de que se necesite una extensión futura dada (especialmente si es buena), pero subestiman la probabilidad de que las cosas salgan mal. Además, si resulta que se necesita una función omitida después, el programador puede escribirla más tarde. Si resulta que después de todo se necesita una verificación de error omitida, el daño puede estar hecho.
Por lo tanto, en realidad es mejor errar al hacer las comprobaciones de condiciones de error inusuales. Pero hay un equilibrio. Algunas de las cosas a considerar en este balance:
No olvide que las personas pueden, y lo harán, intentar usar su programa de maneras inesperadas. Es mejor si sucede algo predecible cuando lo hacen.
Como última línea de defensa, use la afirmación o el cierre. Si sucede algo que no puede resolver cómo lidiar con eso, cierre el programa. Eso suele ser mejor que permitir que el programa continúe y haga algo impredecible.
fuente