Cómo conquistar el código heredado

En algún momento de su carrera como desarrollador, su jefe le entregará un fragmento de código heredado, código que alguien más escribió hace mucho tiempo. Su jefe le dirá que aprenda este código heredado, lo corrija y le agregue nuevas funciones.

He estado en esta situación muchas veces durante las últimas dos décadas. Puedo ayudar.

Cómo entender el código heredado

Si tiene suerte, tendrá documentación, o al menos comentarios en línea. Quizás uno o dos de los autores originales aún estén presentes para ayudar. Pero la mayoría de las veces, no tendrás tanta suerte.

Hablemos de lo que vas a hacer en esos casos desafortunados.

Primero, debes ser humilde. Respete el código y los desarrolladores que lo escribieron.

Es fácil mirar el trabajo que le precedió y decidir que no es bueno y que puede hacerlo mejor. Ésta es la actitud incorrecta. Te llevará por un camino muy peligroso.

Si sigue este camino peligroso, comenzará a realizar cambios antes de comprender adecuadamente el impacto de esos cambios. "Arreglarás" las cosas que no están rotas, porque están escritas en un estilo que no te gusta, o están basadas en una forma más antigua de hacer las cosas. Al final, perderá una cantidad increíble de tiempo con esta actitud.

Así que deja de. Da un paso atrás y date cuenta de que todo en esa base de código se hizo de cierta manera por una razón.

Hasta que conozca el código hacia adelante y hacia atrás, debe asumir que había buenas razones para que se escribiera como está y que aún no las ha descubierto.

Esta es una actitud mucho más productiva y te evitará romper todo y luego simplemente querer saltar por la ventana cuando no puedas volver a armarlo lo suficientemente rápido.

No Humpty Dumpty su código base.

La mejor manera que he encontrado para aprender una base de código es comenzar en el nivel de la interfaz de usuario y luego volver al código.

Elija un flujo de usuario único, como iniciar sesión, realizar un pedido, escribir una reseña o lo que sea relevante para su aplicación en particular. Siga el flujo como usuario final. Luego, mire el código, comenzando con el código de la interfaz de usuario (debería ser el más fácil de reconocer) y siga cada paso hacia atrás hasta la base de datos.

A medida que avanza, dibuje un diagrama de secuencia para ayudar a ilustrar lo que está sucediendo. Si no está seguro de qué es un diagrama de secuencia o cómo dibujar uno, consulte este tutorial gratuito. Si no tiene una buena herramienta para dibujar UML, aquí tiene una gratis.

Una vez que haya completado su primer diagrama de secuencia, utilizando una copia local de la base de código que puede restaurar fácilmente, comience a realizar cambios sutiles en algunos de los componentes que ha encontrado. Vea si puede predecir los efectos de sus cambios en la aplicación. Ésta es una buena forma de poner a prueba su comprensión.

Siga repitiendo este proceso, agregando a sus diagramas hasta que tenga una imagen completa de toda la aplicación (o al menos todas las partes de las que es responsable).

Para obtener puntos de bonificación, asegúrese de compartir sus notas y diagramas. Colóquelos en un lugar muy visible donde el próximo desarrollador que se presente pueda descubrirlos fácilmente. No se preocupe por hacerlos perfectos, o incluso bonitos. Solo haz lo que puedas. Cada poquito ayuda.

En general, lo más importante es ser paciente y evitar golpearse. El código es algo complejo. Comprender el código heredado lleva tiempo. Mantén la calma.

Cómo corregir el código heredado

El mayor desafío al que se enfrentará al corregir el código heredado es decidir hasta dónde llegar con su solución. Le recomiendo encarecidamente que primero haga el cambio mínimo viable . Esto significa que debe realizar el cambio menos disruptivo que solucione por completo el problema antes de intentar limpiar y refactorizar cualquier código.

Esto le da una trampilla de escape. En el peor de los casos, si lo apartan para abordar alguna otra prioridad, o si tiene una fecha límite ajustada, al menos habrá reunido un código de trabajo al que puede recurrir.

Una vez que haya conseguido que su código funcione, si aún le queda tiempo, puede empezar a realizar pequeñas mejoras incrementales.

Martin Fowler ha elaborado un catálogo de refactorizaciones que le darán una buena idea de los tipos de cambios que puede realizar para mejorar gradualmente una base de código. Compruébalo aquí. La idea es dejar siempre el código en mejor forma que cuando lo encontró.

A veces, encontrará un error que en realidad es el resultado de un defecto estructural. Estos errores no se pueden solucionar con un simple cambio a alguna lógica condicional. Requieren cambios más invasivos.

Aquí es donde las cosas se ponen feas. Tienes que ser brutalmente honesto contigo mismo sobre cuál es el cambio mínimo viable. Cada fibra de tu ser querrá separar el código y reescribirlo todo. ¡No lo hagas!

