1.9.6. Fase 5: Evolución

Este es el punto en el ciclo de desarrollo que se conoce tradicionalmente como «mantenimiento», un término amplio que puede significar de todo, desde «conseguir que funcione como se supone que debió hacerlo desde el principio» hasta «añadir características que el cliente olvidó mencionar» pasando por el tradicional «arreglar errores que han ido apareciendo» y «añadir nuevas características según se presentan las necesidades». Se han aplicado algunas ideas equivocadas al término «mantenimiento» que se ha tomado en calidad de pequeño engaño, en parte porque sugiere que realmente ha construido un programa primitivo y todo lo que necesita hacer es cambiar partes, engrasarlo, e impedir que se oxide. Quizá haya un término mejor para describir esa tarea.

Yo usaré el término evolución [24]. Es decir, «no podrá hacerlo bien la primera vez, pero le dará la oportunidad de aprender y volver atrás y hacer cambios». Puede que necesite hacer muchos cambios hasta que aprenda y entienda el problema con mayor profundidad. La elegancia que obtendrá si evoluciona hasta hacerlo bien valdrá la pena, tanto a corto como a largo plazo. La evolución es donde su programa pasa de bueno a fenomenal, y donde estos usos, que realmente no entiende en un primer momento, pasan a ser más claros después. Es también donde sus clases pueden evolucionar de un uso de único-proyecto a recursos reutilizables.

«Hacerlo bien» no significa sólo que el programa funcione según los requisitos y los casos de uso. Significa que la estructura interna del código tiene sentido, y parece que encaja bien, sin sintaxis difícil, objetos sobredimensionados, o pedazos de código desgarbados. Además, debe tener la sensación de que la estructura del programa sobrevivirá a los cambios que inevitablemente habrá durante su ciclo de vida, y estos cambios pueden hacerse fácil y limpiamente. No es una tarea sencilla. No sólo debe entender lo que está construyendo, sino también cómo evolucionará el programa (lo que yo llamo el vector de cambio [25]. Afortunadamente, los lenguajes de programación orientados a objetos son particularmente adecuados para dar soporte a este tipo de modificaciones continuas - los límites creados por los objetos son los que tienden a conservar la estructura frente a roturas. También le permiten hacer cambios - algunos pueden parecer drásticos en un programa procedural - sin causar terremotos en todo su código. En realidad, el soporte para la evolución puede que sea el beneficio más importante de la POO.

Con la evolución, el programador crea algo que al menos se aproxima a lo que piensa que está construyendo, y luego busca defectos, lo compara con sus requisitos y ve lo que falta. Entonces puede volver y arreglarlo rediseñando y re-implementando las porciones del programa que no funcionen bien [26]. Realmente puede necesitar resolver el problema, o un aspecto del mismo, varias veces antes de dar con la solución correcta. (Un estudio de los Patrones de Diseño, descrito en el Volumen 2, normalmente resulta útil aquí).

La evolución también ocurre cuando construye un sistema, ve que encaja con sus requisitos, y entonces descubre que no era realmente lo que buscaba. Cuando ve el sistema en funcionamiento, descubre que realmente quería resolver era problema diferente. Si piensa que este tipo de evolución le va a ocurrir, entonces debe construir su primera versión lo más rápidamente posible para que pueda darse cuenta de si es eso lo que quiere.

Quizás lo más importante a recordar es que por defecto -por definición, realmente- si modifica una clase entonces su superclase -y subclases- seguirán funcionando. Necesita perder el miedo a los cambios (especialmente si tiene un conjunto predefinido de pruebas unitarias para verificar la validez de sus cambios). La modificación no romperá necesariamente el programa, y ningún cambio en el resultado estará limitado a las subclases y/o colaboradores específicos de la clase que cambie.



[24] Por lo menos un aspecto de evolución se explica en el libro Refactoring: improving the design of existing code (Addison-Wesley 1999) de Martin Fowler. Tenga presente que este libro usa exlusivamente ejemplos en Java.

[25] Este término se explica en el capítulo Los patrones de diseño en el Volumen 2

[26] Esto es algo como «prototipado rápido», donde se propone construir un borrador de la versión rápida y sucia que se puede utilizar para aprender sobre el sistema, y entonces puede tirar su prototipo y construir el bueno. El problema con el prototipado rápido es que la gente no tiró el prototipo, y construyó sobre él. Combinado con la falta de estructura en la programación procedural, esto producía a menudo sistemas desordenados que eran difíciles de mantener.