2011-01-21 24 views
33

Necesito algunos consejos sobre cómo trabajar con el código heredado.Consejos para trabajar con el código heredado

Hace un tiempo, me dieron la tarea de agregar algunos informes a una aplicación de informes. escrito en Struts 1, en 2005. No es gran cosa, pero el código es bastante desordenado. No se usan formularios de Acción, y básicamente el código es una acción enorme, y muchas declaraciones if-else adentro. Además, nadie aquí tiene conocimiento funcional sobre esto. Por casualidad lo tenemos en nuestro contrato.

Estoy bastante descontento con esto, y no estoy seguro de cómo proceder. Esta aplicación es invisible: pocas personas (pero todas muy importantes) la usan, por lo que no les importa si mis ojos sangran mientras leen el código, los estándares, etc.

Sin embargo, creo que una deuda técnica debe ser pagado. ¿Cómo debo proceder en esto? Continuar por la carretera if-else, o tratar de hacer este requisito de la manera correcta, haciendo caso omiso del resto del proyecto? ¿Comenzar un enorme refactor arriesgando mi fecha límite?

+9

http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052 –

+0

@Dave Sí, mi empresa ha comprado, pero uno de los grandes nombres lo tiene. Triste historia :( – Tom

+0

así que compre su propia copia. –

Respuesta

44

El código heredado es un gran problema, y ​​estoy seguro de que la gente no estará de acuerdo.

Yo diría que comenzar un gran cambio de factor podría ser un error.

Un gran cambio de factor significa hacer mucho trabajo para hacerlo funcionar exactamente como lo hace ahora. Si eliges hacer esto por tu cuenta, no habrá mucha visibilidad de lo que estás haciendo. Si funciona, nadie sabrá las horas de trabajo que le dedicas. Si NO funciona, y usted termina con el código ordenado, pero agrega algunos errores (y quién alguna vez ha escrito el código sin agregar algunos errores), entonces obtendrá preguntas del tipo "por qué cambió esto".

Actualmente, casi he completado un proyecto que trabaja con una base de código de 10 años. Hemos hecho bastantes piezas de refaccionamiento en el camino. Pero por cada nuevo factor que hayamos hecho podemos justificar que 'este cambio específico hará que la tarea real que estamos haciendo ahora sea más fácil'. En lugar de "esto ahora es más limpio para el trabajo futuro". Hemos descubierto que a medida que trabajamos en el código, solucionando los problemas que enfrentamos de a uno por vez, hemos limpiado una gran cantidad, sin romperlo (mucho).

Y yo diría que antes de que puedas volver a factorizar mucho, necesitarás pruebas automatizadas, por lo que puedes estar bastante contento de haberlo armado de nuevo.

La mayor parte del refaccionamiento se hace para 'facilitar el mantenimiento y el desarrollo futuro'. Su proyecto parece que no hay mucho desarrollo futuro por venir. Eso limita la ventaja que un nuevo factor le dará a la compañía.

+0

Tiene un buen punto, este proyecto está congelado la mayor parte del tiempo. – Tom

+0

"Y yo diría que antes de que pueda volver a factorizar mucho, necesitará pruebas automáticas, por lo que puede estar bastante contento de haberlo restablecido". ¿Qué sucede si su base de código requiere cambios significativos para respaldar las pruebas unitarias? – NeverEndingQueue

+0

Mi opinión? Debes demostrar que el re-factor no rompió nada. ¿Cómo lo harás? Las pruebas manuales pueden ser mejores que las automatizadas ... Si la automatización tardará demasiado. He encontrado que las pruebas automatizadas son muy costosas cuando se trabaja con la integración de VMware – Jon

12

Regla # 1: Si no está roto, no lo arregles.

Regla # 2: En caso de duda, vuelva a leer la regla n. ° 1.

Desafortunadamente, el código heredado rara vez se puede describir como "no está roto". Por lo tanto, debemos modificar el código existente para corregir un error recién descubierto, modificar el código existente para modificar el comportamiento que era previamente aceptable, o ajustar el código existente para agregar nuevas funcionalidades.

Mi experiencia me ha enseñado que cualquier refactorización debe hacerse en pequeños incrementos 'infinitesimalmente'. Si debe violar la regla n. ° 2, le sugiero que comience la búsqueda con el bucle anidado más interno o la estructura IF y se expanda hacia afuera hasta que encuentre un punto de separación limpio y lógico y cree una nueva función/método/subrutina que contenga solo el agallas de ese bucle o estructura. Esto no hará que todo sea más eficiente, pero debería brindarle una visión más clara de la lógica y estructura subyacente. Una vez que tenga varias funciones/métodos/subrutinas más pequeñas y nuevas, puede refactorizarlas y consolidarlas en algo más manejable.

Regla # 3: Ignora mi párrafo anterior y vuelve a leer las dos primeras reglas.

3

Estoy de acuerdo con otros comentarios. Si no tienes que hacerlo, entonces no lo hagas. Por lo general, cuesta mucho más de lo que vale si la base de código está más o menos muerta de cualquier manera.

Por otro lado, si sientes que no puedes entender el código, entonces un refactor es probablemente inevitable. Si este es el caso, dado que es una aplicación web, ¿puedes crear un conjunto sólido de pruebas funcionales con selenio? Si es así, este es el enfoque de prueba más rápido y más gratificante para dicho código y atrapará a la mayoría de los errores por el dinero.

En segundo lugar, comience con la refactorización del método de extracción para crear métodos de composición de los grandes métodos difíciles. Cada vez que piense "Esto debería tener un comentario para explicar lo que hace", debe extraerlo a un método con un nombre que reemplace el comentario.

Una vez hecho esto, si aún no puede agregar la funcionalidad requerida, puede optar por refactorizaciones más avanzadas y quizás incluso agregar algunas pruebas de unidad. Pero normalmente encuentro que puedo agregar lo que se requiere/corregir el error en el código heredado simplemente creando un código de auto documentación.

+0

¡Me cuesta un trabajo! –

3

En pocas palabras: antes de realizar modificaciones en el código heredado, es una buena idea comenzar con las pruebas unitarias automáticas. Esto le dará al desarrollador la comprensión de las cosas clave: dependencias que tiene este fragmento de código, datos de entrada, resultados de salida, condiciones de contorno, etc.

Cuando haya terminado, lo más probable es que comprenda mejor qué hace este código y cómo funciona.

Después tiene sentido (pero no debe) limpiar el código un poco dando nombres más precisos a las variables locales, moviendo algunas funciones (código repetitivo, si hay) a funciones con nombres claros y amigables para el ser humano.

Una simple limpieza podría hacer que el código sea más legible y, al mismo tiempo, ahorrar al desarrollador problemas de regresión con la ayuda de las pruebas unitarias.

Refactorización: realice pequeños cambios, paso a paso, cuando tenga un tiempo y comprenda los requisitos y la funcionalidad, regularmente pruebe el código por unidades.

Pero no empezar de refactorización

+0

No es frecuente que haya encontrado algún código heredado que requiera que este tipo de refactorización sea comprobable en cualquier nivel razonable ... – Joe

Cuestiones relacionadas