archivo

Archivo de la etiqueta: ciclo de vida iterativo incremental

Comenta Mary Poppendieck que: “Si quieres saber lo que el cliente quiere, dale lo que crees que quieren y escucha lo que te tienen que decir al respecto”.

Esa es la esencia del feedback: el usuario da una especificación, ejecutas según la interpretación que has hecho de la misma, obtienes un resultado y el usuario opina sobre el mismo, solicitando aquellos ajustes que consideres necesario.

En el caso de que desarrolles un producto y no te bases en especificaciones directas, el proceso es el mismo.

Recuerda que el sistema que desarrollas no es para ti. Tal vez las decisiones del usuario no te gusten, tal vez pienses que hay otras soluciones más adecuadas, si es así, exponlas, porque lo mismo ese punto de vista no se ha tenido en cuenta, pero no las impongas o manipules para que ese sea el camino elegido. Todos tenemos derecho a equivocarnos, pero más quien paga.

El objetivo es incrementar el valor del producto y la mejor forma de hacerlo es centrarnos en quiénes van a ser sus usuarios porque son ellos los que van a tener que convivir con él todos los días.

Cuando se trata de evolucionar un producto sin consolidar ese avance tenemos que plantearnos si efectivamente se trata de tierra ganada.

Una cosa es la experimentación, otra el desarrollo iterativo incremental o la incertidumbre y otras bien distinta es dar pasos rápidos que lo que van dejando atŕas es tierra quemada.

Experimentar es necesario, es una de las bases del desarrollo de software, realmente es lo que se hace cuando se implementa lo que creemos que hemos entendido de lo que cree que quiere el usuario. Esa diferencia se va paliando a través del feedback, salvo que se piense que se va a acertar a la primera, algo poco probable por muy buena voluntad que pongan las partes.

El desarrollo iterativo incremental refleja esa evolución del producto, tratando de consolidar lo ya realizado a la par de que se van incluyendo nuevas funcionalidades. No es tan importante el concepto como la aplicación de un enfoque adecuado, siendo recomendable pensar en pasar de estados más simples a otros más complejos.

La incertidumbre es lo que rodea al desarrollo de software y también a los negocios. Se está sometido a tantos factores que el contexto puede cambiar de manera lo suficientemente sensible como para que impacte en el proyecto. No se trata de huir de la incertidumbre sino de entenderla como algo inherente, por lo que se trata siempre de estar adaptado al cambio.

Dar pasos rápidos con el objeto de obtener un feedback necesario para obtener una orientación del producto es una buena estrategia. El problema es cuando se confunde ir rápido con la toma de atajos. A veces viene bien cogerlos pero cuando dejan de ser una excepción tenemos en un problema porque probablemente estemos sacrificando estabilidad y deuda técnica (capacidad, a fin de cuentas de adaptación al cambio) por más funcionalidad, que por otro lado hay que ver si es necesaria y que nos restará capacidad de maniobra en el caso de que sea necesario cambiar de enfoque.

Por todo eso, resulta necesario analizar si efectivamente los pasos que se van dando en el proyecto dejan tierra ganada.

La idea que tienen los product owners o los responsables funcionales del software que quieren no es más que algo abstracto, es más, hasta que el producto empiece a materializarse y cobrar una cierta entidad es más acertado decir que su idea inicial es lo que creen que quieren porque hasta que no se empiece a experimentar no saldrán a la superficie comportamientos y funcionalidades deseados pero que estaban ocultos o el caso contrario, comportamientos y funcionalidades que se creían efectivos y útiles y que no son ninguna de esas dos cosas.

De ahí la conveniencia de aplicar desarrollo iterativo incremental y con más razón en aquellos casos donde el sistema se prevea complejo y/o los responsables funcionales no terminen de verlo claro.

Pero desarrollo iterativo incremental es una idea muy general, si definimos ciclos largos hemos fraccionado algo el problema pero probablemente será insuficiente y será mayor la cantidad de desperdicio generado.

También es cuestión de enfoque, mejor siempre partir de soluciones simples consolidadas y validadas para a partir de ahí crecer hacia otras más complejas.

