Archivo

Archivo de la etiqueta: mantenimiento

¿Realmente se puede decir que el producto está terminado antes de que finalice su ciclo de vida? La realidad es que no es así, incluso en aquellos casos donde se encuentre sin evolucionar durante años.

Es más correcto decir que un proyecto se ha terminado que indicar que el producto está terminado porque lo contrario sería suponer que el producto no va a sufrir más modificaciones.

Precisamente el problema de los responsables técnicos de los sistemas de información (que también debería serlo por parte de los propietarios del producto) es que en cualquier momento pueden surgir necesidades de evolución y lo mismo no hay posibilidades en ese momento de dar respuesta a la misma en la medida y forma que se necesita. Es decir, si tienes una vinculación con el producto y no con el proyecto no vas a poder separarte de él, salvo que cambies de empresa, de departamento o tu jefe te indique otras prioridades (aunque, como sabes, seguirás realizando por mucho, mucho tiempo tareas relacionadas con ese sistema).

El prototipado puede ir desde fórmulas muy simples como dibujos realizados a mano alzada a desarrollos que tienen una cierta lógica implementada. Son muy útiles ya que permiten trabajar sobre algo material y no sobre ideas de carácter abstracto. Nunca van a poder sustituir a la funcionalidad una vez implementada en toda su extensión pero sí que permiten desarrollar con más intención.

Este antipatrón surge cuando no se hace un uso adecuado del prototipo, no se interpreta o se comunica adecuadamente su función y utilidad, pudiendo abarcar diferentes áreas:

- El responsable funcional aprueba el prototipo pero no se ha llegado a un suficiente nivel de detalle en el comportamiento, esto puede provocar que una vez implementado no se alcancen (incluso nos hayamos quedado bastante lejos) las expectativas puestas en la funcionalidad. También puede pasar que se piense que el desarrollo es más simple o más complejo que lo que realmente es.

- En entornos de negociación cerrados, en los que solo existe el contrato como objeto de debate, si se cierran términos del mismo (alcance y coste) en base a un prototipo con muchos detalles por concretar, se corre el riesgo de que las estimaciones realizadas sean fallidas y el cliente se niegue a replantear el alcance del proyecto alegando que se conocía perfectamente el alcance ya que había un prototipo que respondía a todas las dudas.

- Los clientes también incurren en un riesgo importante si consideran un prototipo como la base fundamental para realizar una valoración del alcance, sin haber evaluado si el conocimiento que proporciona es suficiente como para hacerla reduciendo la probabilidad de que haya desviaciones sensibles.

En los dos casos anteriores, el problema lo tenemos por un lado en la falta de flexibilidad a la hora de abordar cambios en el alcance y/o de aportar más recursos económicos al proyecto (y esto ocurre trabajando con o sin prototipos) y por considerar los prototipos como una versión real pero de juguete del producto final, algo que no será así porque a lo largo del proceso de desarrollo los usuarios cambiarán de prioridades, descubrirán nuevas funcionalidades a implementar, etc…, es más, incluso en el caso de que el prototipo sea de una funcionalidad, la implementación real sacará a la luz problemas: de carácter tecnológico, de integración, funcional, etc…, muchos de los cuales son complicados de prever cuando se está trabajando con el prototipo.

Es decir, el prototipo es un facilitador para desarrollar con intención pero nadie (cliente y proveedor) debe tomarlo como la verdad absoluta y que en base a ellos se tomen decisiones inamovibles.

- Si se dedica mucho esfuerzo al prototipo es posible que se caiga en la tentación de convertirlo en el producto definitivo. Esto supone un riesgo importante porque lo más posible es que su desarrollo se haya realizado sin tener en cuenta aspectos relacionados con la calidad y mantenibilidad del software, lo que después puede dar lugar a importante costes de evolución del producto, falta de robustez, efectos colaterales en cada versión, etc…

Este antipatrón surge como consecuencia de múltiples cambios en una aplicación que se llevan a cabo de forma simultánea en el mismo, de manera que es posible que se haya aplicado la misma solución en diferentes partes del código, de manera que tendremos clases y/o métodos con un comportamiento parecido aunque tengan codificación diferente.

También es posible que se haya llegado a él, no por el hecho de no poder controlar la programación de personas distintas en diversas funcionalidades de la aplicación, sino por la mala práctica de ir copiando secciones de código, realizando las modificaciones oportunas, achacándolo a las prisas y a la presión por la entrega y/o por terceros.

