Hay un debate clásico en los proyectos de desarrollo de software, entre dedicar tiempo a mejorar la calidad del código versus concentrarse en entregar más características valiosas. En general, la presión por entregar más características domina la discusión, llevando a que muchos desarrolladores se quejen de no tener tiempo para trabajar en la arquitectura y en la calidad del código.

La ley de los titulares de Betteridge es un concepto que dice que cualquier artículo con un título que termine con un signo de pregunta puede resumirse en un “No”. Quienes me conocen sabrán de mis ganas de cambiar esta ley. Pero este artículo va más allá: cuestiona la misma pregunta. La pregunta asume el intercambio clásico entre calidad y costo. Con este artículo intentaré explicar que esta compensación no existe en el software: el software de alta calidad es en realidad más barato de producir.

Aunque la mayoría de mis publicaciones están orientadas a desarrolladores de software profesionales, para este artículo no voy a presuponer ningún conocimiento de la mecánica del desarrollo de software. Espero que este texto pueda ser valioso para cualquiera involucrado en pensar el software, en particular aquellos que actúan como clientes de equipos de desarrollo de software (como por ejemplo, líderes de negocios).

Estamos acostumbrados al intercambio entre calidad y costo

Como ya mencioné, estamos acostumbrados al intercambio entre calidad y costo. Cuando reemplazo mi teléfono móvil, puedo elegir entre un modelo más costoso con un procesador más rápido, mejor pantalla, y más memoria. O puede resignar algunas de estas cualidades y pagar menos dinero. No es una regla absoluta, a veces aparecen oportunidades donde un producto de alta calidad es más barato. A menudo tenemos diferentes valores de calidad: algunas personas no notan como una pantalla es mejor que otra. Pero esta presuposición es cierta la mayor parte del tiempo: más calidad usualmente significa más costo.

La calidad del software significa muchas cosas

Si voy a hablar de la calidad en el software, necesito explicar lo que es. Y aquí aparece la primer complicación: hay muchas cosas que pueden contar como calidad para el software. Puedo considerar la interfaz de usuario: ¿me guia a las tareas que necesito hacer, haciendo que sea más eficiente y eliminando frustraciones? Puedo considerar su confiabilidad: ¿contiene defectos que ocasionan errores y frustraciones? Otro aspecto es su arquitectura: ¿el código fuente está dividido en módulos claros, donde los programadores pueden encontrar y comprender con facilidad en qué porción del código deben trabajar esta semana?

Estos tres ejemplos de calidad no son una lista exhaustiva, pero resultan suficientes para ilustrar un punto importante. Si soy un cliente o un usuario del software, no voy a apreciar algunas de las cosas que refieren a la calidad. Un usuario pueden distinguir si la interfaz es buena. Un ejecutivo pueden distinguir si el software está haciendo que su equipo sea más eficiente en el trabajo. Los usuarios y los clientes van a notar defectos, en particular si se corrompen datos y hacen que el sistema quede inoperativo por un tiempo. Pero los clientes y los usuarios no pueden percibir la arquitectura del software.

Por lo tanto distingo los atributos de calidad del software en externos (como la interfaz de usuario y los defectos) y los internos (la arquitectura). De esta distinción resulta que los usuarios y los clientes pueden ver la alta calidad externa de un software, pero no pueden distinguir entre calidad interna alta o baja.

A primera vista, la calidad interna no le importa el cliente

Ya que la calidad interna es algo que los clientes o los usuarios no pueden ver, ¿nos debería importar? Imaginamos que Rebeca y yo escribimos una aplicación para el seguimiento y la predicción de demoras en los vuelos. Ambas aplicaciones realizan las mismas funciones esenciales, ambas tienen interfaces de usuario elegantes, y ambas apenas tienen defectos. La única diferencia es que la estructura interna del código fuente de Rebeca está prolijamente organizada, mientras que la mia es un lio. Y hay otra diferencia: yo vendo mi aplicación por $6, y ella vende la suya a $10.

Como un cliente nunca ve el código fuente, y no afecta la operación de la aplicación, ¿por qué alguien pagaría los $4 adicionales para el software de Rebeca? Para decirlo de forma más general, esto parecería significar que no amerita pagar más dinero por una mejora calidad interna.

