archivo

Archivo de la etiqueta: calidad del código

En el entorno de personas con las que trabajo existen serias dudas de que la metodología de desarrollo guiado por las pruebas o Test-Driven Development, sea ágil, en el sentido de que entienden que si se aplica de manera ortodoxa o si bien las pruebas unitarias se desarrollan después, se pierde capacidad de trabajo efectivo por parte del equipo de proyecto.

Nunca he participado en un proyecto que siga esta metodología y en los desarrollos en los que he trabajado la importancia que se le da a las pruebas unitarias es muy escasa, por lo que no puedo aportar mi experiencia para opinar sobre las bondades o no de esta metodología, de manera que me tendré que centrar en lo que he leído sobre ella.

No obstante, hay que tener en cuenta una cosa. Agilidad no es lo mismo que desarrollar más rápido o por lo menos no es su objetivo principal, ya que si bien es cierto que la aplicación de metodologías ágiles, eliminan muchos aspectos que son prescindibles en un proyecto de desarrollo de software y por lo tanto pueden optimizar tiempos de desarrollo, el objetivo último de las mismas es conseguir productos software de calidad, que proporcionen satisfacción al cliente, dentro de unos plazos y presupuestos definidos (siempre y cuando, ambos sean realistas y acordes a la naturaleza del proyecto y al nivel de calidad que se espera del producto software), es decir, que no se produzcan los factores que derivan en la crisis del software.

El desarrollo guiado por las pruebas, fue introducido (o reintroducido) por Kent Beck, creador de la metodología de programación extrema y en cierto modo la segunda es una consecuencia natural de la primera, si bien ambas pueden utilizarse sin problemas por separado.

La metodología TDD a grandes rasgos es fácil de exponer:

– Se construyen las pruebas unitarias (o se puede extender si se desea el concepto a otros tipos de pruebas de más alto nivel, siempre y cuando sea automatizable su ejecución).

Como estos casos de prueba están construidos antes desarrollarse el componente software sobre el que se va a trabajar, van a fallar a la primera. De hecho se considera necesario verificar que fallan porque si no es así, querría decir que el test está más construido (¿por qué no?) o que el componente software ya está desarrollado (en proyectos donde se trabaja con sistemas de mediana o gran envergadura y con un número de desarrolladores alto, puede pasar que el componente o módulo ya se haya implementado previamente, bien porque le ha hecho falta a un compañero para otra funcionalidad o bien porque no se ha verificado que efectivamente ese componente ya estaba desarrollado).

Para la construcción de los casos de prueba, los desarrolladores deben basarse en las especificaciones indicadas en los casos de uso o en las historias de usuario. Ahí radica la importancia que tiene la construcción de las pruebas unitarias antes del desarrollo del componente, ya que implica un mayor enfoque en los requisitos, una mayor necesidad de comprender la funcionalidad y comportamiento deseado, es decir, implica comprender el problema, conocer los resultados esperados, antes de empezar a desarrollarlo.

La ventaja de desarrollar las pruebas antes de implementar los componentes es la indicada en el párrafo anterior, es decir, enfrentarse y comprender el problema antes de empezar a resolverlo.

Si las pruebas unitarias se construyen después, no estaríamos hablando de TDD, eso es importante, por lo que lo repito, si las pruebas unitarias se construyen después se trata de otra estrategia de desarrollo de software, no de desarrollo guiado por las pruebas.

Pese a que como he comentado, no se ha fomentado en los proyectos en los que he participado la construcción de pruebas unitarias, soy de la opinión de que es favorable tener una buena cobertura de código, por lo que la existencia de pruebas unitarias, antes o después de implementar los componentes, permite detectar de manera rápida la existencia de efectos colaterales o desarrollos erróneos de métodos o clases.

