Quiero hacer algunas mejoras en un código aún funcional que se escribió hace mucho tiempo, antes de que el lenguaje de programación en el que está escrito creciera en características. En teoría, todo el proyecto utiliza la versión actualizada del lenguaje; sin embargo, este módulo en particular (y de hecho, muchos otros módulos) todavía están escritos en el dialecto anterior.
Debería:
- ¿No tocar las partes del código que no tengo que tocar, pero escribir mi parche haciendo uso de las nuevas características del lenguaje que hacen que sea más fácil escribir el parche pero que no se usan en situaciones análogas en ningún otro lugar del módulo? (Esta es la solución que elegiría intuitivamente).
- ¿Ignora el hecho de que han pasado años y refleja el estilo que se usa en el resto del código al escribir mi parche, comportándose efectivamente como si estuviera haciendo la misma tarea muchos años antes? (Esta solución la consideraría tontamente intuitivamente, pero dada la cantidad de alboroto que todos los que hablan sobre el "buen código" se preocupan por mantener la coherencia a toda costa, tal vez esto es lo que debería hacer).
- ¿Actualizar todo el módulo para usar las nuevas construcciones y convenciones del lenguaje? (Esta es probablemente la mejor solución, pero puede requerir mucho tiempo y energía que podría gastarse mejor en una tarea diferente).
programming-practices
maintenance
gaazkam
fuente
fuente
Respuestas:
Es imposible dar una respuesta definitiva a esta pregunta, porque depende demasiado de los detalles de la situación.
La coherencia en el estilo de la base de código es importante porque ayuda a facilitar la comprensión del código, que es uno de los aspectos más importantes de la mantenibilidad.
No serías el primer programador que fue maldecido por hacer que el código fuera difícil de entender al mezclar diferentes estilos. Incluso podrías ser tú mismo quien maldiga en años.
Por otro lado, el uso de nuevas construcciones de lenguaje que no existían cuando se escribió el código por primera vez no implica automáticamente que esté reduciendo la capacidad de mantenimiento o incluso que esté rompiendo el estilo del código. Todo eso depende de las características del idioma en particular que desee usar y de cuán familiarizado esté el equipo con el estilo antiguo del código y las nuevas características.
Como ejemplo, generalmente no sería aconsejable comenzar a introducir conceptos de programación funcional como map / reduce a una base de código que esté completamente en estilo OO, pero podría funcionar agregar una función lambda aquí y allá a un programa que no utilizó algo así antes.
fuente
En gran medida, el código y cómo se ve es irrelevante . Lo que el código hace es lo que importa.
Si puede garantizar que cambiar / reescribir el código no cambiará lo que hace el código, entonces puede continuar y refactorizar el código al contenido de su corazón. Esa "garantía" es un conjunto exhaustivo de pruebas unitarias que puede ejecutar antes y después de sus cambios, sin una diferencia perceptible.
Si no puede garantizar esa estabilidad (no tiene esas pruebas), entonces déjelo bien solo.
Nadie le agradecerá por "romper" una pieza de software crítico para el negocio, incluso si estaba tratando de hacerlo "mejor". "Trabajar" triunfa "mejor" cada vez.
Por supuesto, no hay nada que lo detenga para crear un conjunto de tales pruebas en preparación para tal ejercicio ...
fuente
Casi cualquier cosa puede analizarse en términos de costos y beneficios, y creo que esto se aplica aquí.
Los beneficios obvios de la primera opción son que minimiza el trabajo a corto plazo y minimiza las posibilidades de romper algo al reescribir el código de trabajo. El costo obvio es que introduce inconsistencia en la base del código. Cuando realiza alguna operación X, se realiza de una manera en algunas partes del código, y de una manera diferente en una parte diferente del código.
Para el segundo enfoque, ya ha notado el beneficio obvio: consistencia. El costo obvio es que tiene que inclinarse para trabajar de maneras que de otro modo hubiera abandonado hace años, y el código sigue siendo ilegible constantemente.
Para el tercer enfoque, el costo obvio es simplemente tener que hacer mucho más trabajo. Un costo menos obvio es que puede romper cosas que estaban funcionando. Esto es particularmente probable si (como suele ser el caso) el código anterior tiene pruebas inadecuadas para asegurar que continúe funcionando correctamente. El beneficio obvio es que (suponiendo que lo haga con éxito) tiene un nuevo código agradable y brillante. Junto con el uso de nuevas construcciones de lenguaje, tiene la oportunidad de refactorizar la base del código, lo que casi siempre proporcionará mejoras en sí mismo, incluso si todavía usó el lenguaje exactamente como existía cuando se escribió: agregue nuevas construcciones que hagan que el trabajo más fácil, y bien puede ser una gran victoria.
Sin embargo, otro punto importante: en este momento, parece que este módulo ha tenido un mantenimiento mínimo durante mucho tiempo (a pesar de que el proyecto en su conjunto se mantiene). Eso tiende a indicar que está bastante bien escrito y relativamente libre de errores; de lo contrario, probablemente habría sufrido más mantenimiento mientras tanto.
Eso lleva a otra pregunta: ¿cuál es la fuente del cambio que está haciendo ahora? Si está arreglando un pequeño error en un módulo que en general aún cumple con sus requisitos, eso indicaría que el tiempo y el esfuerzo para refactorizar todo el módulo probablemente se desperdicien en gran medida, para cuando alguien necesite meterse con nuevamente, es muy posible que estén en la misma posición que usted ahora, manteniendo un código que no cumple con las expectativas "modernas".
Sin embargo, también es posible que los requisitos hayan cambiado, y usted está trabajando en el código para cumplir con esos nuevos requisitos. En este caso, es muy probable que sus primeros intentos no cumplan con los requisitos actuales. También hay una posibilidad sustancialmente mayor de que los requisitos se sometan a algunas rondas de revisión antes de que se estabilicen nuevamente. Eso significa que es mucho más probable que esté haciendo un trabajo significativo en este módulo a corto plazo (relativamente), y es mucho más probable que realice cambios en el resto del módulo, no solo en el área que conoce bien ahora. En este caso, es mucho más probable que la refactorización de todo el módulo tenga beneficios tangibles a corto plazo que justifiquen el trabajo adicional.
Si los requisitos han cambiado, es posible que también necesite ver qué tipo de cambio está involucrado y qué está impulsando ese cambio. Por ejemplo, supongamos que estaba modificando Git para reemplazar su uso de SHA-1 con SHA-256. Este es un cambio en los requisitos, pero el alcance está claramente definido y es bastante limitado. Una vez que haya hecho que se almacene y use SHA-256 correctamente, es poco probable que encuentre otros cambios que afecten al resto de la base de código.
En la otra dirección, incluso cuando comienza pequeño y discreto, un cambio en una interfaz de usuario tiende a aumentar, por lo que lo que comenzó como "agregar una nueva casilla de verificación a esta pantalla" termina más como: "cambie esta IU fija para admitir plantillas definidas por el usuario, campos personalizados, esquemas de colores personalizados, etc. "
Para el primer ejemplo, probablemente tenga más sentido minimizar los cambios y errar por el lado de la coherencia. Para este último, la refactorización completa es mucho más probable que valga la pena.
fuente
Iría por tu primera opción. Cuando codifico, sigo la regla para dejarlo en un mejor estado de lo que era.
Entonces, el nuevo código sigue las mejores prácticas, pero no tocaré código que no esté relacionado con los problemas en los que estoy trabajando. Si lo hace bien, su nuevo código debería ser más fácil de leer y mantener que el código anterior. Descubrí que la mantenibilidad total mejora, porque si sigues así, el código que debes tocar para tu trabajo es cada vez más el código "mejor". Lo que lleva a una resolución de problemas más rápida.
fuente
La respuesta, como tantas otras cosas, es que depende . Si existen ventajas importantes para actualizar las construcciones más antiguas, como una capacidad de mantenimiento a largo plazo enormemente mejorada (evitando el infierno de devolución de llamadas, por ejemplo) que lo haga. Si no hay una gran ventaja, la consistencia es probablemente tu amigo
Además, también querrá evitar incrustar dos estilos en la misma función más de lo que desearía evitarlo dentro de dos funciones separadas.
En resumen: su decisión final debe basarse en un análisis de "costo" / "beneficio" de su caso particular.
fuente