architecture agile methodology technical-debt

architecture - ¿Cómo se puede evitar la deuda técnica mientras se mantiene fiel a Ágil, es decir, se evita la violación de YAGNI y se evita el BDUF?



agile methodology (10)

Donde trabajo, creo que la forma en que evitamos la deuda es dando vueltas rápidamente por el ciclo, es decir, mostrando la funcionalidad al usuario final y obteniendo una señal de que se debe presionar para probar o un rechazo para decir qué estuvo mal dando un requisito actualizado. Al hacer esto repetidamente dentro de una iteración, se pueden encontrar muchos cambios sobre lo que quiere el usuario al probar esto y aquello.

Un punto clave es tratar de hacer exactamente lo que el usuario quiere ya que violar más YAGNI y trae BDUF, mientras que la idea de refinar los requisitos una y otra vez está en el corazón de Agile en mi mente.

Deuda técnica a través de Martin Fowler , a través de Steve McConnell

YAGNI (No vas a necesitarlo) a través de Wikipedia

BDUF (Big Design Up Front) a través de Wikipedia

ACTUALIZACIÓN: Para aclarar la pregunta, creo que también puedo decirlo de esta manera y mantener mi significado:

"¿De qué manera, como un especialista ágil, encuentra el equilibrio correcto entre" rápido y sucio "(riesgo técnico involuntario al intentar adherirse a YAGNI) y sobreingeniería (BDUF) dentro de cada iteración?"


El problema puede estar realmente en un nivel más alto: con los propietarios de la gestión y del producto preocupados por los plazos en lugar de por los propios desarrolladores.

En mi último lugar de trabajo, trabajé en código heredado, pero estuve en contacto con personas que desarrollaban código nuevo usando (supuestamente) Agile y TDD.

Ahora se supone que TDD es rojo - verde - Refactor: escriba las pruebas que fallan, haga el mínimo para pasar la prueba, luego vuelva a trabajar el código para hacerlo más fácil de mantener mientras se asegura de que todavía pase la prueba.

Pero ... el progreso se midió por la rapidez con que se implementaron las historias de los usuarios, es decir, la rapidez con la que se agregó la nueva funcionalidad. Lo que pasa con la refactorización es que no agrega ninguna funcionalidad nueva. Sí, es muy importante, pero no tiene el mismo impacto inmediato que mostrar al propietario del producto la nueva funcionalidad o incluso las líneas de código de prueba para ir con él.

A medida que las fechas límite se acercaban más y las horas extra se volvían estándares, había un incentivo para escatimar en la parte de refactorización. Cuanto más se hace esto, más rápido se obtiene a través de las historias de los usuarios, lo que parecía ser lo que a la gerencia le importaba.

Ahora bien, esto llevó a una deuda técnica porque en varias ocasiones para completar la siguiente historia de usuario resultó necesario volver atrás y refactorizar, realmente reescribir, el código para el grupo anterior de historias de usuarios. La gerencia se enojó con esto porque, desde su punto de vista, la historia del usuario en cuestión no parecía ser tan diferente de las anteriores, entonces, ¿por qué la estimación era 10 veces más larga?

(También había un aspecto feo de la teoría de juegos en las cosas. Si tú o tu equipo eran conscientes de la refactorización, eso no evitaba que te quedaras atrapado limpiando a otro equipo que no lo era . Por supuesto, ese otro equipo se veía mejor porque obtuvieron más historias de usuarios hechas en la misma cantidad de tiempo).

Mi punto aquí es, quizás, TDD no conduce a la deuda técnica si se hace correctamente. Pero para que se haga correctamente debe haber una compra genuina desde arriba.


Encuentro que el enfoque de Desarrollo impulsado por prueba (TDD) de Robert Martin ayuda con estas preocupaciones.