¿Por qué no lo hemos fomentado? Es una suma de varios factores, por un lado pese a que entendemos los beneficios que puede proporcionar, no tenemos del todo claro su retorno de la inversión, pese a que es objetivo que la deuda técnica se reduce en proporción a la cobertura, por otro lado, los proveedores con los que hemos trabajado tampoco utilizan esta práctica en sus desarrollos. Por tanto y en resumen, la falta de experiencia nuestra y de los proveedores hace que nos más dar el paso y prioricemos otros aspectos en el proceso de desarrollo y en la calidad del diseño y de la codificación.

– A continuación se construye el componente software que debe verificar las reglas de funcionamiento definidas en las pruebas.

Una vez desarrollado, se pasa el test y si funciona adecuadamente, se pasa de nuevo todo el juego de pruebas, si hay errores, se vuelve a revisar el componente, si todo ha ido bien, se pasa a la siguiente fase.

– Una vez que se tiene un software que verifica las pruebas implementadas, se procede a su refactorización.

El objetivo de la utilización de esta técnica es evidente, desarrollar software con el menor número de fallos posible, reduciendo además los errores debidos a efectos colaterales en el desarrollo, respetando también la calidad de diseño y de codificación para favorecer la comprensión y capacidad de mantenimiento del software.

Se sabe que cuanto más tarde se detecten los errores más esfuerzo se requiere para solucionarlo, esta técnica pretende disminuir el riesgo por la presencia de errores de ese tipo, además de facilitar un código donde sea mucho más fácil trabajar, tanto para corregir esas incidencias como para contruir nuevas funcionalidades o modificar, si fuera necesario (el software es de naturaleza adaptativa), las ya implementadas.

Espero poder probar más pronto que tarde esta metodología en alguno de los proyectos en los que participo y poder verificar personalmente las ventajas que tiene la utilización de esta estrategia de desarrollo.

En el artículo anterior, se analizaron algunos de los principios que surgen de los cuatro valores o principios fundamentales que se especifican en el manifiesto ágil, en este se va a proceder a analizar los que restan:

– La atención continua a la excelencia técnica enaltece la agilidad.

No se pueden realizar desarrollos ágiles con software desarrollado con mala calidad. La deuda técnica impedirá avanzar en los desarrollos de manera eficiente y productiva ya que se necesitará más tiempo para comprender el funcionamiento de un módulo o de una clase y existirán más riesgos de efectos colaterales en el mantenimiento del software o en su desarrollo mediante iteraciones.

Si se quiere minimizar la documentación, incluso la que se realiza en el código mediante los comentarios es necesario que la claridad del código sea la mejor posible, así como su ejecución técnica. De esta forma los fuentes estarán autodocumentados y no será necesario realizar ajustes en los comentarios conforme la aplicación vaya evolucionando porque la comprensión del código está implícita en él.

– La simplicidad como arte de maximizar la cantidad de trabajo que no se hace, es esencial.

Una de las virtudes y también, si no se maneja adecuadamente, uno de los grandes defectos de los que nos dedicamos al desarrollo de software lo tenemos en nuestra creatividad. Tenemos por costumbre aportar nuestro granito de arena en los proyectos y en muchos casos lo que hacemos nos es otra cosa que complicar lo que los usuarios (cliente) nos ha solicitado.

Funcionalidades, las justas y necesarias. Complejidad, la justa y la necesaria. Todo lo que vaya más allá de esto es trabajo de más, cuya recompensa será inferior en la mayor parte de los casos al esfuerzo realizado. No debemos olvidar que todo esfuerzo de más que invirtamos en una tarea, es esfuerzo de menos que dedicamos a otras tareas que necesita de ello (en cierto modo es uno de los ejes en los que se sustentan los métodos de producción mediante kanban).

– Las mejores arquitecturas, requisitos y diseños emergen de equipos que se autoorganizan.

La interacción entre personas, la comunicación entre las mismas, la unicidad de los equipos de trabajo favorecen la toma de decisiones. Nadie es tan listo o bueno como para que sus ideas sean mejores que las que proporcionan el resto de personas que participan en el proyecto, donde no llega la perspectiva de uno, llegará la de otro y si no llega la de ninguno seguro que una decisión tomada entre varios tendrá más posibilidades de acercarse más a la realidad (o alejarse menos de ella) que la que toma uno de manera individual.

