May 24, 2007

Prisioneros del Software

Llevo unas semanas involucrado en un tema que me resulta bastante recurrente: ayudar a un cliente a lanzar una nueva versión de un software existente, esta vez a ser posible con ciertas garantías de que el software no sufrirá de “mortalidad infantil”. Hablo de la reescritura desde cero de un software, sin usar ni considerar (a nivel constructivo, es decir, de diseño y programación) nada de lo ya existente. Se trata de un software con bastantes funcionalidades, que ha reportado grandes beneficios a la empresa. De hecho, es la base de su negocio, con lo que además es una pieza estratégica y, por lo tanto, crítica en la empresa...



El círculo vicioso

¿Por qué cambiarlo? El software en cuestión se ha vuelto imposible de mantener: cualquier cambio acaba desatando gran cantidad de problemas y bugs, el rendimiento no es el deseable, es costoso de modificar por su pobre diseño, el código está totalmente “prostituido”… seguro que a más de uno le resulta familiar.

El problema es que el software funciona.

Desde la perspectiva de la empresa, el software es una herramienta para resolver un problema, no un fin en sí mismo, y por lo tanto si un software se usa es que funciona, puesto que en mayor o menor medida cumple con su cometido (también podría ser que no hubiera más remedio que usarlo, pero no es el caso).

Y ¿por qué es un problema que funcione? Pues porqué cuando un sistema funciona, tiende a crecer.

El software y todo lo que le rodea (usuarios, empresas, negocios, datos) son organismos "vivos", y en el software, entendido como herramienta, sucede algo que no sucede con el resto de herramientas: CRECE. Esto solo sucede con los organismos vivos. El usuario, como “ente vivo” que es, tiene que adaptarse al medio, y para ello requiere de nuevas herramientas. Sin embargo, con las “herramientas software” las quiere hacer crecer, ampliarlas, en lugar de reemplazarlas por otras herramientas nuevas, mejor adaptadas, en principio, a la nueva realidad de su medio.

La situación que pretendo describir se da normalmente con software que lleva cierto tiempo en operación; mal vamos si un software nuevo ya está tan mal, aunque también se da esta situación (hablemos de ello otro día). Se trata, por lo general, de software con cierto grado de complejidad, a la construcción del cual se ha dedicado una elevada suma de dinero (o tiempo, que es lo mismo), bien sea un software desarrollado por un tercero o construido por la propia empresa (lo que más adelante llamo “cliente interno”). Sea cual sea el caso, se trata un activo de importante valor. Por lo tanto, deshacernos del mismo significa eliminar un importante activo de la empresa, lo que a nivel financiero es un problema, puesto que hablamos de eliminarlo, no de venderlo. Este es el principal motivo por el que ciertos managers se niegan a “matar” este tipo de programas casi insostenibles, lo que resulta en un gravísimo error. Cuando se comete este error, irremediablemente le sigue otro: añadirle más funcionalidades. Entonces tenemos un software muy costoso de mantener, que nos gustaría eliminar pero nos cuesta hacerlo por el gran valor que tiene, al cuál le estamos añadiendo todavía más valor, dificultando así aun más que pueda ser reemplazado. La dificultad de reemplazarlo viene, llegado este punto, por dos o tres motivos:

  1. Como decía, significa deshacerse de un activo de importante valor

  2. La reconstrucción del mismo, la obtención de un software sustituto (puesto que es una herramienta necesaria), es más costosa en tiempo y, por lo tanto, en dinero, pues para conseguir el mismo grado de funcionalidades es necesario un mayor esfuerzo

  3. Si el software es un producto o servicio que vendemos, o la base de ello, el tiempo de puesta al mercado de la nueva solución es también mayor, aumentando el coste de oportunidad al no poder aplicar durante este tiempo funcionalidades nuevas