¿Se trata de obtener una versión rápida a toda costa? Versión rápida a toda costa es algo demasiado general, sí que resulta interesante cuanto antes obtener un feedback del usuario pero también que el desperdicio generado sea el menor posible (por lo que los ciclos de desarrollo deben hacerse con intención, de no hacerse así estaremos haciendo desarrollo por permutación y eso tiene un coste importante) y que no perdamos de vista que para seguir generando nuevas versiones es necesario que las modificaciones a realizar sobre el producto se puedan hacer en unos plazos razonables, por lo que en el momento en el que la deuda técnica supere unos determinados umbrales perderemos esa capacidad de respuesta rápida o por lo menos no tan rápida, efectiva y económica como sería deseable.

Tal vez al principio consideres que lo más importante es desarrollar una versión aunque sea prototípica para verificar si el producto va por el camino deseado y que determinados factores como la calidad del código son secundarios. Al final es algo que tendrás que valorar tú en base al contexto en el que estás desarrollando.

Te puedes esforzar en un proyecto para cumplir una planificación y ceñirte a unos costes y sin embargo no conseguir nada, incluso desarrollando todas y cada de las funcionalidades tal y cual se especificaron en un principio.

¿Por qué? La idea inicial no tiene por qué funcionar, de hecho todos sabemos que es muy difícil acertar a la primera y todavía más conforme se incrementa el tamaño y/o complejidad de la solución. Esto es extensible tanto para el desarrollo de un producto propio como para el desarrollo de software para terceros.

Por tanto, afirmar que un producto que va acorde a unos plazos, unos costes y unas determinadas funcionalidades va bien, es mucho suponer si no se mide realmente el valor que se está obteniendo, de ahí el riesgo que supone, por ejemplo, un desarrollo en cascada cuando los desarrolladores y usuarios viven separados desde la finalización del análisis hasta etapas próximas a la entrega.

En los desarrollos iterativos incrementales, con entregas más frecuentes y con versiones en producción desde etapas tempranas el feedback permite evaluar el valor real que se está obteniendo y adoptar decisiones encaminadas a incrementarlo.

Otra cosa, es que pese a trabajar de esta forma se quiera seguir con el guión inicial prácticamente sin variaciones, en ese caso, poco importará la metodología porque predominará el seguimiento de un plan y esto es consecuencia muchas veces no de confiar ciegamente en él, sino por el afan de cumplir, de cubrir el expediente: “si al final se fracasa, la culpa no es nuestra, sino del plan”.

Parece políticamente incorrecto en el mundo ágil la utilización de la palabra requisito. También, aunque algo menos, la palabra especificación. El motivo principal es su asociación a los desarrollos en cascada y a un modelo de desarrollo basado, yéndonos a un extremo, al dicto, interpreto/apunto, construyo.

Parece que el concepto de historia de usuario se asocia más a la colaboración que es la base en la que se sustenta la agilidad y el enfoque de desarrollo iterativo incremental (os recuerdo que un enfoque o ciclo de vida concreto de desarrollo no es en esencia ágil ya que depende de la actitud con que se aborde).

Estoy de acuerdo en que en determinados momentos usar la palabra adecuada puede ser importante pero tampoco se pierde valor si el fondo realmente dice lo que queremos transmitir. Lo realmente importante, independientemente del nombre que le demos, es que en los ciclos de vida clásicos se piensa en el producto, por encima de analizar y trabajar sobre los problemas reales que se quieren resolver y esto es así, entre otras cosas, porque los desarrollos en cascada piensan en los productos en términos finalistas y en los enfoques evolutivos en términos de valor ganado en aproximaciones sucesivas hacia una determinada solución.

Asumir que no se sabe o se conoce todo es una de las bases para el desarrollo iterativo incremental.

Has podido realizar un análisis que te ha llevado meses, en el que se ha trabajado concienzudamente con los responsables funcionales pero cuando se esté en la fase de desarrollo del producto se materializarán de forma muy probable ciertos riesgos que rompan con esa concepción lineal del desarrollo: analizo, diseño, construyo; bien porque los responsables funcionales descubran que su especificación inicial tiene errores y/o es perfeccionable o bien porque cambie el propio contexto del proyecto (se recorte el presupuesto, cambie determinada normativa que condicionaba las especificaciones, etc…).