Otras forma de verlo es que tiene sentido intercambiar costo por mejor calidad externa, pero no parece tener sentido intercambiar costo por más calidad interna. Un usuario puede juzgar si quiere pagar más por una mejor interfaz de usuario, ya que pueden acceder a dicha interfaz y evaluar si es lo suficientemente más linda como para pagar el dinero adicional. Pero un usuario no puede ver la estructura modular interna del software, y mucho menos evaluar cuál es mejor. ¿Por qué pagar más por algo que no tiene efecto? Y siendo este el caso, ¿por qué cualquier desarrollador de software debería usar su tiempo en mejorar la calidad interna de su trabajo?

La calidad interna hace que resulte más fácil mejorar el software

Entonces, ¿por qué a los desarrolladores de software les importa tanto la calidad interna? Los programadores pasan la mayor parte del tiempo modificando código. Incluso en un sistema nuevo, casi toda la programación ocurre en el contexto de una base de código existente. Cuando quiero agregar una nueva característica al software, mi primer tarea consiste en ver cómo esta nueva característica encaja en el flujo actual de la aplicación. Luego necesito cambiar el flujo para permitir incorporar la característica. Con frecuencia necesito utilizar datos que ya existen en la aplicación, por lo que necesito comprender lo que representan los datos, cómo se relacionan con los datos a su alrededor, y qué datos necesito para agregar la característica nueva.

Todo esto es sobre la comprensión del código existente. Pero es muy fácil que el software sea difícil de comprender. La lógica puede estar toda enmarañada, los datos puede ser difíciles de seguir, los nombres que refieren a cosas pueden haber tenido sentido para Tony hace 6 meses, pero son tan misteriosos para mí como para sus motivos por dejar la empresa. Todos estos temas son formas que los desarrolladores denominan “deuda técnica”: la diferencia entre el código actual y cómo debería ser idealmente.

Una de las principales características de la calidad interna es que hacerme más fácil entender cómo funciona la aplicación, para poder ver cómo agregar nuevas cosas. Si el software está bien dividido en módulos separados, no tengo que leer las 500.000 línes de código, y puedo encontrar rápido unas pocas cientos de líneas en un par de módulos. Si invertí esfuerzo en usar nombres claros, puedo entender rápidamente lo que hace distintas partes del código sin tener que bucear en los detalles. Si los datos siguen de manera sensata el lenguaje y estructura del negocio, puedo comprender con facilidad cómo se relaciona con el pedido que recibí del cliente. La deuda técnica le suma tiempo a la tarea de comprender cómo agregar un cambio, y también incrementa las chances de que cometa algún error. Si detecto mis errores, luego hay más tiempo perdido intentando entender cuál es el problema y solucionarlo. Si no detecto mis errores, entonces tendremos errores en producción, y será más tiempo perdido arreglando cosas después.

Mis cambios también afecta el futuro. Puedo encontrar una forma rápida de agregar esta característica nueva, pero es una ruta que va contra la estructura modular del programa, agregando deuda técnica. Si tomo este camino, va a ser más rápido hoy, pero hará que sea más lento para todo el resto de personas que tenga que lidiar con este código durante las semanas y meses siguientes. Una vez que otros miembros del equipo tomen la misma decisión, una aplicación que hubiera sido fácil de modificar puede acumular deuda técnica muy rápido, al punto de que cada cambio menor lleve varias semanas de esfuerzo.

A los clientes les importa que se agreguen rápido las nuevas características

Aquí es donde empezamos a ver porqué la calidad interna le importa a los usuarios y a los clientes. Una mejor calidad interna se traduce en que agregar nuevas funciones será más facil, y por lo tanto más rápido y barato. Rebeca y yo podemos tener la misma aplicación hoy, pero en los próximos meses la mejor calidad interna del software de rebeca le permitirá agregar nuevas características semanalmente, mientras que yo voy a estar estancado lidiando con la deuda técnica para publicar una sola nueva característica. No puedo competir con la velocidad de Rebeca, y pronto su software es más completo que el mio. Luego todos mis clientes borran mi aplicación e instalan la de Rebeca, incluso aunque ella pueda cobrarles más caro.