Pero la necesidad de reemplazarlo es clara, pues hay 2 problemas graves que resultan ya infranqueables:
  1. Añadir cualquier funcionalidad nueva supone un coste mayor, posiblemente en grados de magnitud, de lo que debería, dado que:

    1. la complejidad para añadir nuevas funcionalidades es mayor, ya que el estado actual es de un software poco modular, posiblemente con una elevada densidad de errores, sin documentar o mal documentado y con gran cantidad de código que posiblemente interactuará con la funcionalidad que vamos a añadir, puesto que el diseño del software no es el que sería deseable

    2. debido a la anterior razón, el tiempo para añadir nuevas funcionalidades es también mayor de lo que debería

    3. no hay tests automatizados, por lo que la calidad del software percibida por el cliente se ve afectada. Si hubiera tests y se hicieran pruebas de regresión, al menos se podría confiar en no romper lo que ya funciona o en no introducir cualquier bug

  2. Cada vez que añadimos funcionalidades a dicho software estamos aumentando su complejidad, aumentando así su coste de mantenimiento futuro y posiblemente también su coste de operación

El resultado es que hemos entrado en un círculo vicioso para el que no hay solución (salida) óptima: somos prisioneros del software.


Escapar

Debemos escapar de esta situación. No importa a qué extremo se ha llegado en el círculo vicioso, cuanto antes salgamos mejor. ¿Cómo debemos salir? evidentemente, matando el software. Pero, ¿Cómo?

For every complex problem, there is an answer that is short, simple and wrong (H. L. Mencken)


Primero debemos plantearnos cuáles son los principales impedimentos que vamos a encontrarnos:
  1. Los usuarios. Puesto que el sistema funciona, los usuarios serán reacios a cambiarlo por otro.

  2. Los managers. Por lo habitual según mi experiencia, lamentablemente son pocas las empresas que tienen buenos procedimientos de desarrollo de software; es por ello que el management puede ser reacio a dejar cambiar el software, pues tiene miedo –históricamente justificado en la mayoría de casos— a que no se pueda sustituir en los plazos comprometidos, es decir, a que las estimaciones planteadas por el equipo de desarrollo no se cumplan. Otra razón es el riesgo que puede suponer una decisión de este tipo cuando el software en cuestión es una importante fuente de ingresos en la empresa. Por lo tanto, el problema de base es la falta de confianza del management hacia el equipo de desarrollo en lo que a estimaciones se refiere (justificada en muchos casos).

Para matar el software hay que fijar 2 fechas críticas:
  1. Fecha de fin de producto (end of product): es la fecha a partir de la cual, bajo ningún concepto, se va a realizar ningún otro cambio al software, pase lo que pase, a excepción de bugs críticos. Se mantiene el soporte a usuarios, sin embargo. Si se trata de software comercial, lo deseable es disponer en esta fecha de una versión mínima de la nueva versión del producto.

  2. Fecha de muerte(end of life). Me hace gracia el eufemismo que usan los anglosajones, “fin de vida”, en lugar de “muerte”. En fin, se trata de la fecha en la que el producto es abandonado por completo, es decir, en la que ya no hay soporte a usuarios, corrección de bugs ni nada.

La cuestión clave aquí es que para poder poner una fecha de muerte, es necesario disponer de una fecha en la que, casi sin posibilidad de error, tendremos la nueva versión del producto.

Esto implica que debemos disponer de un equipo con experiencia como equipo, que pueda estimar tiempo y costes bien, y que se disponga de un procedimiento de desarrollo de software (que no solo de construcción) probado, disciplinado, sistemático y cuantificable, y que dicho procedimiento sea bien conocido por el equipo de desarrollo.