Suponer que las condiciones iniciales no van a cambiar es mucho suponer, si has desarrollado en cascada lo habrás sufrido y yo he trabajado en muchos proyectos de este tipo y lo he vivido en primera persona.

Que sí, que todo es negociable, que se pueden cambiar unas tareas por otras y que con voluntad se pueden alcanzar acuerdos que den lugar a soluciones satisfactorias, pero el margen de conseguir esos acuerdos será menor conforme menos presupuesto quede en el proyecto y conforme el coste de realizar los cambios sea mayor o lo que es lo mismo, cuanto más tarde se detecte la necesidad del cambio o los problemas y un desarrollo en cascada es muy dado a que se produzcan esas circunstancias.

Si un proyecto puede presentar problemas presupuestarios cuando se prevé un alcance y una complejidad mayor que cuando se hizo su estimación económica, la solución debería pasar, no por intentar meter todas las funcionalidades con calzador, sino por tratar de buscar una solución más racional que permita obtener un producto que satisfaga las prioridades que se han establecido con un alto nivel de calidad, aunque esto implique dejar fuera o para más adelante (en muchos casos es necesario gestionar con los responsables funcionales el síndrome de la última versión), otra serie de funcionalidades que pueden resultar interesantes.

El primer paso debería consistir en dividir el proyecto en diferentes entregas, siendo conscientes todas las partes de que el desarrollo será iterativo incremental porque del feedback de cada versión vendrán, muy probablemente, solicitudes de mejora por parte del área usuaria.

Si se trata hacer todo de golpe se correrá el riesgo de que se agote el presupuesto y que en medio del proceso de desarrollo se entre en un conflicto entre las partes sobre cuál será el alcance final.

La experiencia dice que por muy buen acuerdo que se alcance se verá afectada la calidad del software porque el proveedor tratará de minimizar pérdidas, porque los desarrolladores tendrán overtime y llegado a un punto el cansancio y las ganas de terminar darán lugar a precipitación que se traduce en deuda técnica y en un producto menos probado.

Por otro lado, el cliente tendrá una mayor desconfianza y la comunicación entre las partes, tan necesaria en un proyecto de desarrollo de software, perderá fluidez y en función del grado de desgaste en las relaciones podría dar lugar a situaciones del antipatrón “arrojar al otro lado del muro“.

También se puede agotar el presupuesto con el enfoque iterativo incremental, la diferencia está en que al reestructurar el proyecto de esta manera todas las partes conocen las reglas del juego: se trabaja así no solo porque sea el enfoque que mejor pueda convenir al proyecto sino porque permite gestionar de manera adecuada las prioridades, el seguimiento y consumo económico del proyecto.

El siguiente paso consiste en trabajar con pila de producto e historias de usuario. Los responsables funcionales priorizan estas historias que una vez tasadas y ajustadas a la capacidad del sprint, se convierten en lo que será el resultado final de la entrega.

Si no lo ves claro (y también si lo ves claro), no dudes en dividir el proyecto en partes y cada parte en componentes o trabajos más simples (historias de usuario). Será más manejable, te beneficiarás el feedback y la gestión económica será mucho más transparente y mejor entendida entre las partes.

El aprendizaje requiere también de experimentación con el objeto de obtener un feedback que nos permita seguir evolucionando y tomando nuevas decisiones.

El enfoque iterativo incremental en el desarrollo de software supone un marco ideal, si bien, lo ideal es que los ciclos no se demoren mucho en el tiempo para ir adquiriendo ese conocimiento lo más rápidamente posible (la duración en los ciclos, en mi opinión, no lo debe imponer la metodología sino las propias necesidades que tenga el proyecto).

Con ciclos demasiado largos probablemente los errores de enfoque por parte de desarrolladores o usuarios y el descubrimiento de alternativas más simples se detecten demasiado tarde, no porque no tengan solución (que dependerá del estado del proyecto) sino por el coste que tendrá afrontar los ajustes necesarios para evolucionar el producto hacia una solución que se vaya aproximando más a las expectativas que se tienen puestas en él.

