Introducción
Imagina que estás trabajando con código antiguo con el que trabajar. Ha sido escrito por mucha gente, por mucho tiempo. Puedes encontrar las mejores y las peores soluciones, con diferentes estilos. Partes grandes de dicho código, o pequeñas, pueden ser descubiertas por pruebas unitarias. Puedes oler a naftalina por aquí y por allá. Ese código antiguo puede tener un mayor impacto en eficiencia, flexibilidad, pruebas, etc. Después de un momento, puedes tener muchas ideas de como probar o deshacerte de ese código. Bien ... ¡no lo toques!
¿Porqué deberías dejarlo como está?
Considera lo siguiente:
- Funciona: mejor o peor, pero funciona. Es claro que podrías hacer cualquier cosa que funcione mejor, pero tu tiempo es limitado y tienes una lista de nuevas características a implementar y también una lista de errores que reparar. Hay una falta de pruebas unitarias. Puede ser, pero alguna prueba ha pasado y es la prueba del tiempo. Aparte del tema de eficiencia, podrías decir que si refactorizas el código será más flexible, más fácil de aprender y nuevas características podrán agregarse más rápido. Es verdad. Sin embargo, eso garantiza que ...
- Introducirás más errores: jugar con código antiguo es como jugar con la ruleta rusa. Tarde o temprano introducirás un error que aparecerá en la demo ante tu cliente y nadie prestará atención a las grandiosas mejoras invisibles que has agregado. No puedes estar seguro de nada. Veamos un par de ejemplos. Digamos que no ves ninguna referencia al código al que le has puesto la mira. Quítalo y veamos. La aplicación funciona ... hasta que encuentras que un archivo XML externo fuera del entorno utiliza ese código eliminado en alguna rara pero crucial circunstancia y ahora obtienes una excepción en tiempo de ejecución que no te dice nada o incluso peor: la excepción es atrapada en un bloque try catch y te deja pensar que todo funciona bien. Puede parecer una buena idea relanzar excepciones en vez de manejarlas. Si, pero entonces empezarías a recibir excepciones en tiempo de ejecución de todo tipo desde lo más profundo del código de la aplicación. La gente que utiliza tu aplicación también las recibe, y claro está que eres tú quien malogró la aplicación porqué no había esos mensajes de error hasta que tocaste el código. Está bien, al menos has creado una nueva política de manejo de excepciones, que antes no había. En realidad, no tienes tiempo para eso. Pero, incluso, si tienes el tiempo ...
- Tu pequeño cambio disparará una avalancha de cambios. Si el código antiguo involucra un sistema amplio, y eres el chico nuevo, encontrarás más dependencias de las que pensaste. Ahora, tomando eso en cuenta es probable que seas demasiado optimista y pidas a tu jefe menos tiempo de lo que realmente necesitas (tal vez conscientemente para no asustarlo), y tu jefe te de menos tiempo del que pediste y el problema real requiere más tiempo del que pensaste. Eso termina en que tienes un gran problema en tus manos.
¿Cómo trabajar con código antiguo?
Es una pregunta abierta y depende del código base que enfrentes. Te doy algunas pistas que funcionaron en algún momento para mi:
- Evita cambiar código existente. Trátalo como una caja negra y sigue el principio de abierto-cerrado. Prueba extender el código existente hasta donde sea posible en vez de modificarlo.
- Agrega nuevo código encima del existente. Prueba minimizar los lugares donde el nuevo código es enganchado. Si algo va mal, puedes retirar el código nuevo y revisar el origen de los problemas.
- Mantén el código nuevo separado del antiguo. Digamos que es un nuevo método, una clase con una única responsabilidad, un adaptador en vez de nuevos bucles o lógica de control dentro de una vieja función. Podría ser fácil de diferenciar lo que es nuevo y puede ser refactorizado, modificado, mejorado y lo que es viejo y debería dejar intacto.
Siguiendo éstas líneas guía tendrás un núcleo de la aplicación basado en código antiguo que ha sobrevivido el paso del tiempo, a la vez que nuevo, flexible, legible y probado nuevo código construido sobre el viejo.
Una estrategia diferente reside en el hecho que el programador intenta camuflar su código con el antiguo, de modo que es muy similar y la fuente es homogénea. La desventaja es que esto fuerza al desarrollador a internarse en las funciones ya existentes que son imposibles de comprobar. Cambia totalmente la estimación del tiempo y no hay la seguridad de que funcione. Crea código rígido e ilegible. Introduce más lógica de control de flujo de la información. No agrega nada positivo en favor de una futura factorización.
La estrategia de refactorización introduce nuevos errores. Puede crear un mejor código, pero existe el riesgo de llegar a un estado en donde el código es confuso, tener un montón de nuevos errores y una línea de tiempo donde el final de la refactorización se aleja cada día más.
0 comentarios:
Publicar un comentario