← Volver

Refinamiento continuo

Refinar continuamente el software mediante pequeñas mejoras de diseño, código, pruebas y despliegue facilita su mantenimiento y reduce el esfuerzo de incorporar nuevas funcionalidades.

Buenas PrácticasRefactoring

Antes de comenzar una nueva fase de desarrollo, conviene dedicar algo de tiempo a mejorar todo lo que ya hay.

La construcción de una pieza de código de calidad es un proceso incremental y nunca, absolutamente nunca, lo primero que escribes —aunque funcione— tiene la calidad que debe tener para asegurar su mantenibilidad.

Empieza a ser algo recurrente para mí encontrarme analizando proyectos que, por alguna razón, terminan siendo difíciles o imposibles de seguir evolucionando. No importa la tecnología que se use, aunque hay algunas que tradicionalmente han provocado una mayor cantidad de proyectos muy deteriorados; quiero decir, proyectos que terminan reescribiéndose desde cero. PHP, por ejemplo, tiende a esto, pero no por el lenguaje en sí, sino porque su curva de aprendizaje es tan fácil que, en poco tiempo, alguien que se inicia en el mundo de la programación consigue obtener algún resultado sin siquiera necesitar programación orientada a objetos. Con el tiempo, la aplicación va creciendo sin consolidar principios de diseño, buenas prácticas, una gestión de la configuración correcta ni código limpio. O sea, una auténtica pesadilla. La orientación a objetos tiende a forzar un diseño algo mejor, aunque este tema da mucho de sí.

A primera vista se puede sospechar si el diseño ha sido cuidado y revisado —si es que existe un «diseño» como tal y no un sistema excesivamente monolítico—, así como la estructura y calidad del código de cada método.

Ocurre exactamente igual que cuando escribes un relato: primero comienzas con un borrador (y sí, «funciona», en el sentido de que transmites la idea que quieres dar a conocer). Si le das una pasada, seguramente encontrarás algún error de puntuación, ortográfico o gramatical y, con toda seguridad, descubrirás párrafos que puedes mejorar en esa segunda lectura. En una tercera revisión vuelve a ocurrir lo mismo, hasta que llega un momento en que intuyes que la calidad de lo que has escrito está a la altura de tus expectativas, quizá en la quinta, sexta o décima lectura de corrección. Más aún si otras personas leen tu texto y encuentran typos sutiles que tú has pasado por alto.

En software ocurre igual, con la diferencia de que estas revisiones afectan tanto a la estructura del código (el diseño) como a sus defectos: acoplamiento excesivo, baja cohesión, duplicidades, violaciones de principios de diseño, código difícil de entender, pruebas insuficientes, etc. La cuestión es: ¿para qué me debo preocupar de esto si mi aplicación funciona? Mmmm…

Si desarrollas una aplicación que nunca va a tener que cambiar, hasta vale entregarla con todos los defectos que se te puedan ocurrir. Pero esto rara vez ocurre, porque en la mayoría de los casos todos los proyectos sufrirán modificaciones en mayor o menor medida.

Cuántas aplicaciones he visto ya que son una simple extensión de un núcleo excesivamente monolítico… hasta que llega el momento en que ya no soporta más cambios y hay que tirarla a la basura y comenzar de cero, para frustración (o alivio, quién sabe) de los desarrolladores y varapalo para el negocio, que incurre en sobrecostes; además, algún responsable tratará de escurrir el bulto como sea.

La forma de evitar esto es refinar continuamente la aplicación en la que se trabaja, tratando de mejorar todos aquellos aspectos que, en ingeniería del software, sabemos que aportan calidad al código. Hablo de calidad en el sentido de generar una aplicación mantenible, que soporte pruebas automatizadas y que sea fácil de modificar y de ampliar.

Es sorprendente que algunos de estos refinamientos sean triviales y sencillos, y se realicen en poco tiempo. Igualmente sorprendente es el beneficio que aportan a medio y largo plazo. Por poner algunos ejemplos:

  • Comprobar si el código cumple con todas las buenas prácticas de clean code (buenos nombres, indentación correcta, clases cortas y comentarios limitados a lo necesario).
  • Comprobar la cohesión de las clases para generar un buen diseño.
  • ¿Se cumplen correctamente los principios S.O.L.I.D.?
  • Refactorizar pequeñas partes de la aplicación para mejorar su diseño y aumentar la simplicidad.
  • Darle una vuelta a la lógica de negocio más compleja para simplificarla en la medida de lo posible.
  • Revisar si se puede mejorar aún más el procedimiento de despliegue.
  • Etc.

Es buena idea dedicar algo de tiempo a todo lo anterior antes de comenzar una nueva fase de desarrollo. Al hacerlo, es más que probable que necesitemos menos tiempo para incorporar las nuevas características sobre las que tenemos que trabajar.