Pero, ¿qué sucede cuando el equipo, históricamente, ha fallado con las fechas de lanzamiento previstas? (da igual si es por culpa de cambios constantes en requisitos o de lo que sea) Entonces el management no confía en las fechas que le damos. Para ello es necesario convencer con hechos y hacer lo que debería hacerse en todo proyecto: implicar al cliente (sea un cliente externo o interno). ¿Cómo lo implicamos?:

  • haciendo que participe en todas las reuniones de toma de requisitos y de seguimiento de proyecto

  • descomponiendo los requisitos en tareas pequeñas, agrupándolas en hitos (milestones) a corto plazo, como a 1 semana, y en ciclos de desarrollo cortos (de 1 mes) que acaben con una entrega parcial totalmente operativa (aunque puede ser, y normalmente será, incompleta) al cliente, aumentando así la visibilidad del cliente sobre el progreso del proyecto

  • atacando primero aquellas partes del proyecto que tienen más riesgo, aumentando así la previsibilidad del proyecto al reducir el riesgo (lo que se llama estrechar el cono de incertidumbre), y ante el mismo nivel de riesgo, atacando primero aquellas tareas que aportan más valor al cliente en relación con su requisito de negocio, aumentando así el ROI de la entrega y, consecuentemente, del proyecto; de esta forma aumentamos más rápidamente el valor del proyecto, por lo que conseguimos reducir el coste del cambio

  • informando periódicamente (cada semana o cada vez que lo solicite) al responsable del proyecto por parte del cliente del estado del proyecto, facilitándole pleno acceso a los documentos de seguimiento de proyecto y trabajando conjuntamente para resolver cualquier posible problema que creamos que podemos tener en un futuro en el mismo momento en que lo creemos posible, no cuando lo tenemos encima


Evitar ser capturado

A scientist builds in order to learn; an engineer learns in order to build (Fred P. Brooks)


Para evitar ser capturado de nuevo solo hay un camino: aplicar un enfoque sistemático, disciplinado y cuantificable a las tareas de desarrollo, operación y mantenimiento del software; es decir, a todo el proceso de desarrollo, no solo a la construcción (diseño detallado y programación).

Así mismo, debido a la idiosincrasia particular del software y a las tendencias actuales, en que el tiempo de puesta al mercado y de adopción de cambios prima más que cualquier otra cosa, debemos adoptar unos procedimientos que sean adaptables al cambio, que sean flexibles. A un arquitecto no se le pide que construya un rascacielos encima de una casa de planta baja sin tocar los cimientos; a un ingeniero de software, sí.

No es necesario adoptar una metodología existente en concreto. Con frecuencia, da mejores resultados adoptar buenas prácticas y establecer una metodología propia, basada en alguna existente, pero adaptándose a las características particulares de aquél entorno concreto: experiencia y tamaño del equipo, tipo de software, requisitos de negocio, distribución geográfica del equipo,… Está claro que este tipo de decisiones sobre buenas prácticas y metodologías debe tomarlas alguien con basta experiencia y conocimiento en la materia.

Por último, es de vital importancia la mejora continua. Debemos establecer mecanismos de mejora continua y seguirlos estrictamente, para aprender de nuestra experiencia constantemente y disponer de una buena base histórica para afinar las estimaciones. Somos humanos y aprendemos de los errores.

Como dice mi mentor (gracias Pere por tus impagables enseñanzas):

L’experiència és molt bona, però sempre vé tard.
(La experiencia es muy buena, pero siempre llega tarde)



11 comentarios:

Fernando Andrade said...

La solución me suena mucho a SCRUM. Solo en la parte de predecir los tiempos de salida no cuadra con un modelo totalmente ágil. Como contraparte se podría intentar con TSP, aunque no veo que tengas nada sobre levantar estadísticas individuales de rendimiento.


Josep Ruano said...

Hola Fernando,

efectivamente parece a SCRUM, cierto. Sin embargo, pretendía hablar a un nivel más generalista que entrar en metodologías concretas, que sería otro tema distinto.