La integración del equipo de trabajo permite que cada cual pueda aportar más en el área donde sea más fuerte. Esta forma de trabajar favorece el reparto de tareas en función de las habilidades de cada uno, de sus circunstancias personales.

Para ser ágil, es necesario además que los equipos tengan la oportunidad de tomar decisiones. Hay aspectos relativos a la ejecución del proyecto que perfectamente pueden ser tratados y tenidos en cuenta por quienes participan en él. Se podrá estar equivocado o acertado, pero existirá un menor margen del error si las decisiones se toman desde el interior del proyecto que desde fuera, ya que quienes trabajan en el mismo conocen de primera mano la problemática que se está produciendo.

Esto es compatible con la existencia de un marco de trabajo o de una metodología porque todas ellas son o deben ser lo suficientemente abiertas como para dar la oportunidad de realizar ajustes que favorezcan la realización de los trabajos.

– En intervalos regulares, el equipo reflexiona sobre la forma de ser más efectivo y ajusta su conducta en consecuencia.

El fracaso es la antesala del éxito. Los errores son un medio para continuar aprendiendo. Todo es susceptible de mejorar, pero para ello es necesario realizar un análisis de lo que se está haciendo lo más objetivo posible, basado siempre que se pueda en métricas que sean evaluables y repetibles.

Las mejoras en los procesos, metodologías, técnicas, decisiones, etc… no llegan de una sola vez, son el resultado de diferentes iteraciones, igual que los desarrollos. Los proyectos son adaptativos, las organizaciones cambian, la tecnología evoluciona, nosotros también.

Nunca se es lo suficientemente experto, nunca se es lo suficientemente bueno, incluso los mayores expertos en ingeniería del software del mundo se equivocan y pueden fallar en proyectos donde nosotros podemos tener éxito y tener dudas en los mismos aspectos en que podamos tenerla nosotros.

El objetivo no es saberlo todo sino en intentar ser cada vez mejor, esto requiere de analizar nuestros resultados, de ser autocríticos y a partir de ahí sacar conclusiones y crecer.

Continuemos con el análisis del manifiesto ágil.

La Ley de Eagleson viene a decir que (traducción libre): “Cualquier código que hayas desarrollado y que no lo hayas revisado desde hace seis meses o más parecerá que lo hubiera escrito otro”.

Esta situación es muy común y he escuchado distintas versiones de lo mismo a muchos programadores. El motivo generalmente es que conforme se va adquiriendo experiencia y nuevos conocimientos se va mejorando (y cambiando) el estilo de programación.

A esto hay que añadir la aparición de nuevos frameworks, librerías, versiones de las mismas, etc…, la necesidad de adaptarte a los requirimientos técnicos de los distintos proveedores, así como el hecho de trabajar con distintas tecnologías y/o lenguajes de programación.

En el anterior artículo comencé con el análisis del primero de los cuatro principios o valores que componen el manifiesto ágil. Ahora le toca el turno al segundo principio:

Principio 2: Valorar el software que funciona, por encima de la documentación exhaustiva.

La finalidad última de todo desarrollo de software es obtener un producto que satisfaga las necesidades de quienes los vayan a utilizar. Todo lo demás está uno o varios escalones por debajo.

Por tanto si una aplicación funciona tal y como quería el cliente, de manera que pueda realizar su trabajo de manera eficiente y productiva se habrá conseguido un éxito…¿o no?.

Es un éxito hoy, pero mañana puede suponer una fuente de problemas.