Como consecuencia tenemos un código más complejo, con más deuda técnica y, por tanto, con un mayor esfuerzo de evolución y mantenimiento (hay que tener en cuenta que es posible que con estas prácticas, para hacer un cambio sea necesario hacer modificaciones en tantos puntos como ese código haya sido replicado).

Contar con presupuesto te permite el suficiente margen de maniobra para solucionar los posibles problemas que puede tener un sistema de información. Sin embargo, el dinero por sí mismo no arregla nada si las decisiones que se toman son incorrectas, si no se desarrolla con intención o no se resuelven los problemas que existen de raíz.

Puedes echar decenas y decenas de miles de euros a un sistema y no incrementar proporcionalmente su valor.

Este antipatrón surge cuando se cuenta con un importante presupuesto que bien utilizado podría mejorar el producto pero que en lugar de centrarse en los problemas existentes en el sistema, se invierte en un crecimiento desproporcionado y/o difícil de controlar del sistema que mezcla la resolución de esos problemas con una ampliación funcional generalmente de aspectos secundarios.

En esta situación se divide el enfoque y el presupuesto entre lo principal y lo accesorio poniendo ambos al mismo nivel, a la que vez que se dota de una mayor complejidad al sistema, generándose resistencias que afectan al directamente al esfuerzo (y coste) necesario para desarrollar. Por tanto, el presupuesto para arreglar los verdaderos problemas del sistema queda debilitado a la vez que la deuda técnica va creciendo y en consecuencia los costes de desarrollo.

Llegado a un extremo (y a veces no es necesario escorarse tanto) nos habremos “comido” el presupuesto y los problemas (o la mayoría de ellos) seguirán ahí, y lo que es todavía peor, con otros nuevos que posiblemente se han añadido, con un producto más complejo de evolucionar y con una confianza muy erosionada por parte del cliente o del área usuaria (independientemente de que ellos hayan tenido mucho o poco que ver en la priorización de las tareas y en la estrategia utilizada).

Llegado un punto resulta más costoso seguir mejorando un sistema de información que los beneficios que realmente produce esa mejora.

Si el producto está consolidado los cambios serán cada vez más complejos (rizar el rizo) y responderán generalmente más a caprichos que a necesidades reales. No se trata de oponerse a la evolución sino de entender cuándo produce beneficios y cuando no.

Cuanto más grande sea el producto más complejo será mantenerlo, probablemente mayor será su deuda técnica y más complicado será para el usuario (y eso es un problema).

Cuanto más cambios hagamos más posibilidad hay de que introduzcamos errores graves en la aplicación, los cuales pueden tener un efecto bola de nieve en el sistema porque si la aplicación ha tenido éxito y tiene un amplio grado de implantación se requerirá una rápida solución y todos sabemos qué pasa cuando se va demasiado deprisa: posiblemente no se corrigen todos los errores, se introducen otros y el código no tiene toda la calidad que debería.

Desde el punto de vista del usuario nunca vas a encontrar la perfección en un software, cuando creas que al usuario no se va a ocurrir nada nuevo le surgirá una nueva idea y cuando realmente se quede sin ideas aparecerá otro con un listado sin fin (cada persona tiene percepciones y necesidades distintas).

Tampoco la vas a encontrar desde el punto de vista del desarrollador, siempre tendremos la oportunidad de mejorar el código o la arquitectura, de automatizar nuevos tests, de abstraer funcionalidades, de modificar el comportamiento de una funcionalidad o de hacer nuevas propuestas.

Donald Norman realizó una reflexión que viene a refrendar lo que comento en el artículo: “Una vez que se ha alcanzado un producto satisfactorio, realizar más cambios puede ser contraproducente, especialmente si el producto tiene éxito. Tienes que saber cuándo parar”.

El desarrollo de software es un continuo adelante y detrás no solo fruto del feedback o del cambios en las especificaciones sino también como parte del proceso de construcción. ¿Quién no tiene que corregir errores?, ¿quién no mejora una sección del código que no termina de convencerle?, ¿quién no tiene que realizar ajustes como consecuencia de evolución solicitada por el área usuaria?.

Este tema lo traté en artículo: “¿Qué es el mantenimiento?” y lo vuelvo a hacer ahora porque realmente el hecho de que en el desarrollo de software la frontera entre la construcción y el mantenimiento sea tan débil (por no decir inexistente) me parece muy interesante ya que refleja un aspecto inherente al desarrollo de software como es su naturaleza evolutiva, es decir, el sistema se desarrolla poco a poco y con el paso del tiempo va adquiriendo forma, en todo ese proceso hay evolución y no solo por los aspectos funcionales (o no funcionales) que se van añadiendo, modificando o eliminando sino porque en ese proceso el software también cambia y no necesariamente para cambiar una funcionalidad (refactorización, corrección de incidencias, etc…).