En cuanto a los modelos ágiles tienen ventajas, pero también tienen sus problemas cuando no existe un equipo, sino un grupo de gente, o cuando el equipo no es suficientemente senior para ser "auto gestionado" (eso es especialmente válido si hablamos de scrum). También tienen ciertos problemas cuando hay que dar presupuesto y tiempo cerrado para un proyecto grande, puesto que no están pensadas para analizar en detalle el proyecto por adelantado; en estos casos, tal y como reconoce Ken Schwaber (firmante del agile manifesto y autor de SCRUM), hay que combinarlas con métodos de estimación y análisis más tradicionales, pero aun así las metodologías ágiles nos pueden dar una ventaja competitiva para las fases de construcción.

No pretendía en el artículo discutir sobre metodologías, simplemente abrir debate sobre una situación excesivamente frecuente en muchos proyectos. Así mismo, la solución en el sentido de aumentar visibilidad, predicibilidad y reducir el riesgo, es la base de los fundamentos de ingeniería de software y de gestión de proyectos, que siempre deben incluír prácticas de gestión de riesgos (evaluación y control).

Muchas gracias Fernando por tu aportación.

Saludos


JM said...

Me parecen muy interesantes tus reflexiones sobre algo tan habitual (por desgracia) en el desarrollo de software.

Mi opinión al respecto (después de intentar recuperar unos cuantos proyectos) es que tirar el producto a la basura no es una buena decisión en la mayoría de los casos.

Mi modus-operandi suele ser algo parecido a esto (cada paso es un reto en si mismo):

1) Intentar crear un equipo de desarrollo pequeño y compacto, del nivel lo más alto posible (obviamente). Esto suele llevar a "sacar" del equipo a aquellos que no estén al nivel. Es importante aquí crear el rol de QA si todavía no existe, pero no como "probador" de software, sino como desarrollador orientado a la calidad.

2) Dedicar los primeros meses a la infraestructura del proyecto: procesos de construcción, sistema de bug-tracking, gestión de la configuración (SCM), toma de métricas etc.

3) Escribir el plan de pruebas del sistema (si no existe) y automatizarlo al máximo: este plan de pruebas no servirá como pruebas de regresión, para no ir hacia atrás en vez de avanzar.

4) Una vez que tenemos el entorno de trabajo y un colchón de seguridad, empezar a rescribir las partes del núcleo de la arquitectura, empezando por las más aisladas. Todo nuevo código irá acompañado de pruebas unitarias.

5) Aprovechar nuevas funcionalidades para rescribir la parte afectada.

6) No perder la referencia de las métricas (automáticas en cada ciclo de desarrollo). Nos irán informando si estamos consiguiendo o no nuestro objetivo.

Todo esto no da garantías de éxito, pero lo he probado en varias ocasiones y da resultados relativamente buenos.

Quizá de este modo tardes lo mismo o incluso más que rehaciendo el producto, pero la diferencia es que el resultado lo has conseguido por evolución del producto, y no haciendo borrón y cuenta nueva (ya que esto último tampoco te da garantías de que a la segunda lo hagas bien)

La clave de todo está en dos factores:
- Madurez del producto a reconducir
- Calidad del equipo.

Y sobre tus comentarios sobre metodologías ágiles, me parece muy sensato lo que dices de utilizar buenas prácticas junto con una metodología "ligera" adaptada a nuestro caso. Precisamente eso es lo que propone SCRUM: que se adapte la metodología a cada caso concreto, y se acompañe con buenas prácticas de ingeniería (habitualmente XP).

Un saludo y enhorabuena otra vez

JM


Josep Ruano said...

Gracias jm!

Creo que depende del grado de mala calidad al que haya llegado el producto. En la mayoría de casos en que me he encontrado, es prácticamente imposible aprovechar nada, porqué se ha hecho ya mal de base, empezando por la toma de requisitos, que siendo estrictos ha sido inexistente como tal. Eso ha llevado a que el proyecto viejo no sirva ni para tomar requisitos, porqué muchas features que tiene no son necesarias. Sin embargo, en algunas situaciones han sido adecuados planteamientos más similares al que tu indicas.