Entregar un software sin errores es muy complicado (no digo que sea imposible), de hecho es tal el esfuerzo que habría que hacer por parte de los que lo revisan y tal el esfuerzo que tendría que hacer por parte del desarrollador para que un software se entregue sin errores, que no resulta rentable llegar a ese extremo (salvo que se trate de un software que por sus características específicas y criticidad requiera la realización de ese esfuerzo, el cual, para que sea efectivo debe ser tenido en cuenta en el presupuesto del proyecto), esto requerirá tareas de mantenimiento correctivo, que no deberían ser muchas ni complicadas, porque si así fuera no deberíamos considerar que el software que se ha entregado funciona.

Los requisitos cambian y el software se tiene que adaptar a esos cambios, lo que hace que los sistemas de información requieran de tareas de mantenimiento evolutivo.

La realización de tareas de mantenimiento correctivo y evolutivo (como también ocurriría con el mantenimiento adaptativo y perfectivo) implica trabajar con el código fuente de la aplicación. Si la codificación no es buena: dificultad en la legibilidad y comprensión del código, alto acoplamiento, baja cohesión, el mantenimiento del sistema se puede convertir en una tortura, cuyo coste será proporcional a la deuda técnica existente.

No basta solo con que el software que se entregue funcione, la calidad del código es importante de cara a futuros mantenimientos.

En este principio se pone en una balanza el funcionamiento del sofware sobre la existencia de una documentación exhaustiva y es algo en lo que estoy totalmente de acuerdo.

El software cambia, por lo que si la documentación no cambia con él (y no me estoy refiriendo solo a la que se encuentra recogida en ficheros ofimáticos, herramientas CASE o la compuesta por los propios comentarios que aparecen en el código), tenemos documentación que cada vez servirá para menos, hasta que llegue a un punto de que más que ayudar a la comprensión del sistema, le perjudique.

Mi visión sobre la documentación (salvo las actas que se quieran elaborar de reuniones o documentación adicional que se quiera elaborar, como por ejemplo, esquemas de interfaz de usuario, etc….) es que se realice sobre herramientas CASE, ya que facilita la trazabilidad de los diferentes componentes documentales y que sea la justa y necesaria para el proyecto en el que se está trabajando, es decir, ni más, ni menos.

La documentación debe servir para que los programadores sepan qué funcionalidad es la que tienen que desarrollar, por lo que la misma debe ser concisa y sin ambigüedades. Todo lo que sea ambiguo tenderá a ser rellenado en la mayoría de los casos por la interpretación que del problema haga el programador, la cual además será errónea en la mayor parte de los casos y no porque el programador sea bueno o malo sino porque lo más habitual es que el contacto entre usuario y programador haya sido escaso o nulo, y por tanto difícilmente ha podido captar sus necesidades y sensaciones.

Por tanto, documentación, la necesaria, de calidad y actualizada (debiéndose mantener actualizada toda aquella que no se pueda obtener por ingeniería inversa). Si además a partir de ella se puede generar código pues mucho mejor.

¿Tiene la documentación alguna misión más que la de servir de apoyo al proceso de desarrollo? Si tenemos un sistema de información grande en el cual hemos podido tener diferentes proveedores trabajando y se quiere sustituir un proveedor por otro, lo mejor es que haya un soporte documental técnico que facilite la compresión del nuevo proveedor lo antes posible (también lo podría hacer interpretándolo a partir del código, pero puede resultar complejo si el mismo no es muy bueno y si el sistema es de gran tamaño).

Además, si desarrollas un producto tener ciertas partes documentadas vende (y no es ya cuestión de lo que puedas pensar como desarrollador de la utilidad de la documentación) sino de lo que pueda pensar quien te va a comprar la aplicación.

En resumen, lo primordial es que el sistema de información que se ha desarrollado se ajuste lo máximo posible a las necesidades del usuario con el menor número de errores posible pero sin olvidar que también debe ser desarrollado con un código de calidad y se ha debido generar una documentación que debe ser la mínima necesaria para la realización y comprensión del sistema, que también debe ser de calidad y actualizarse, salvo aquellas partes que se puedan obtener de forma rápida y sencilla mediante ingeniería inversa.