¿Por qué?

  • Solo tiene que escribir suficiente código para pasar la próxima prueba.
  • Creo que el código comprobable es más limpio.
  • El diseño debe alimentar las pruebas que pueden ayudar a mantener el diseño enfocado.
  • Cuando tiene que cambiar (refactorizar) tiene pruebas para recurrir

Independientemente de cuándo se escriban las pruebas (antes o después), creo que escribir la prueba lo ayuda a tomar decisiones prácticas. Por ejemplo, elegimos el diseño A o B porque A es más comprobable.


Es por eso que siempre es más fácil escribir buenos "documentos acadamic" hablando sobre cómo el desarrollo ágil es bueno, cuáles son las "mejores prácticas", etc.

Es por eso que encuentras muchos "ingenieros adecuados" que crean nuevas técnicas de ingeniería de software.

El proceso es importante, mantener las mejores prácticas es genial, pero sobre cualquier otra cosa, el proceso de diseño de la unidad de sentido común. El software es desarrollado por personas para que YAGNI realmente debería ser:

Puede que no lo necesite pero quizás lo haré porque en mi negocio / empresa / departamento concreto esto sucede o lo necesitaré, pero no tengo el tiempo justo, no es tan rápido y sucio para hacer dinero y mantener mi trabajo. , o podría necesitarlo y refactorizarlo más adelante será un dolor en el culo que cuesta 10 veces más que solo hacerlo ahora desde el principio, y tengo el tiempo AHORA MISMO.

Así que use su sentido común, confíe en él o confíe en el sentido común de las personas que trabajan para usted. No tome todos los documentos académicos como un hecho comprobado, la experiencia es el mejor maestro y su compañía debe mejorar su camino o hacer las cosas con el tiempo y su propia experiencia.

Editar: Por cierto, TDD es lo opuesto a YAGNI, estás construyendo pruebas incluso antes de saber si vas a necesitarlas. ¡En serio, deja de escuchar lo académico! No hay una forma mágica de producir software.


La respuesta "tradicional" de XP es la refactorización combinada con pruebas unitarias automatizadas.

Pero es una pregunta muy interesante filosóficamente. No creo que deba evitar la deuda técnica, simplemente manténgala en un nivel manejable. El artículo de Steve McConnell es bueno en este balance: la razón por la cual la analogía funciona es que es normal y aceptable acumular deuda financiera en una compañía, siempre y cuando acepte los costos y riesgos, y la deuda técnica también está bien.

Tal vez la respuesta en sí también radica en el principio de YAGNI. No va a necesitar la deuda técnica pagada hasta que lo haga, y es entonces cuando hace el refactor. Cuando está haciendo un trabajo sustancial en un área del sistema con deuda técnica, observe la diferencia a corto plazo que hará para rediseñar. Si es suficiente para que valga la pena, pague. La sugerencia de McConnell de mantener una lista de deudas le ayudará a saber cuándo tomar esta consideración.

No creo que haya una respuesta absoluta a esto; como muchas otras, es una decisión basada en su experiencia, su intuición y su análisis en cada situación particular.


Parece que si te apegas a la idea de "planear, hacer, adaptar, planificar, hacer, adaptar" de ágil (iteraciones, revisiones de iteración), evitarías esas cosas de manera predeterminada. BDUF es tan contrario a la idea de la estimación y planificación ágiles que si eres realmente ágil, no serás BDUF automáticamente.

El propósito de las reuniones de planificación de lanzamiento e iteración es asegurarse de que está agregando las características más valiosas al proyecto para esa iteración. Si lo tienes en cuenta, evitarás YAGNI gratis.

Recomiendo encarecidamente los libros de Mike Cohn sobre planificación ágil:

  1. Historias de usuarios aplicadas
  2. Estimación y planificación ágiles

Actualización: después de su aclaración sobre cómo evitar YAGNI y BDUF en una iteración ...