Cíñete a una solución rápida, seguida de una mejora incremental que la refactorice y limpie tanto como el tiempo lo permita. Tu objetivo es mejorar el código cada vez. Cuanto más tiempo mantenga el código base, mejor será.

Para que este enfoque realmente funcione, asegúrese de estar siempre rellenando sus estimaciones para dar tiempo a un poco de refactorización.

A veces, los defectos estructurales son tan graves que una estrategia de parcheo permanente simplemente no funcionará. En realidad, esta situación es mucho más rara de lo que piensas.

Nuevamente, debes ser brutalmente honesto contigo mismo sobre el costo / beneficio de una reescritura o rediseño. Debe aceptar que, en última instancia, esta será una decisión comercial y no técnica.

Prepárese para exponer su caso en términos comerciales. ¿Cuánto costará hacer una reestructuración importante del código? ¿Cuáles son los riesgos comerciales reales de no hacerlo? Si tiene un caso sólido, eventualmente será escuchado. Sin embargo, no se sorprenda si primero se necesitan algunos ciclos más de parcheo.

Recuerde: si está realizando una revisión importante, primero asegúrese de que haya apoyo para el cambio y un presupuesto razonable que lo acompañe. No intentes pasar desapercibido con esto. A menos, por supuesto, que disfrute de las conversaciones incómodas con la gerencia cuando comience a romper cosas y a no cumplir con los plazos.

Cómo agregar nuevas funciones al código heredado

Finalmente, eventualmente se le pedirá que agregue funciones al código heredado. En este punto, debe tomar una decisión importante. ¿Sigues el flujo del código base actual o tomas las cosas en una nueva dirección?

Nuevamente, le aconsejo que sea brutalmente honesto en su evaluación. ¿Continuar siguiendo los patrones y prácticas evidentes en el código base existente lo empeoraría o se acumularía en un problema existente?

La mayoría de las veces, querrá mantener las cosas estables. Simplemente realice adiciones incrementales utilizando los patrones y prácticas existentes del código. Reutilice elementos existentes. Realice los cambios menos perturbadores posibles, mientras realiza pequeñas mejoras incrementales mediante la limpieza y la refactorización.

Si cree que una nueva dirección es absolutamente necesaria, entonces deberá encontrar una manera de aislar sus cambios y acoplarlos lo más libremente posible al código base existente.

Intente crear la nueva función como un proyecto independiente. Luego, puede exponer una API que permite que el código heredado se conecte a su nuevo código. Esto hace que su nuevo código y el antiguo código heredado no necesiten saber mucho el uno del otro.

Esto comienza a ser un poco complicado cuando necesita usar la funcionalidad del código heredado para implementar la nueva función. La mejor forma de aislar el código antiguo del código nuevo es utilizar el patrón de adaptador.

DO Factory tiene una buena explicación del patrón del adaptador:

“El patrón Adaptador traduce una interfaz (las propiedades y métodos de un objeto) a otra. Los adaptadores permiten que los componentes de programación funcionen juntos que de otro modo no lo harían debido a interfaces no coincidentes. El patrón de adaptador también se conoce como el patrón de envoltura. Un escenario en el que los adaptadores se utilizan comúnmente es cuando los nuevos componentes necesitan integrarse y trabajar junto con los componentes existentes en la aplicación. Otro escenario es la refactorización en la que partes del programa se reescriben con una interfaz mejorada, pero el código antiguo todavía espera la interfaz original ".

Aquí hay algunos enlaces a explicaciones y ejemplos en varios idiomas.

  • Ejemplo de JavaScript del patrón de adaptador
  • Ejemplo de C # del patrón de adaptador
  • Ejemplo de Java del patrón de adaptador

Conclusiones clave

En resumen, estos son los puntos clave que lo ayudarán a abordar y finalmente conquistar cualquier base de código:

  1. Nunca juzgue el código heredado ni lo cambie hasta que se haya tomado el tiempo de comprenderlo por completo.
  2. Los diagramas de secuencia son tus amigos.
  3. Prefiera mejoras pequeñas e incrementales sobre reescrituras o cambios al por mayor.
  4. Cada cambio debe intentar dejar el código un poco mejor de lo que estaba cuando lo encontró.
  5. Si necesita hacer grandes cambios, haga un caso comercial y obtenga la aprobación primero.
  6. Cuando agregue nuevas funciones, intente "seguir la corriente".
  7. Si necesita llevar el código en una nueva dirección, aísle sus cambios y use el Patrón de Adaptador para integrar.

Esperamos que este artículo le haya resultado útil. Mi misión es ayudar a tantos desarrolladores como pueda. Por favor ❤ recomiende ❤ esta historia usando el corazón verde a continuación para ayudar a correr la voz.

¿Quiere codificar mejor? Únase a miles de desarrolladores que reciben de mí artículos valiosos e información como esta todas las semanas de forma gratuita . Haga clic aquí.