Continuemos con el análisis de los principios del manifiesto ágil.

La metodología de programación extrema fue introducida por el americano Kent Beck (autor también de la metodología de desarrollo guiado por las pruebas (TDD: Test-driven Development) y coautor de JUnit) en el año 1999, aunque empezó a trabajar en la misma años antes, concretamente desde el año 1996 cuando fue contratado por Chrysler Corporation, para intentar sacar adelante una aplicación para nóminas que hasta entonces tenía importantes problemas en el desarrollo. Cuando empezó a trabajar en el proyecto, detectó una serie de aspectos en el proceso de desarrollo que debían cambiar, aplicando para ello una serie de estrategias, muchas de ellas basadas en buenas prácticas ya contempladas y utilizadas.

La programación extrema se sitúa en una posición diferente a los ciclos de vida tradicionales. Ya no se trata de requisitos que se cierran en etapas tempranas del desarrollo y que constituyen el contrato de lo que posteriormente se va a desarrollar (y que los usuarios no ven hasta mucho después) sino de requisitos que están vivos y que son modificables a lo largo del ciclo de vida.

La programación extrema se centra en cinco principios:

– Simplicidad: Conforme en el proceso de construcción un sistema va creciendo paulatinamente (aplicable también a mantenimientos sobre sistemas ya construidos), la complejidad del código va creciendo de manera proporcional (o incluso exponencial en función del tamaño del proyecto y del número de personas que participen en el proceso).

Mediante la refactorización, se intenta mantener el código en unas condiciones donde la complejidad esté controlada y facilite la escalabilidad del sistema. Esto requiere disciplina y creer que esta metodología produce resultados ya que resulta complicado tomar la decisión de tocar código que ya funciona (esto va en contra de una de las máximas de la programación que consiste en que no toques algo que funciona, aunque también es cierto que la misma viene derivada de las malas experiencias provocadas por la crisis del software).

La integración continua resulta esencial en esta metodología, ya que ofrece la oportunidad de probar con una cierta regularidad la integración de los componentes, de manera que este tipo de problemas se puede detectar lo antes posible.

El control de la calidad del código se complementa con otras estrategias como por ejemplo el intento de que el mismo sea lo más autocomentado posible (sin prescindir de comentarios cuando sean necesarios). ¿Por qué la metodología prioriza la autodocumentación? Como el proyecto es algo que está vivo, el código se modifica con cierta frecuencia (sobre todo en el proceso de construcción), ¿por qué preocuparse en comentar un código que tal vez tenga que modificar muy pronto ya sea por una modificación funcional, por una corrección o por una refactorización? A esto hay que añadirle el peligro de que empiecen a quedarse atrás comentarios que no se han eliminado y que no se correspondan con la realidad del código. Si el código está autodocumentado evoluciona de la misma manera que lo hace el proyecto.

Para esta metodología lo más importante del proceso de desarrollo de software es el código, la base para esto tiene un razonamiento simple, sin código no hay aplicación. Se considera que una aplicación que funciona según las necesidades del cliente tiene mucho más peso que el hecho de que esté documentada al detalle.

Para sostener esta afirmación en sistemas de un cierto tamaño es fundamental un código de mucha calidad. De no ser así, el cambio de un equipo de desarrollo por otro puede provocar un riesgo importante para conseguir una continuidad en el mantenimiento del proyecto ya que se estará caminando por un terreno lleno de trampas y con poca luminosidad.

– Comunicación: Fluida y continua. Para ello se programa por parejas (pair-programming, un ordenador, dos personas) y los usuarios designados por el cliente forman parte del equipo de desarrollo (se eliminan fronteras). Pero la comunicación va más allá de eso, un código comentado (autodocumentado) y con pruebas unitarias definidas expresa información para la comprensión del mismo, es como una caja del tiempo o un mensaje en una botella y que será muy útil cuando se tengan que realizar modificaciones.