En cuanto a SCRUM, lo que plantea más bien es que, desde el punto de vista del equipode producción, el equipo sea autoorganizado y autogestionado, y haya una fina capa de gestión de proyecto que es la que controla el "SCRUM Master", pues SCRUM se centra en la gestión de proyectos complejos, y desde el punto de vista del cliente, se aumente la visibilidad de progreso, la predicibilidad y el control sobre el proyecto. Pero SCRUM plantea sus propias formas de gestionar los proyectos, y el propio Ken Schwaber indica que SCRUM no es apropiado para proyectos dónde hay que tener tiempos y costes acotados de antemano, aunque pueda dar una ventaja competitiva en la fase de construcción, y como sabemos en la mayoría de proyectos se nos pide que acotemos tiempo y dinero de antemano.

Por lo que respeta a los tests, el que sean apropiados o no para las pruebas de regresión depende de qué tests hablemos:
* sobre requisitos funcionales o sobre requisitos no funcionales
* pruebas de caja negra o de caja blanca

Si se trata de tests de caja negra sobre requisitos funcionales, entonces sí que pueden ser apropiados para mantenerlos y usarlos en los tests completos para el "regression testing".

En relación a lo que planteas sobre los primeros meses, de establecer los procedimientos y herramientas para la gestión y desarrollo del proyecto, estoy de acuerdo contigo en cuanto a la gran importancia que tiene y la importancia de dedicarle el tiempo necesario, aunque creo que este trabajo debe hacerse para un equipo o empresa, no para cada proyecto, al menos en lo que es la base (herramientas y procedimiento).


Saludos y gracias


JM said...

Hola otra vez...

Tanto SCRUM como cualquier otra metodología ágil, se quedarán cojas en el tema de planificación y presupuestos.

Hay que tener en cuenta que las metodologías ágiles no son predictivas (no te dicen cuando acabas el proyecto), sino adaptativas (te dicen sobre duracte el desarrollo si vas bien o vas mal, para que puedas ir tomando medidas correctoras a tiempo).

Por eso, el propio Schwaber dice que habría que complementar a SCRUM con otro tipo de prácticas más "formales".

De todas formas, mi experiencia es que a priori todos los gestores quieren saber "cuando" y "por cuanto", pero a la hora de la verdad, lo único que les importa es que se acabe, y que el producto final sea útil (y yo, como desarrollador añadiría "mantenible").

Por esto último me parece que SCRUM da en el clavo, porque le importa más ofrecer valor al producto en construcción, que no seguir con una planificación de tiempos o de costes.

Bueno, es mi opinión.

Un saludo

JM


Josep Ruano said...

jm,

estoy absolutamente de acuerdo contigo en tu reflexión.

Los gestores, en realidad, quieren y deben acotar el coste y el tiempo, pero no es necesaria una estimación al céntimo o al minuto.

En mi opinión, tal y como tu dices, SCRUM da en el clavo. En CAPSiDE usamos SCRUM para la construcción, y lo acompañamos de otras prácticas más "formales" para poder acotar costes con el cliente, pero para el proceso de construcción y con un buen equipo, funciona francamente bien.

Saludos y gracias de nuevo por comentar.


Alberto Giménez said...

Muy bueno el artículo (en tu línea, vamos)...

La metodología que comentas es muy buena sobre el papel, y de hecho con equipos preparados está demostrada su eficacia, pero se plantea la duda de ¿qué pasa si el equipo (o parte de él) simplemente no sirve?. Es decir, para entender y poner en práctica este tipo de metodologías hace falta tener una mínima base y algunos conceptos claros. ¿Qué pasa si no se tienen? Existe un lastre que evita que el equipo y el proyecto avancen.

Me refiero a que si todo el equipo no funciona correctamente, el proyecto se va al garete (retrasos, mala calidad del SW, etc). En estos casos, ¿se tendría que hacer limpieza? ¿O intentar dar formación?