BDUF ... Si sintiera que una característica no estaba claramente definida antes de comenzar a trabajar en ella, crearía una pequeña "característica" o historia para explicar la parte del trabajo de diseño que se necesita. Entonces, tal vez la historia más pequeña tenga un estimado de 1 punto en lugar de la característica real 5. De esa manera, el diseño se encapsula en una historia más pequeña, y se lo llevará a la función en sí.

Para evitar violar YAGNI , trabajaría para ser muy claro sobre lo que el cliente espera de una característica dentro de una iteración. Solo haga un trabajo que se corresponda con lo que el cliente espera. Si cree que se debe agregar algo adicional, cree una nueva característica para él y agréguelo al trabajo atrasado que se realizará. Entonces persuadiría al cliente a ver el beneficio de ello; del mismo modo que el cliente presionaría para que se realice una función en un momento determinado.


Pareces decir que "YAGNI" implica "rápido y sucio". No veo eso.

Como programador ágil, practico desarrollo basado en pruebas, revisión de código e integración continua.

  • El desarrollo basado en pruebas (TDD), como un proceso, es una buena forma de evitar YAGNI. El código que está allí "en caso de que sea útil" tiende a no ser probado y es difícil de probar.
  • TDD también elimina en gran medida la compulsión a BDUF: cuando su proceso comienza por sentarse y comenzar a hacer algo que en realidad ofrece valor, no puede permitirse el uso de BDUF.
  • TDD, como práctica de diseño, significa que el diseño grande surgirá a medida que adquiere experiencia con el problema y refactoriza el código real.
  • La integración continua significa que usted diseña su proceso para que su producto sea esencialmente liberable en cualquier momento. Eso significa que tiene un proceso integrado de calidad que intenta evitar que la calidad de la línea principal caiga.

En mi experiencia, las principales formas de deuda técnica son:

  • Código no cubierto por el conjunto de pruebas automatizadas. No permita que eso suceda, a excepción de componentes muy localizados que son especialmente difíciles de probar. El código no probado es código roto.
  • Código feo que infringe el estándar de codificación. No permita que eso suceda. Esa es una de las razones por las cuales necesita construir una revisión de código en el proceso de integración continua.
  • Código y pruebas que huelen y necesitan refactorización para ser modificados o entendidos más fácilmente. Esta es la forma benigna de la deuda técnica. Usa tu experiencia para saber cuándo acumularla y cuándo pagarla.

No estoy seguro de si eso respondió su pregunta, pero me divertí escribiéndola.

Troy DeMonbreun comentó:

No, ese no era mi punto ... "rápido y sucio" = (arriesgando involuntariamente la deuda técnica al intentar adherirme a YAGNI "). Eso no significa que YAGNI solo sea rápido y sucio. La frase" rápido y sucio "es lo que solía citar a Martin Fowler en su descripción de deuda técnica

Evitar YAGNI es otra forma de decir KISS . YAGNI aumenta la deuda técnica . No hay tensión entre evitar YAGNI y mantener baja la deuda técnica.

Creo que todavía podría estar perdiendo el sentido de su pregunta.


Sin duda, ser ágil mantendrá su TD abajo para cualquier proyecto dado.

El hecho de que esté implementando lo que el cliente quiere, es decir, con sus comentarios, está manteniendo a TD al mínimo,


Solo haz lo más simple que funcione . Estoy de acuerdo con Ayende cuando dice que la clave para ser ágil es "enviarlo, a menudo". Un ciclo de lanzamiento regular como este significará que no hay tiempo para BDUF y también disuadirá a los desarrolladores de violar YAGNI.


Hubo una discusión interesante sobre Deuda técnica basada en su definición de hecho en HanselMinutes hace un par de semanas: ¿Qué se hace ? Los conceptos básicos del programa eran que si redefinía ''Hecho'' para aumentar la velocidad percibida, acumularía Deuda técnica. El corolario de esto es que si no tiene una definición adecuada de ''Hecho'', es muy probable que esté adquiriendo una lista de elementos que deberán completarse antes del lanzamiento, independientemente de la metodología de diseño.