Algunos de los críticos de esta metodología comentan que la tendencia de los programadores a considerar el código desarrollado como propio dificulta el proceso de comunicación ya que cada cual considera que sus opiniones y decisiones son y han sido las mejores, que su código es difícilmente superable (o por lo menos que era complicado hacerlo mejor en el tiempo que se ha dispuesto para desarrollarlo) y además no se suelen aceptar de buen grado las correcciones (sobre todo si están relacionadas con la calidad).

Para resolver ese inconveniente la programación extrema considera que el código es colectivo, no hay parcelas, de manera que cualquier integrante del equipo de proyecto puede realizar contribuciones a cualquier parte del mismo.

Las pruebas unitarias resultan esenciales, ya que permiten automatizar la revisión del funcionamiento de cada módulo y así tener la posibilidad de realizar este tipo de tareas con frecuencia. Hay que tener en cuenta también que el código está en continua evolución por lo que las pruebas de regresión cobran importancia. El objetivo es detectar posibles errores lo antes posible. La detección tardía de errores es más costosa y su corrección además tiende a ensuciar el código (cuando el tiempo aprieta lo importante es apagar el fuego).

Aunque no es obligatorio, se recomienda incluso que las pruebas unitarias de cada componente estén construidas antes de desarrollarlo.

Otro aspecto característico de la metodología son las reuniones diarias, que se realizan de pie y en círculo (stand-up meetings) y que tienen una duración aproximada de quince minutos. En las mismas se habla sobre el estado actual del proyecto y sobre contingencias, problemáticas o dudas que se produzcan en el mismo.

Para favorecer la comunicación se aconseja que todo el equipo de trabajo se encuentre en la misma ubicación física y en entornos despejados.

– Retroalimentación: La participación y proximidad de los usuarios permite resolver dudas casi de forma instantánea, pueden ver funcionalidades concretas construidas parcialmente y opinar sobre ellas. Se comparten opiniones sobre cuál puede ser la mejor solución (es importante lo funcional pero hay que equilibrar lo que se quiere con la complejidad de realizarlo, como dijo Voltaire, lo perfecto es enemigo de lo bueno)

El desarrollo iterativo incremental permite que en cada evolución el usuario pueda expresar su opinión sobre los resultados obtenidos y si es necesario corregir algo, planificarlo para la siguiente o próximas iteraciones.

– Coraje: Optar por esta metodología no es sencillo por muchos factores, por muchos interrogantes. ¿Es sencillo admitir que se programe por parejas?, es decir, ¿puede todo el mundo entender que en cada momento uno toque el teclado y el otro mire?, ¿se puede comprender que esta estrategia no tiene por qué afectar a la productividad?.

La programación en parejas tiene una serie de ventajas:

Las decisiones en la codificación no son algo unilateral de la persona que programa el componente (los arquitectos o analistas orgánicos no pueden llegar a todo el detalle de la programación, ya que ellos determinan el armazón de la aplicación que librerías utilizar, su división en capas, etc…, es decir, establecen el marco general).

El código es revisado en tiempo real, disminuyendo la probabilidad de error e incrementando la calidad del código.

Pero no es solo lo anterior, ¿puede ser admisible que se retoque software que ya funciona con el objeto de mejorar su calidad (simplicidad)?, ¿se puede vivir en un proyecto donde los requisitos están siempre en el aire?, ¿es sostenible un proyecto orientado a entregas continuas cada poco tiempo donde el cumplimiento de los plazos resulta de gran importancia?.

Sobre esto último algunos de los críticos con la metodología consideran que el equipo de trabajo está vendido a las entregas y que al haber muchas y frecuentes, los errores en la planificación provocarán numerosos picos de trabajo con el consiguiente overtime para los distintos integrantes del equipo de proyecto.