Esta naturaleza evolutiva junto a otra característica inherente al proceso de desarrollo como es la incertidumbre ponen de manifiesto que el software estará sometido a cambios a lo largo del proyecto (por muy diversas causas) y que será necesario habilitar los mecanismos necesarios para que la adaptación a los mismos se realice lo antes posible.

Me gusta el enfoque que Dave Thomas da sobre este tema (traducción libre): “Si nos fijamos en el tiempo que pasamos programando, escribimos un poco y luego volvemos atrás y hacemos un cambio. O volvemos atrás y corregimos una incidencia. O lo tiras todo o lo reemplazas por otra cosa”.

Textual. Esto me lo comentó un amigo cuando estuvimos conversando sobre la importancia de la deuda técnica en la mantenibilidad del software.

¿Cuál era el contexto de esa frase? Pues el típico proyecto Death March Project: presupuesto muy por debajo de las necesidades del proyecto, plazos irreales y un equipo de proyecto con desarrolladores de muy escasa experiencia para intentar que la diferencia entre costes y presupuesto no fuera abismal (aunque todos sabemos que lo que te puedes ahorrar en precio/hora lo vas a perder por el tiempo de más que requieren para desarrollar y por la existencia de un mayor número de errores tanto en la programación como en las tareas de análisis).

El proyecto, por tanto, estaba condenado desde que empezó y en esas condiciones casi todo eran problemas:

- Desgaste con el cliente para intentar negociar continuamente el alcance, eliminar las peticiones que van más allá de ese alcance e intentar que los cambios en los requisitos sean los menores posibles.

- Desgaste con tus jefes que no paran de apretar por las desviaciones de los costes (precisamente esos mismos jefes que habían mal vendido el proyecto) y transmitiendo continuamente las quejas de los clientes por los retrasos, por los errores de las entregas y por discutir continuamente el alcance.

- Desgaste con tu equipo al imponer un nivel de exigencia superior al que pueden dar por su experiencia y conocimientos y por hacerles ver que es necesario hacer esfuerzos más allá de la jornada laboral.

Y todo eso para desarrollar un producto que se prevé de baja calidad y que no cubrirá todas las necesidades del usuario y que estarán todavía más lejos de sus expectativas.

En medio de ese huracán tiene sentido la pregunta que da nombre al artículo.

La calidad es una inversión económica que permite a los proyectos partir de una base a partir de la cual desarrollar un software que satisfaga las expectativas del usuario y tenga una mantenibilidad adecuada a la naturaleza del sistema de información.

Si no inviertes en el proyecto, la calidad se verá mermada al tratar de hacerlo por un importe inferior o muy inferior a lo que necesita.

No todo es dinero, el proveedor también debe invertir en el proyecto poniendo el mejor equipo posible a realizarlo acorde al presupuesto disponible. Si se decide maximizar los beneficios poniendo un equipo de menor valor el equilibrio se empieza a romper y en algún momento las cuentas no empezarán a salir, sobre todo para el cliente que verá que la calidad de los trabajos estará muy por debajo de sus expectativas (y no tardará mucho en darse cuenta), pero también para el proveedor por el coste adicional que tiene no hacer las cosas bien a la primera (a la segunda, a la tercera…) y porque además se tarda más en realizar los desarrollos.

Soy de la opinión de que el equipo de proyecto debe partir de base con la actitud y aptitud necesaria para que el desarrollo de software con la menor deuda técnica posible esté integrado en su forma de concebir sus tareas, lo cual permitirá que incluso en las peores condiciones se consiga dentro de esas restricciones hacerlo lo mejor posible (las restricciones ponen el techo y si es muy bajo así serán los resultados que se podrán conseguir, pero hay que intentar estar lo más cerca posible de ese techo).

Tenemos los extremos de tener sistemas absolutamente cerrados y tener sistemas totalmente configurables. ¿Qué extremo es el más válido? Dependerá, como es lógico, del sistema de información que se desarrolla.

Si hablamos en términos generales, un sistema totalmente cerrado, sin posibilidad de configurar nada, requiere cambios en el código para realizar cualquier tipo de modificación. En mi opinión, este comportamiento no es deseable.