Se debe evitar también, salvo que sea absolutamente necesario, entrar en un bucle de prueba y error porque cada iteración tiene un coste y de la inversión realizada se debe tratar de conseguir el mayor valor posible. Por ese motivo, cada evolución deben tener unas historias de usuario lo suficientemente trabajadas (en las tareas que se deben realizar en paralelo de refinamiento de la pila de producto), ya que permitirá ajustar mejor las estimaciones a realizar y se acertará (o nos acercaremos a una solución válida) en un mayor porcentaje de casos.

Lao-Tsé refleja en un par de citas, un aspecto esencial que tenemos que tener en cuenta a la hora de abordar un proyecto de desarrollo de software y en general para cualquier tarea de un cierto tamaño que queramos afrontar:

“Proyecta lo difícil partiendo de donde aún es fácil”.

“Realiza lo grande partiendo de donde aún es pequeño”.

Precisamente uno de los grandes problemas del ciclo de vida en clásico o en cascada es ese, construir un producto demasiado grande que después resulta complicado de reajustar.

Cuanto más grande sea, más dinero nos habremos gastado, por lo que menos disponibilidad presupuestaria tendremos para hacer modificaciones (a la par de la presión por amortizar la inversión) y la deuda técnica hará más costosas las modificaciones, y eso casi en el mejor de los casos, porque si hay que cambiar arquitectura o estrategias de diseño, los costes se disparan.

Si encima el producto cubre un proceso de negocio estratégico el impacto será aún más fuerte.

Precisamente quienes conocen este problema tratan de dividir el sistema en diferentes versiones, siguiendo un enfoque incremental. Eso es un primer paso para hacerlo también iterativo, en el sentido de que en cada versión se subsanen deficiencias de las anteriores, que no solo llegan a nivel correctivo, sino también perfectivo y evolutivo.

Se mejora de esta forma, pero si la duración de las iteraciones es demasiado prolongada, seguiremos teniendo en esencia el problema inicial, atenuado, pero seguirá ahí.

Por ese motivo, el siguiente paso es la realización de ciclos más cortos. Si son fijos o variables en tiempo, es otro tema de debate.

Hace un tiempo me expusieron un caso de un proyecto que se desarrolló siguiendo un enfoque iterativo incremental con ciclos cortos de menos de un mes de duración, en el que se obtuvo un producto cuyo resultado final dejaba mucho que desear.

¿Pero no es así como recomiendas que se desarrolle? Lo que sí digo siempre es que es la estrategia que mejor se adapta a la realidad de los proyectos de desarrollo de software pero que después cada proyecto es un mundo y sus necesidades o contexto pueden recomendar otras estrategias.

Sin embargo el proyecto no salió bien porque aplicar un desarrollo iterativo incremental sino porque se cayeron en algunos errores que se arrastraron hasta el final:

– Mala elección de la arquitectura del sistema.

– Se desarrollaban historias de usuario que no estaban lo suficientemente consolidadas, lo que hacía que su desarrollo tuviera menos intención y se requirieran más iteraciones de la cuenta en cerrarlas.

– En lugar de rehacer completamente módulos o funcionalidades cuyo funcionamiento se descartó, se trató de solucionar parcheándolas, lo que no daba la suficiente libertad para desarrollar la solución que pudiera satisfacer de manera efectiva las expectativas de los usuarios y por otro lado incrementaba la deuda técnica porque los desarrollos no eran limpios.

– En lugar de dedicar el esfuerzo en resolver los problemas principales del sistema se repartía desarrollando nuevas funcionalidades, lo que implicaba que muchos de ellos no terminaban de corregirse nunca (porque además en los nuevos desarrollos aparecían nuevas contingencias).

La mayoría (o todos) de estos problemas se hubieran dado igualmente en un enfoque clásico, es más, pienso que el resultado final hubiera sido peor porque en este caso, por lo menos, gracias al feedback se pudo ir desarrollando un producto que se aproximase a las expectativas del usuario.

Lo que vengo a exponer en este artículo es que realmente una estrategia o metodología de desarrollo no te ofrece una solución, solo te indica una manera de hacer las cosas, después las decisiones que se adopten, la actitud y la aptitud de las diferentes personas que participan y el contexto del propio proyecto son las que permiten obtener unos resultados mejores o peores.