Sin embargo los defensores sostienen que el mismo Kent Beck considera que es necesario evitar el cansancio de los componentes del equipo de proyecto, debiéndose respetar su jornada laboral, situándose esta en cuarenta horas semanales. De hecho considera que no se debe haber overtime dos semanas consecutivas. Aplica por tanto el principio de responsabilidad en el sentido de que hay que tener disciplina con las entregas pero que eso no puede estar por encima de un continuo sobreesfuerzo de los integrantes del equipo de trabajo. ¿Por qué defiende esto? Pues porque los programadores cansados escriben código de peor calidad y además son menos productivos.

– Respeto: Algo complicado de encontrar en los proyectos de desarrollo de software y en un mundo tan ombliguista como es este. Se basa en el hecho de que todos los participantes en el equipo de proyecto suman y que es importante que se tenga en cuenta que para que todo vaya bien, todos tienen que dar lo mejor de sí y para que esto se pueda producir hay que crear un ambiente que lo propicie. Las críticas deben ser constructivas, siempre para mejorar, siempre para ir hacia adelante. Es importante que se tenga en cuenta que para que el barco vaya hacia adelante todos tienen que remar y que si se hunde se hunden todos.

Por otro lado cada participante debe asumir su responsabilidad, cada cual tiene su rol y debe entender que tras él hay una serie de tareas que se tienen que realizar, gustén más o gusten menos.

En el siguiente artículo sobre este tema se tratará sobre el ciclo de vida/metodología de la programación extrema.

Pensando en las posibles consecuencias del uso de metodologías ágiles en la calidad de la codificación, me vino a la cabeza el algoritmo de planificación de Wexelblat (atribuido a Richard L. Wexelblat).

No quiero decir que necesariamente tenga consecuencias, ni que esté en contra de las metodologías ágiles (antes al contrario), mi única intención es crear una reflexión.

El algoritmo de planificación de Wexelblat es el siguiente:

Elige dos:

– Bueno.
– Rápido.
– Barato.

Asunto espinoso. Las metodologías ágiles están orientadas a la entrega de productos funcionales que vayan completando mediante iteraciones sucesivas y a través del feedback del usuario un sistema completo acorde a las necesidades del usuario (por tanto, un sistema de calidad), dentro los plazos y presupuesto establecido.

¿Es incompatible con lo anterior la calidad del código? Por supuesto que no, pero, ¿es lo más importante? Tampoco lo es.

El objetivo es conseguir que un sistema sea satisfactorio para el usuario, sin eso de nada vale lo demás y eso se consigue mediante aproximaciones sucesivas teniendo como soporte a un usuario que es aliado y que está comprometido en el proyecto.

Si nos centramos exclusivamente en el objetivo y no vemos más allá, la calidad del código queda en un octavo o noveno plano, es decir, el sistema es lo que el usuario quería, ¿para qué pedir más?. Si el sistema no se va a tocar nunca más, si se van a realizar modificaciones mínimas en el mismo o si no presenta problemas de rendimiento por una mala codificación y/o arquitectura, puede tener sentido que no importe mucho lo que está dentro (la máquina me da buen café y no requiere mantenimiento, ¿qué más me da cómo se hayan construido los circuitos que la hacen funcionar?).

Ahora bien, si se prevén modificaciones de cierta envergadura en el proyecto o que las mismas pueden existir, sí que entra en juego la calidad del código, ya que la deuda técnica del software puede hacer muy costoso el mantenimiento (y hacerte recordar a los ancestros de quiénes codificaron el sistema).

Esta misma idea podría ser aplicable a las sucesivas iteraciones en la construcción del producto. Hay que tener en cuenta que en cada iteración además de nuevas funcionalidades, se corrigen aspectos funcionales y no funcionales del sistema de acuerdo a las directrices del usuario y del equipo técnico del proyecto. Una mala arquitectura, una mala codificación, puede condicionar las sucesivas evoluciones del producto, haciéndose cada vez más pesadas y costosas, lo que obligaría a ser menos ambicioso en cada iteración y requiriéndose un mayor número de iteraciones para obtener el sistema, lo que puede provocar que se ponga en riesgo el cumplimiento de plazos y el presupuesto.