Por otro lado, un sistema totalmente configurable requiere un nivel muy importante de su abstracción en su desarrollo y la definición de modelos de datos generalistas. Esto requiere un coste adicional y puede dar lugar a dificultades con la explotación de la información y el rendimiento. También, si son muchas las opciones de configuración el usuario puede perderse en ellas.

Configurable es que el comportamiento de determinadas funcionalidades, la realización de determinados cálculos o la aplicación de determinadas restricciones varíe en tiempo de ejecución (o en tiempo de arranque del servidor) pero va más allá de eso, ya que configurable también es la posibilidad de poder actualizar manualmente (sin entrar directamente en las tablas de la base de datos) los valores de las tablas maestras o de determinados parámetros. Esto que parece obvio no lo es tanto cuando ves incrustados en el código determinados dominios de datos o se le impide al usuario modificar valores de una tabla maestra.

Pese a que los generadores de código prácticamente te ahorran el tiempo de desarrollo (o buena parte de él) de la gestión CRUD existe mucha pereza en los desarrolladores a dedicarle tiempo a esto: “Total, siempre existe la posibilidad de hacerlo directamente a través de base de datos”. ¿Qué pasa después? Pues que podemos tener un sistema con doscientas tablas y un montón de ficheros de configuración y a ver quién mantiene eso. Desde luego el usuario no, por lo que la responsabilidad recaerá en el departamento TIC, debiendo dedicar unos recursos a realizar estas tareas que con el paso del tiempo suponen un mayor coste del que hubieran tenido si las cosas se hubieran hecho bien desde un principio.

Me parece muy interesante la siguiente reflexión de Dave Thomas: “Queremos que la gente vea el software como algo más orgánico, como algo más maleable y algo con el que tengas que estar preparado para interactuar con él y mejorarlo todo el tiempo”.

Esta reflexión está relacionada con una cita de Andy Hunt y Dave Thomas de su libro “The Pragmatic Programmer”: “En lugar de a la construcción el software se parece más a la jardinería” y en la justificación de dicha afirmación por parte del propio Dave Thomas (traducción libre): “En los jardines existe la suposición de que va a tener un mantenimiento constante. Todo el mundo dice que quiere un jardín que no requiera mucho mantenimiento pero al final es un jardín es algo con lo que siempre estás interactuando bien sea para mejorarlo o mantenerlo”.

Yo también veo el desarrollo de software así. La realidad demuestra que los procesos que se informatizan están en continua evolución, cambian normativas, se quiere buscar una mejora continua, se quiere ser competitivo. Por otro lado el software por sus características es un elemento que puede ser mantenido y mejorado sin necesidad de interrumpir el funcionamiento normal del sistema, incluso cuando se realizan modificaciones radicales sobre el mismo (salvo en aquellos casos donde el cambio en el proceso sea tan abrupto que haga el sistema inútil de la noche a la mañana, cosa que si bien puede pasar, no es lo más frecuente).

El software va a requerir mantenimiento (o mejor dicho, evolución), por ese motivo hay que pensar en tiempo de desarrollo la estrategia más adecuada para reducir la necesidad y los costes de mantenimiento. Desarrollar dejando eso en segundo plano después cuesta mucho dinero y problemas.

Hay un aspecto importante a tener en cuenta, un software que no tiene prevista una evolución ya sea porque el proceso o procesos que informatiza ya están consolidados en la herramienta o porque no merece la pena ya que la tecnología está obsoleta (y resulta más adecuado, por tanto, hacer un nuevo desarrollo) no debería ser tenido en cuenta a la hora de plantear un programa progresivo de reducción de la deuda técnica en una aplicación.

Que no se tenga prevista una evolución no quiere decir que no vaya a surgir nunca esa necesidad, ya que basta con que lo pienses como para que mañana mismo te vengan con una petición de cambio. Ahora bien, se trata de sacar el mayor provecho posible a los medios que tengamos y para ello es necesario priorizar dónde realizar este tipo de actuaciones.

Lo normal es que si tienes previsto un plan de evolución de un producto y el mismo presenta una deuda técnica inadecuada se intente dedicar parte del esfuerzo a mejorar la misma de manera que vaya mejorando la mantenibilidad del sistema. Lo mismo no hay posibilidad de hacer un cambio en profundidad del sistema ya sea porque el esfuerzo que se puede invertir esté bastante limitado y/o porque existen fuertes restricciones temporales pero siembre cualquier mejora que se pueda aplicar se agradecerá después.

Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 1.758 seguidores