Saludos y felicidades


Josep Ruano said...

Hola Alberto,

uno de los motivos por los que no me gustan las metodologías ágiles es este. Las llamadas metodologías ágiles se centran mucho en tener equipos que funcionen con la mínima gestión y documentación; cuando lees casos de estudio, dónde han fallado dicen que el equipo no era bueno. Claro, con un equipo de gente senior, todos brillantes, es fácil que salga bien. Personalmente me gusta SCRUM para la etapa de construcción, pero como ya decía antes, hay que acompañarla de otras buenas prácticas y fundamentos de ingeniería de software.

En cuanto al equipo, tener un buen equipo es fundamental. Creo yo que hay que distinguir entre aquellos que son buenos profesionales, con buena base, pero inexpertos, y aquellos que no tienen base suficiente y/o buenas actuitudes y aptitudes. A los últimos hay que descartarles si queremos tener un buen equipo. A los primeros, simplemente es cuestión de tiempo y de que tengan un buen mentor que les guíe por el camino correcto.

Solo mis 2 c.

saludos,


Juan Palacio said...

Hola Josep.
Acabo de descubrir tu blog (perdón por el despiste :-) y...: ehnorabuena!.

El tema de tu post es tan tan típico y para mi tan difícil de construirle una solución de talla única.

No conozco para nada el sistema al que te refieres, Algunas sugerencias que quizá puedan encajar:
- Desarrollar un análisis de inventario del sistema para sentarse con el cliente y tener datos y cifras objetivas sobre las que tratar el mantenimiento de su sistema.
Si un sistema es útil y perdura, el 80% del trabajo estará en su mantenimiento, quizá el cliente pensó que había comprado algo para lo que ya no necesitaba invertir, y que se puede moldear sin limitaciones ni metodo alguno.

- Dejar el sistema actual sólo con mantenimiento correctivo y las nuevas funcionalidades desarrollarlas sobre el diseño del nuevo, trasladando el coste actual de mantenimiento hacia el desarrollo del que será su relevo.

No se... no lo conozco, y podíamos charlar tanto.

Quizá una cosa más: si plantea hacer lo mismo, pero de nuevo; sabiendo perfectamente lo que quiere y siendo un experto (el cliente) en cómo lo quiere por el tiempo que lleva usando y trabajando en su negocio, quizá un modelo de desarrollo ágil no sea el más indicado. Aquí los requisitos se podrían tener cerrados y muy estables para todo el proyecto, y tratar de "hacerlo bien a la primera" como diría Humprey.

En fin... por apuntar cosas.

Un saludo, y enhorabuena por tu blog.
Juan


Josep Ruano said...

Juan,

gracias por pasarte y comentar.
En el caso del que hablo, el cliente cree conocer a la perfección los requisitos, pero en realidad no los conocía del todo: faltaba hacer lo que se llama "requirements scrubbing", es decir, revisarlos y eliminar aquellos que son superfluos, contradictorios o innecessarios. Por lo tanto, lo que quiere lo conoce en detalle, pero quiere menos de lo que cree.

En cuanto a metodologías ágiles, a mi personalmente no me gustan demasiado. Como sabe la gente que me conoce, la única que me gusta, en parte, es SCRUM, y solamente para el proceso de construcción (diseño detallado y programación); creo que a las metodologías ágiles les falta una parte indispensable para quiénes hacemos proyectos para terceros, que consiste en acotar los requisitos de entrada hasta un nivel suficiente como el riesgo de variación que el cliente o el equipo esté dispuesto a aceptar.

Me pasó mi amigo José Luis Martínez el siguiente enlace, que ilustra bien los problemas de los que carecen las metodologías ágiles (entendiendo siempre que estamos generalizando):
The Great Pyramid of Agile

saludos y gracias


estefania said...

por que tanta bronca contra el software???
yo les paso un enlace que para varios va aser util:
http://www.hispanosnet.com/software/

saludos!