Visualizando el impacto de la calidad interna

El rol fundamental de la calidad interna se el de disminuir los costos de cambios futuros. Pero existe cierto esfuerzo adicional necesario para escribir buen software, el cual impone cierto costo en el corto plazo.

Una forma de visualizar esto es con el siguiente pseudo-gráfico, donde muestro la funcionalidad acumulada del software versus el tiempo (y por lo tanto, el costo) de producirlo. Para la mayoría de las iniciativas de software, la curva se ve algo así:

Eso es lo que ocurre con una calidad interna pobre. El progreso es rápido al principio, pero a medida que el tiempo avanza se va volviendo más difícil agregar nuevas características. Incluso los cambios menores necesitan que los programadores comprendan grandes áreas de código, código que resulta difícil de entender. Cuando realizan los cambios, aparecen errores inesperados, generando tiempos de testing extendidos y defectos que necesitan arreglarse.

Para reducir esta caída en la productividad debemos concentrarnos en la alta calidad interna. De hecho algunos productos ven un efecto contrario, donde los desarrolladores pueden acelerar a medida que se pueden agregar nuevas características usando el trabajo anterior. Esta situación feliz es un caso más raro, ya que necesita de un equipo con habilidad y disciplina para hacer que ocurra. Pero ocasionalmente lo vemos.

El detalle sutil es que existe un periodo de tiempo donde la calidad interna baja es más productiva que el camino de la calidad interna alta. Durante este tiempo existe cierta compensación entre calidad y costo. Por supuesto, la pregunta es: ¿qué tan largo es ese período antes de que las líneas se crucen?

Y aquí es donde entendemos porqué son pseudo-gráficos. No hay forma de medir la funcionalidad entregada por un equipo de software. Esta inhabilidad de medir la salida (y por lo tanto la productividad) hace que sea imposible poner número concretos a las consecuencias de la calidad interna baja (la cual también es difícil de medir). Es bastante común esta inhabilidad para medir la salida dentro del trabajo profesional: ¿cómo medimos la productividad de los abogados o los doctores?

La forma en la que yo determino dónde se cruzan las líneas es escuchando la opinión de varios desarrolladores habilidosos que conozco. Y la respuesta sorprende a muchas personas. Los desarrolladores coinciden que la baja calidad de código los empieza a retrasar significativamente luego de unas pocas semanas. Por lo tanto, no hay mucho espacio de tiempo en donde aplique la relación entre calidad interna y costo. Incluso los esfuerzos pequeños de software se benefician de prestarle atención a las buenas prácticas de software, lo cual es algo que además puedo respaldar con mi experiencia.

Incluso los mejores equipos crean deuda técnica

Muchas personas que no son desarrolladores tienden a pensar que la deuda técnica sólo ocurre cuando los equipos de desarrollo que son descuidados y cometen errores, pero incluso los mejores equipos van a crear algo de deuda técnica mientras trabajan.

Me gusta ilustrar este punto con una anécdota que ocurrió mientras charlaba con uno de nuestros mejores líderes técnicos en el equipo. Él había recién terminado un proyecto que era considerado abiertamente como un gran éxito. El cliente estaba feliz con el sistema entregado, tanto en términos de sus capacidades, los tiempos de construcción y el costo. Nuestras personas tenían una mirada positiva de su experiencia trabajando en el proyecto. El líder técnico también estaba ampliamente contento, pero confesó que la arquitectura del sistema no era tan buena. Yo reacción con un “¿cómo puede ser? Sos uno de nuestros mejores arquitectos!”. Su respuesta es una muy familiar para cualquier arquitecto de software con experiencia: “tomamos buenas decisiones, pero recién ahora comprendemos cómo deberíamos haberlo construido”.

