La ingeniería del software prescribe un conjunto de actividades ordenadas encaminadas a la producción de software.
Las actividades del “ciclo de vida” del software son:
1. Requisitos. Esta actividad tiene como objetivo descubrir los problemas o necesidades que el software debe solventar o suplir.
2. Análisis. Una vez aterrizadas las necesidades que debe suplir el software, se especificarán sus funcionalidades.
3. Diseño. Tras concretar las funcionalidades del software se idea el sistema y se define la arquitectura que sustentará el código.
4. Codificación. A partir del diseño y sobre los cimientos de la arquitectura propuesta se codifica el software.
5. Pruebas (Verificación y validación). El software debe funcionar correctamente y responder a las expectativas del cliente.
6. Despliegue. Finalmente, el software se despliega para ser operado por los usuarios.
Existen diferentes métodos para llevar a cabo todas las actividades del ciclo de vida. Sobre estas metodologías hay dos grandes puntos de vista: la visión predictiva y la visión adaptativa.
El modelo “waterfall” o “en cascada”, es uno de los modelos de desarrollo software más antiguos. Fue propuesto por Herbert D. Benington en el año 1956 aunque no fue formalizado hasta 1970 por Winston W. Royce.
Algunos productos se desarrollan con procedimientos normalizados, ejecutados según protocolos y prácticas estandarizadas, que con carácter repetitivo se emplean para construir productos de características similares. Los electrodomésticos, muebles, automóviles, prendas de vestir, etc. son ejemplos de productos realizados a través de procedimientos normalizados. Las operaciones que prescriben estos procedimientos se ejecutan de forma repetitiva para obtener resultados de características similares.
La visión predictiva pretende aplicar las técnicas utilizadas en la ingeniería civil o industrial (construcción de puentes o automóviles) a la construcción de software, normalizando el proceso de construcción lo máximo posible para obtener productos de características similares y predecibles.
De esta forma, de modo similar a la construcción de un puente o un automóvil, se plantea la siguiente secuencia de actividades:
Requisitos. Durante la actividad de “requisitos” los analistas recogerán las necesidades que el producto software debe suplir de la forma más detallada posible, aunque evitando concretar las soluciones técnicas (esto se hará en la siguiente fase “Análisis”).
Análisis. Tras recoger de forma muy detallada las necesidades que el producto software debe suplir se aterrizan las funcionalidades que el producto software debe ofrecer. Hay que ser especialmente cuidadoso en esta fase, ya que en este modelo no se pueden añadir nuevas funcionalidades en fases tardías. Disponer de una especificación del software permite precisar el diseño del software. Además, permite tener una base a partir de la cual estimar el coste del producto, los riesgos y los plazos. La fase de “Análisis” termina con un entregable donde se detallan las funcionalidades del software.
Diseño. Una vez cerradas las especificaciones, es necesario “imaginar” y “bocetar” el software. Las especificaciones funcionales y técnicas se comunicarán al equipo de diseño que elaborará los “planos” del software. Estos “planos” o “diagramas” describen la estructura interna del software y las entidades que lo componen. Los diagramas deben ser lo suficientemente rigurosos para que el equipo de desarrollo implemente la solución. Al finalizar la fase “Diseño” se entregan diagramas UML y documentos que describen cómo el producto software implementará las especificaciones definidas en el análisis.
Codificación. En la fase de “Codificación”, el equipo de desarrollo, especialistas en el lenguaje de programación, escribirá el código a partir de los “planos” entregados por el equipo de diseño. Esta fase concluye con la entrega de software.
Pruebas. El equipo de calidad (QA) realizará todas las pruebas pertinentes antes de entregar el producto al cliente. El objetivo de las pruebas es el de obtener información de la calidad del software, y sirven para: encontrar defectos o bugs, aumentar la calidad del software, refinar el código previamente escrito sin miedo a romperlo o introducir nuevos bugs, etc.
Despliegue. Por último, una vez el software ha sido verificado y validado el equipo de despliegue lo instalará en el entorno de producción para que los usuarios puedan operar con él.
Cada fase debe ser realizada por un equipo independiente y cada fase termina con un “entregable” que no puede ser modificado. La construcción basada en “silos” de conocimiento (especialistas en análisis, especialistas en diseño, especialistas en codificación, especialistas en pruebas y especialistas de operación) exige una documentación muy exhaustiva.
Esta visión presenta resistencia a los cambios. De la misma forma que en la construcción de un puente el cliente no puede cambiar las características una vez comenzada la construcción, una vez cerradas las especificaciones del software, no se aceptan cambios. Introducir un cambio en el documento de especificaciones o en los planos del diseño implica una cascada de modificaciones tanto en el código como en el resto de entregables (especificaciones, diagramas UML, prototipos, pruebas, etc.).
Actividad vs Tiempo. Planificación predictiva, sin iteraciones y sin solapamientos
Para construir un producto software que implemente las funcionalidades A, B, C y D, la visión predictiva planifica 5 fases: Requisitos, Análisis y Diseño, Codificación, Pruebas y Despliegue. Cada una de estas actividades son realizadas por especialistas: Analistas, Diseñadores, Codificadores, Probadores y Operadores. Una fase no puede comenzar sin terminar la anterior. La última fase, “despliegue” entrega el producto software completo con todas las funcionalidades. El alcance de cada fase cubre todas las funcionalidades (A, B, C y D). Por ejemplo, en la fase de Requisitos el analista recoge completamente los requerimientos de todas y cada una de las funcionalidades del software. En la fase de “Análisis y Diseño” los analistas y diseñadores elaboran las especificaciones del software para todas y cada una de las funcionalidades. El equipo de desarrollo codifica el producto completo implementando las cuatro funcionalidades. Finalmente, el equipo de testers prueba el software y los técnicos de operaciones lo despliegan.
Los métodos ágiles ponen el foco en entregar valor al cliente de forma temprana y frecuente. Para ello plantean el desarrollo de software iterando entregas, cada pequeño incremento ofrece algo más de valor que el anterior. Las especificaciones del software no se recogen con detalle al comienzo, sino que se van descubriendo, poco a poco, según se va entregando el producto. Los requisitos, el diseño, la codificación y las pruebas están abiertos al cambio durante todo el proceso de construcción.
Esta visión adaptativa prescribe la eliminación de “silos”, hacen desaparecer los roles “arquitecto”, “analista” o “tester”. No hay un equipo de analistas, otro de diseñadores, otro de testers, etc. Únicamente hay un equipo, auto-organizado e hiper-productivo, que reúne a las personas esenciales para, en su conjunto, sumar las competencias necesarias para tener éxito.
Actividad vs Tiempo. Planificación adaptativa, con iteraciones, pero sin solapamientos
Para construir un producto software que implemente las funcionalidades A, B, C y D la visión adaptativa planifica cuatro entregas, cada sprint o iteración entregará cada una de las funcionalidades del producto software. Es decir, se planifican cuatro despliegues. Cada iteración es realizada por un equipo de técnicos que reúne todas las competencias necesarias para tener éxito en la iteración.
La visión adaptativa no sólo prescribe la iteración de actividades para poder entregar periódicamente software con valor para el cliente, también permite el solapamiento de actividades.
Actividad vs Tiempo. Planificación Adaptativa, con iteraciones y con solapamientos
Por ejemplo, en el Sprint A el equipo comienza recogiendo los requisitos de la funcionalidad A, también comienza el análisis y diseño de dicha funcionalidad. Cuando el equipo considera que el análisis y diseño está suficientemente maduro, comienzan la codificación que pronto la solapan con las pruebas automatizadas. Además, es habitual que los miembros del equipo sean capaces de interpretar diferentes roles.
Para ayudar a entender la visión adaptativa, en el ejemplo se han simplificado las entregas de funcionalidad. Es habitual, en el primer sprint, entregar un porcentaje de cada funcionalidad en lugar de entregar totalmente una concreta. Por ejemplo, la primera iteración podría haber entregado el 60% de la A, el 20% de la B, el 10% de la C y el 10% de la D. La segunda iteración podría haber entregado el 10% de la A, el 50% de la B, el 40% de la C y el 5% de la D. Las sucesivas iteraciones irán aumentando el porcentaje de funcionalidad entregada haciendo el producto final cada vez más “completo”.
En la construcción ágil del producto software no son necesarios los extensos documentos de requerimientos, son sustituidos por sencillas “historias de usuario”. Las necesidades del cliente que debe solventar el producto software se irán detallando según avance el proyecto recibiendo constante “feedback” por parte del negocio.
Cada miembro del equipo es responsable de diseñar, codificar y probar un segmento funcional (feature), esto reduce la cantidad de documentación a generar. Desaparecen los “planos” del software (diagramas UML rigurosos). Ya no es necesario que el equipo de arquitectos comunique las especificaciones del software al equipo de codificación o que el equipo de testers elabore extensos planes de prueba. Prescindir de toda esta documentación exige nuevas técnicas de diseño. Los desarrolladores no improvisan el código. Los miembros del equipo utilizan técnicas de desarrollo guiadas por pruebas que facilita el diseño de las clases y sus comportamientos.
Las metodologías adaptativas, también llamadas “ágiles”, subrayan las características propias de la industria del software que la hacen diferente a la industria civil o manufacturera. Juan Palacio en "Flexibilidad con Scrum" (2008) ofrece las siguientes claves:
Coste de la materia prima. Un ingeniero de software puede desarrollar con recursos escasos una solución extraordinaria; sin embargo, un arquitecto o un ingeniero naval no pueden hacer lo mismo. Los recursos físicos necesarios para la construcción de sistemas en ninguna ingeniería son despreciables, excepto en la ingeniería de software. Esta característica tiene implicaciones importantes en la gestión porque permite considerar opciones que la gestión clásica de proyectos ni se plantea. Sería absurdo considerar para la construcción de edificios, ir edificando en pequeños incrementos, revisar lo hecho sobre el terreno, y derribar lo que se considere erróneo o mejorable, para rehacerlo de una nueva forma.
Maleabilidad del producto. Los materiales físicos no son muy maleables. Esta característica refuerza la necesidad de previsión antes de comenzar la construcción de un sistema, porque una vez desarrolladas cada una de las partes o módulos, no es posible su cambio, amoldando lo ya construido. Pero el software no es físico, la maleabilidad puede ser muy elevada si se tiene en cuenta como opción de desarrollo, para acometer ampliaciones y modificaciones del sistema con técnicas de refactorización. El producto software es “moldeable”.
Valor aportado por las personas. Cuando el grueso del conocimiento reside en los procesos, y las personas aportan capacidad de ejecución en forma de tareas mecánicas o supervisión, la diferencia de productividad o calidad si el trabajador es mejor o peor, no es muy significativa. En la cocina de un Telepizza, que el operario tenga más o menos talento influye muy poco en el resultado. Sin embargo, cuando el grueso del conocimiento reside en las personas, que aportan el talento, y los procedimientos son quienes ayudan a las personas, las diferencias de los resultados entre los mediocres y los mejores son muy relevantes.
Factor de escala del producto. Algunos productos tienen factores de escala escasos: aumentar el número de unidades realizadas, supone incrementos de proporciones similares en el coste de fabricación. El software tiene un factor de escala prácticamente infinito: cuesta lo mismo producir uno que miles.
La maleabilidad del producto y el reducido coste de la materia prima permiten plantear ciclos de construcción ágil, pequeños incrementos en iteraciones breves, durante los que se van refinando y descubriendo nuevos requisitos. Un modelo de gestión que parecería absurdo en otras industrias, no lo es tanto si atendemos a las características propias de la industria del software, diferentes a las del resto. La necesidad de desarrollar nuevas formas de ingeniería viene dada por la propia naturaleza intangible del software. Si construir puentes se pareciese a construir software, entonces indicando en la configuración “3 pilares” el puente mágicamente se levantaría sustentado en tres pilares, tras cambiar la configuración a “4 pilares” observaríamos cómo inmediatamente cuatro pilares sostienen el puente.
💬 Si bien puede usarse como analogía para la planificación de construcción de software la planificación de construcción de una casa o un rascacielos, difícilmente puede utilizarse [...] El software es más como la jardinería. Planifica el jardín, planta las plantas. Luego vea qué está creciendo, elimine las malas hierbas y plante nuevas plantas.
Andrew Hunt, The Pragmatic Programmer, 1999
En Software Engineering Economics (1981), Barry Boehm demuestra que los cambios introducidos en etapas tardías de la construcción tienen mayor coste final que los cambios detectados en las primeras fases.
Este hecho fue usado durante los 80s y gran parte de los 90s para justificar los ciclos de vida en cascada de la visión predictiva: Si es “caro” introducir un cambio una vez el software ha sido desplegado, pero barato introducirlo antes de iniciar el análisis, entonces es económicamente rentable indagar con mucho detalle cada una de las funcionalidades del software en la primeras fases de construcción (requerimientos y análisis) para prever todas los posibles cambios futuros y adelantarse a ellos en el diseño de la solución. Despectivamente, los críticos de los 80s bautizaron BDUF (Big Design Up Front) a este tipo de enfoque. El “Gran Diseño Al Frente” se caracteriza por alargar enormemente las fases de Requerimientos, Análisis y Diseño para elaborar pesados documentos de especificaciones.
Las metodologías adaptativas huyen del “Gran Diseño Al Frente”, prefieren ir descubriendo el producto software en cada iteración, introduciendo cambios constantemente. Pero si los cambios introducidos en etapas tardías de la construcción son “caros”, ¿no deberían ser las metodologías adaptativas una ruina económica? La solución más elemental pasaría por introducir cambios de la forma más barata reduciendo, por ejemplo, la calidad del producto software.
Reducir la calidad del producto software no es una buena idea: los errores y nuevas necesidades obligarán a pagar la factura con intereses. En la visión adaptativa es imprescindible abaratar el coste del cambio sin perjuicio de la calidad del producto software. Para reducir el coste del cambio en fases tardías de la construcción sin renunciar a la calidad, Kent Beck propone (Extreme Programming, 1999) el uso de una técnica de codificación guiada por pruebas, TDD (Test Driven Development). Esta técnica de codificación logra aplanar la curva del coste de cambio.
Cubrir con tests automatizados el código facilita tanto su refactorización como su extensión. El equipo de desarrollo es “obligado” a escribir pruebas automatizadas, estas pruebas exigen al software capacidad de extensión, capacidad de aceptar ciertos cambios. De esta forma es posible añadir nuevas funcionalidades o modificar las existentes reduciendo el esfuerzo de recodificación.
Existen metáforas para explicar cómo debe construirse software. Estas metáforas ofrecen diferentes puntos de vista. Todas tienen algo de razón y todas se equivocan en parte.
Referencias:
• K.Beck; "Extreme Programming Explained", Addison-Wesley Professional, 1999
• F.Brooks; "The Mythical Man-Month: Essays on Software Engineering", Addison-Wesley, 1975
• R.C. Martin "Arquitectura Limpia", Anaya, 2018
• J. Palacio; "Flexibilidad con Scrum", 2008.
• H. Kniberg; "SCRUM y XP desde las trincheras", InfoQ, 2007
• R.Jeffries; "The Nature of Software Development", Pragmatic Bookshelf, 2015
• I. Sommerville; “Ingeniería del Software”, Addison Wesley, 2005
• R. Pressman; “Ingeniería del Software: Un enfoque práctico”; McGraw-Hill, 2005.
• B. W. Boehm, "Software Engineering Economics", Prentice Hall,1981
• L. Artola, “Software Economics”, LeanPub, 2020
• T. Winters y H. Wright, “Software Engineering at Google”, O’Reilly, 2020
• J.Garzas; https://www.javiergarzas.com/