El control de la complejidad es la esencia de la programación

Brian Kernighan (n. 1942). Científico de la computación canadiense.

¿Por qué la mayoría de los sistemas de software acaban siendo piltrafas sin pies ni cabeza, con código spaghetti, innumerables parches y con tal dependencia entre sus componentes que la menor de las modificaciones puede provocar un desastre? ¿Acaso estamos condenados a siempre repetir este «patrón de desarrollo» o existe alguna manera en que podemos solucionarlo e incluso evitarlo?

El artículo Big Ball of Mud (Gran Bola de Lodo) de Brian Foote y Joseph Yoder trata de responder estas preguntas y acercarnos un poco a las filosofías que se requieren para prevenir o al menos disminuir la posibilidad de engendrar tal monstruo.

De forma elocuente, los autores definen qué es una gran bola de lodo (confieso haber participado en la creación de algunas de ellas en mis años mozos y haber sido víctima de otras tantas):

Una Gran Bola de Lodo es una jungla de código spaghetti, mal hecho, caóticamente estructurado, con crecimiento descontrolado y que se mantiene unido a base de alambres. Todos los hemos visto. Este tipo de sistemas presentan signos inconfundibles de crecimiento sin control y constantes reparaciones. La información es compartida entre elementos distantes del sistema, al grado en que cualquier información importante se hace global o se duplica. Es posible que incluso la estructura general del sistema nunca haya estado claramente definida; si alguna vez lo estuvo, probablemente se haya deteriorado hasta el punto de ser imposible reconocerla. Los programadores con un mínimo de sensibilidad arquitectónica detestan estos atolladeros. Sólo aquellos a quienes no les importa la arquitectura y tal vez están confortables con la inercia de generar parches día con día para tapar los agujeros de estos diques que se desmoronan, pueden estar contentos al trabajar en estos sistemas.

Concretamente, los autores nos presentan varias estrategias – algunas de ellas firmemente arraigadas en el Extreme Programming o el Rational Unified Process – que nos permitirán mitigar el riesgo de generar una bola de lodo:

Código desechable. Código realizado de forma apresurada con la intención de desecharlo mas tarde. Sin embargo, en más de una ocasión dicho código forma parte de la arquitectura, a pesar de lo informal de su estructura y pobre o inexistente documentación. Bien manejado es fundamental para generar los prototipos, demos y pruebas de concepto que requiere cualquier proyecto de software.

Crecimiento iterativo e incremental. Incluso sistemas con arquitecturas bien definidas son propensos a la erosión estructural. Dicha erosión toma la forma de requerimientos cambiantes que pueden desembocar en crecimiento fragmentado y sin control. Desarrollando con el cambio como punto central, en conjunto con retroalimentación por parte del usuario y refactoring constante, es posible adquirir un crecimiento ordenado y constante.

El Daily Build. Puede haber la necesidad de que un sistema necesite un cambio de gran envergadura, sin embargo realizar este tipo de operaciones es muy peligroso. Siempre será mejor una estrategia de mantenerlo trabajando, refactorando o rediseñando una parte del sistema por vez y comprobando que el todo siga funcionando correctamente. Como mencionan los autores:

Microsoft requiere por política que todos los días se genere un daily build o compilación de todo el proyecto al final de cada día de trabajo… Este enfoque, en conjunto con mantener la última versión [del código] en el repositorio, son prácticas universales de cualquier programador exitoso.

Capas de soporte. Los sistemas y sus capas constituyentes evolucionan a diferente ritmo. Conforme lo hacen, los componentes que cambian rápidamente tienden a hacerse distintos de aquellos que cambian de forma más lenta. Las capas de soporte que se desarrollan entre éstas son capas de abstracción que permiten reducir dependencias.

Barrer debajo de la alfombra. Una forma sencilla para controlar el declive del código consiste en «acordonar» las áreas arruinadas y colocar una fachada a su alrededor. [Utilizando patrones de diseño como el Façade o Connector me vienen a la mente de primera instancia].

Reconstrucción. En casos más avanzados de «deterioro de código», puede que no haya alternativa más que eliminar todo y empezar de nuevo. Cuando una reconstrucción total se hace necesaria, lo que queda es realizar un postmortem y aprender de los patrones observados.

Especialmente atractiva me parece la analogía que hacen los autores entre los conceptos de arquitectura de software y urbanismo; tanto una plataforma de software como una ciudad comparten la característica de que son sistemas vivos y complejos, con requerimientos en constante cambio. Un ejemplo muy peculiar es el caso de las capas de soporte:

Pic: Shearing Layers in a Building

La noción de capas de soporte (Shearing Layers) es una de las piezas centrales de How Buildings Learn de Stewart Brand. En éste dice: «Nuestro argumento básico es que no existe tal cosa como un edificio. Una construcción correctamente concebida se compone de muchas capas de longevidad de componentes construidos»… Estas capas son Sitio, Estructura, Fachada, Servicios, Plan de Espacio y Muebles… Estas capas cambian a diferentes ritmos. Los sistemas de software no pueden permanecer estáticos. Con frecuencia, el software debe adaptarse a requerimientos cambiantes, porque ya que está hecho de bits, puede cambiar.

(Fuente: peterme.com)

Como conclusión, aunque las estrategias que describen a lo largo del texto son algo abstractas y no tan específicas como los patrones de diseño del Gang of Four, es muy práctico en cuanto a guías que podemos usar para no batir nuestros proyectos. Como un bono extra, introduce al lector en algunos conceptos que se manejan en el día a día en cualquier metodología de desarrollo de software como la revisión por pares, pruebas de concepto o la retroalimentación del usuario. En definitiva, vale la pena echarle una hojeada.