Muchas personas, incluidas varias de la industria del software, comparan la construcción de software con la construcción de catedrales o edificioes: después de todo, ¿por qué usamos la palabra “arquitecto” para los programadores seniors? Pero el desarrollo de software ocurre en un mundo de incertidumbres desconocido en el mundo físico. Los clientes del software apenas tienen una idea vaga de las característica que necesitan en el producto, y descubren más a medida que se construye el software, en especial a medida que se van entregando versiones a los usuarios. Los bloques que conforman a la construcción de software (lenguajes, librerías y plataformas) cambian de manera significativa en unos pocos años. El equivalente en el mundo físico sería que los clientes agreguen pisos nuevos y cambien plano de los pisos una vez que medio edificio esté construido y ocupado, todo mientras las propiedades fundamentales del concreto cambian año tras año.

Debido a este nivel de cambios, los proyectos de software siempre están creando algo nuevo. Casi nunca nos encontramos trabajando en un problema bien conocido que se solucionó antes. Naturalmente aprendemos más sobre el problema a medida que vamos construyendo la solución, por lo que resulta habitual escuchar que los equipos recién comprenden mejor cuál sería la arquitectura de software luego de pasar un año desarrollando la solución. Incluso los mejores equipos tendrán deuda técnica en su software.

La diferencia radica en que los mejores equipos crean mucha menos deuda técnica, y a la vez eliminan la suficiente deuda técnica que crearon para poder continuar agregando características de forma rápida. Usan el tiempo para crear pruebas automatizadas que revelan los problemas rápidamente, y gastan menos tiempo arreglando bugs. Realizan refactors frecuentes, de manera de eliminar la deuda técnica antes de que sea un problema. La integración continua minimiza la deuda técnica que aparece debido a miembros del equipo trabajando en distintas áreas. Una metáfora común es la de limpiar la superficie de trabajo y el equipamiento de una cocina. No podemos usar las cosas sucias mientras cocinamos, pero si no limpiamos rápidamente, la suciedad se seca, es más difícil quitarla, y todas las cosas sucias se entrometen para cocinar el próximo plato.

El software de alta calidad es más barato de producir

Para resumir:

  • Descuidar la calidad interna lleva a una rápida acumulación de deuda técnica
  • Esta deuda técnica enlentece el desarrollo de características
  • Incluso los grandes equipos producen deuda técnica, pero como generan una calidad interna alta, les es posible mantenerla bajo control
  • La calidad interna alta mantiene la deuda técnica al mínimo, permitiéndole a los equipos agregar nuevas características con menos esfuerzo, menos tiempo y menos costo.

Desafortunadamente, en general los desarrolladores de software no explicamos bien esta situación. Incontables veces hablé con equipos de desarrollo que dicen “ellos (los jefes) no nos dejan escribir software de calidad porque lleva mucho tiempo”. Los desarrolladores a menudo justifican la atención hacia la calidad mediante la necesidad de ser profesionales. Pero este argumento moralista presupone que la calidad tiene un costo, y esto condena al argumento. Y lo más molesto de la situación es que la deuda técnica resultante le hace la vida más difícil a los desarrolladores, y le cuesta más dinero al cliente. Cuando pensemos sobre la calidad interna, sugiero solo hacerlo a través del argumento económico. La calidad interna reduce el costo de las características futuras, por lo que asignar tiempo en escribir buen código en realidad reduce el costo.

Y es por todo esto que la pregunta de este artículo es equivocada. El “costo” de la calidad interna alta es negativo. El típico intercambio entre costo y calidad, que estamos tan acostumbrados para la mayoría de las decisiones de nuestra vida, no tiene sentido con la calidad interna del software (aunque si tiene sentido para la calidad externa, como una experiencia de usuario bien creada). Debido a que esta relación entre costo y calidad interna es inusual y contra-intuitiva, suele ser difícil de incorporar. Pero comprender esta relación es crítico para desarrollar software con la máxima eficiencia.

Traducido de Is high quality software worth the cost?, por Martin Fowler.

Inspiración.

"Si tú tienes una manzana y yo tengo una manzana e intercambiamos las manzanas, entonces tanto tú como yo seguiremos teniendo una manzana cada uno. Pero si tú tienes una idea y yo tengo una idea, e intercambiamos las ideas, entonces ambos tendremos dos ideas"

Bernard Shaw