Showing posts with label lean. Show all posts
Showing posts with label lean. Show all posts

Thursday, August 14, 2025

Lean, XP y Mentalidad de producto. Tres pilares para un desarrollo sostenible

Cuando hablamos de desarrollar software de forma sostenible, no estamos hablando solo de cuidar el código o de ir a una velocidad razonable. Nos referimos a la capacidad de construir productos útiles, con calidad técnica, en un flujo continuo, sin quemar al equipo y sin hacer que el sistema colapse con cada cambio.Es un equilibrio difícil. Sin embargo, en los últimos años he ido viendo cómo ciertos enfoques nos han ayudado una y otra vez a mantenerlo.

No son ideas nuevas ni especialmente exóticas. Pero cuando se combinan bien, pueden marcar la diferencia. Me refiero a tres pilares concretos: las prácticas de Extreme Programming (XP), el pensamiento Lean aplicado al desarrollo de software, y una mentalidad de producto que nos impulsa a construir con propósito y entender el “porqué” detrás de cada decisión.

Curiosamente, aunque a veces se presentan como enfoques distintos, XP y Lean Software Development tienen raíces y objetivos muy similares. De hecho, muchos de los principios de Lean —como eliminar desperdicio, optimizar el flujo o fomentar el aprendizaje continuo— están profundamente presentes en la forma de trabajar de XP. No es casualidad: Kent Beck, creador de XP, fue uno de los primeros en aplicar el pensamiento Lean al desarrollo de software, incluso antes de que este se popularizara con ese nombre. Como él mismo escribía:

"If you eliminate enough waste, soon you go faster than the people who are just trying to go fast." — Kent Beck, Extreme Programming Explained (2nd ed.), Chapter 19: Toyota Production System

Esta cita de Kent Beck resume la esencia de la eficiencia a través de la eliminación de lo superfluo.

No pretendo decir que esta sea la única forma válida de trabajar, ni que todo equipo tenga que funcionar así. Pero sí quiero compartir que, en mi experiencia, cuando estos tres pilares están presentes y equilibrados, es mucho más fácil mantener un ritmo sostenible, adaptarse al cambio, y crear algo que realmente aporta valor. Y cuando falta alguno, por lo general, se nota.

Este artículo no es una receta, sino una reflexión sobre lo que hemos ido aprendiendo como equipos al construir productos reales, con ciclos de vida largos, bajo presión de negocio y con la necesidad de mantener el control técnico, una forma concreta que nos ha funcionado para hacer “la cosa correcta, de la forma correcta… y sin desperdicio”.

Hacer la cosa correcta, de forma correcta… y sin desperdicio

Hay una frase que me gusta mucho y que resume bien el tipo de equilibrio que buscamos: hacer la cosa correcta, de la forma correcta. Esta frase se ha atribuido a Kent Beck y también la ha usado Martin Fowler en algunos contextos. En nuestra experiencia, esta frase se queda corta si no añadimos una tercera dimensión: hacerlo sin desperdicio, de forma eficiente y fluida. Porque puedes estar haciendo lo correcto, hacerlo bien, y aun así hacerlo con un coste o una lentitud que lo haga insostenible.



A lo largo de los años, hemos visto cómo trabajar de esta manera —haciendo lo correcto, de forma correcta y sin desperdicio— requiere tres pilares:

  • Hacer lo correcto implica entender qué problema hay que resolver, para quién, y por qué. Y esto no se puede delegar fuera del equipo técnico. Requiere que quienes diseñan y desarrollan el software también piensen en producto, en impacto y en negocio. Es lo que en muchos contextos se ha llamado Mentalidad de Producto: vernos como un equipo de producto, donde cada persona actúa desde su disciplina, pero siempre con una mirada de producto.
  • Hacerlo de forma correcta significa construir soluciones que sean mantenibles, testeables, que nos den confianza para evolucionar sin miedo y que lo hagan a un ritmo sostenible, respetando a las personas. Aquí entran de lleno las prácticas de Extreme Programming.
  • Y hacerlo sin desperdicio nos lleva a optimizar el flujo de trabajo, a eliminar todo lo que no aporta valor, a posponer decisiones que no son urgentes y a reducir el coste basal del sistema. De nuevo, mucho del pensamiento Lean nos ayuda aquí.

Estas tres dimensiones no son independientes. Se refuerzan entre sí. Cuando falla una, normalmente se resienten las otras. Y cuando conseguimos que las tres estén presentes, aunque sea a un nivel básico, es cuando el equipo empieza a funcionar con fluidez y con impacto real.

Los tres pilares

A lo largo del tiempo, hemos ido viendo que cuando un equipo tiene estos tres pilares presentes —XP, Lean Thinking y Product Engineering— y los mantiene equilibrados, el resultado es un sistema de trabajo que no solo funciona, sino que aguanta. Aguanta el paso del tiempo, los cambios de estrategia, los picos de presión y las decisiones difíciles.

1. XP: evolucionar sin romper

Las prácticas de Extreme Programming son lo que nos permiten construir software que se puede cambiar. Tests automatizados, integración continua, TDD, diseño simple, refactorización frecuente… todo eso está al servicio de una idea muy simple: si queremos evolucionar, necesitamos ciclos de retroalimentación muy cortos que nos permitan ganar confianza rápidamente.

Con XP, la calidad no es un objetivo separado. Es la base sobre la que se apoya todo lo demás. Poder desplegar cada día, hacer experimentos, probar cosas nuevas, reducir el coste de equivocarse… todo eso depende de que el sistema no se nos caiga cada vez que tocamos algo.

"The whole organization is a quality organization." — Kent Beck, Extreme Programming Explained (2nd ed.), Chapter 19: Toyota Production System

Recuerdo, en Alea, cambiar el núcleo de un producto (sistema de provisión de routers de fibra) en menos de una semana, pasando de funcionar de forma síncrona a asíncrona. Nos apoyamos en los tests principales con la lógica de negocio y fuimos cambiando todos los puntos de entrada del componente poco a poco, test a test. O en The Motion, donde cambiamos en paralelo toda la arquitectura del componente que calculaba el estado y el resultado de los lotes de vídeos que generábamos, para que pudiera escalar a lo que el negocio necesitaba.

Hacer este tipo de cambios en un sistema que no hubiese usado buenas prácticas de ingeniería moderna (XP/CD) habría sido un drama, o incluso se habría descartado totalmente, optando por el parche sobre parche hasta tener que declarar la bancarrota técnica y rehacer el sistema desde cero.

Sin embargo, para nosotros, gracias a XP, era simplemente trabajo normal: conseguir mejoras de escalabilidad o adaptar un componente a cambios del fabricante. Nada excepcional.

Nada de esto sería posible sin equipos que puedan mantener un ritmo constante en el tiempo, porque XP no solo se busca construir sistemas flexibles y robustos, sino también de cuidar a las personas que los desarrollan.

XP no sólo impulsa la sostenibilidad técnica del producto, sino también un ritmo de trabajo sostenible, que incluye holgura productiva para ser creativos, aprender e innovar. Evita “marchas de la muerte” y esfuerzos heroicos que agotan y reducen la calidad. La regla de las 40 horas semanales de Kent Beck refleja una idea clave: la calidad no se sostiene con equipos exhaustos; el exceso de horas reduce la productividad y aumenta los errores.

2. Lean Thinking: foco en valor y eficiencia

El pensamiento Lean nos da herramientas para priorizar, simplificar y eliminar lo innecesario. Nos recuerda que hacer más no siempre es mejor, y que cada línea de código que escribimos tiene un coste de mantenimiento. A menudo, lo más valioso que podemos hacer es no construir nada.

Aplicamos principios como eliminar desperdicio, posponer decisiones hasta el último momento responsable (defer commitment), medir el flujo en lugar de la ocupación o aplicar sistemáticamente YAGNI. Esto nos ha permitido evitar complejidades prematuras y reducir el trabajo innecesario.

En todos los equipos con los que he trabajado hemos simplificado procesos: eliminando ceremonias, trabajando en pasos pequeños y sólidos, prescindiendo de estimaciones y orientándonos a un flujo continuo. Asimismo, hemos reutilizado tecnología “aburrida” antes de introducir nuevas herramientas, y buscado siempre minimizar el coste basal de cada solución, eliminando funcionalidades no usadas cuando es posible.

Recuerdo, en Alea, que durante los primeros meses del sistema de provisión de routers de fibra almacenábamos todo en un par de ficheros de texto, sin base de datos. Esto nos permitió lanzar rápido y migrar a algo más complejo solo cuando fue necesario. O en Clarity AI, donde nuestro bot de operaciones evitó mantener estado aprovechando el que ya guardan los sistemas que opera (como AWS) y prescindió de un sistema propio de autenticación y autorización, usando el que ya ofrece Slack, que es su interfaz principal.

Estos enfoques nos han ayudado a centrarnos en lo esencial, reducir costes y mantener la flexibilidad para adaptarnos cuando las necesidades realmente lo requieren.

3. Mentalidad de Producto: entender el problema, no solo construir la solución

Y, por último, el pilar que más a menudo se olvida o se subcontrata mentalmente: entender el problema.
Como equipo de producto, no podemos limitarnos a ejecutar tareas desde nuestras disciplinas; necesitamos implicarnos en el impacto de lo que construimos, en la experiencia del usuario y en el porqué de cada decisión.

Cuando el equipo asume esta mentalidad, la forma de trabajar cambia por completo. Desaparece la línea divisoria entre “negocio” y “tecnología”, y empezamos a pensar como un todo. No significa que todos hagan de todo, pero sí que compartimos la responsabilidad sobre el resultado final.

En la práctica, esto implica priorizar problemas antes que soluciones, descartar funcionalidades que no aportan valor aunque ya estén planificadas, y mantener abiertas las opciones técnicas hasta contar con datos y feedback reales. El trabajo se organiza en incrementos verticales pequeños y funcionales, entregando mejoras casi a diario para validar hipótesis con usuarios y evitar grandes entregas llenas de incertidumbre. Gracias a esto, este enfoque permite adaptar en pocas horas procesos críticos a cambios de requisitos o contexto, sin comprometer la estabilidad ni la experiencia del usuario.

No todos los pilares aparecen a la vez

Una de las cosas que he aprendido con el tiempo es que los equipos no arrancan desde el equilibrio. A veces heredas un equipo con un nivel técnico muy sólido, pero sin ninguna conexión con el producto. Otras veces llegas a un equipo que tiene buen criterio sobre qué construir, pero que vive en una trinchera de código imposible de mantener. O el equipo está tan ahogado por los procesos y las dependencias que ni siquiera puede salir a producción con fluidez.

Lo primero, en esos casos, no es meter una metodología o una práctica concreta. Es entender. Ver cuál de los pilares está más débil y trabajar en mejorarlo hasta que, al menos, te permita avanzar. Si el equipo no puede desplegar sin sufrir, importa poco que entienda perfectamente el producto. Si el equipo construye rápido pero lo que hace no lo usa nadie, el problema está en otra parte.

Nuestro enfoque ha sido siempre buscar un cierto equilibrio de base, aunque sea en un nivel muy inicial, y a partir de ahí mejorar en los tres pilares a la vez. En pasos pequeños. Sin grandes revoluciones.

El objetivo no es alcanzar la perfección en ninguno de los tres, sino evitar que alguno falle tanto que el equipo quede bloqueado o se frustre. Cuando conseguimos que los tres estén razonablemente presentes, la mejora se retroalimenta. Aumentar la calidad permite probar más cosas. Entender mejor el producto permite reducir código innecesario. Mejorar el flujo hace que podamos aprender más rápido.

Cuando falta algún pilar…

Con el tiempo, también hemos visto lo contrario: qué pasa cuando alguno de los pilares no está. A veces parece que el equipo funciona, pero hay algo que no termina de encajar, y al final siempre acaba apareciendo la factura.

  • Equipos sin autonomía se convierten en meros ejecutores, sin impacto ni motivación.
  • Equipos sin prácticas técnicas acaban atrapados en su propia complejidad, incapaces de evolucionar sin romper cosas.
  • Equipos sin foco en valor son capaces de construir rápido… basura rápida.

Y muchas veces, el problema no es técnico sino estructural. Como bien apunta Kent Beck:

"The problem for software development is that Taylorism implies a social structure of work... and it is bizarrely unsuited to software development." — Kent Beck, Extreme Programming Explained (2nd ed.), Chapter 18: Taylorism and Software

En algunos contextos se puede trabajar para recuperar el equilibrio. Pero también hay veces en las que el propio entorno no lo permite. Cuando no hay espacio para que el equipo tome decisiones, ni siquiera para mejorar sus propias dinámicas o herramientas, la situación se vuelve muy difícil de sostener. En mi caso, cuando no ha sido posible cambiar eso desde dentro, he preferido cambiar de contexto directamente.


Solo una forma entre muchas

Todo lo que cuento aquí viene de mi experiencia en empresas de producto. Equipos que construyen sistemas que tienen que evolucionar, que tienen vidas largas, que están bajo presión de negocio y que no pueden permitirse tirar todo a la basura cada seis meses.
No es el único contexto posible. En entornos más orientados a servicios o consultoría, las dinámicas pueden ser distintas. Se trabaja con otros ritmos, con otras responsabilidades y con otras prioridades. No tengo experiencia directa en esos contextos, por lo que no opinaré sobre lo que funcionaría mejor allí.

Solo quiero dejar claro que esto que propongo es una forma, no la forma. Pero también he visto muchas otras que, sin unos pilares mínimos de disciplina técnica, enfoque en el valor real y una búsqueda constante de la eficiencia, simplemente no funcionan a medio o largo plazo en entornos de producto que necesitan evolucionar. Mi experiencia me dice que, si bien no tienes que seguir esto al pie de la letra, tampoco puedes esperar grandes resultados si te dedicas a 'guarrear' el código, a construir sin entender el problema o a generar desperdicio por doquier.

Esta combinación, en cambio, es la que más veces ha resistido el paso del tiempo, los cambios de dirección, la presión y la incertidumbre. Y es la que ha hecho que muchos equipos no solo funcionen bien, sino que disfruten de lo que hacen.

Reflexión final

Construir software sostenible no es solo una cuestión técnica. Es un equilibrio entre hacer lo correcto, hacerlo bien y hacerlo sin desperdicio. Y para eso, necesitamos algo más que prácticas o procesos. Necesitamos una forma de trabajar que nos permita pensar, decidir y construir con sentido.

En nuestro caso, eso ha pasado por apoyarnos en tres patas: XP, Lean y Product Engineering. No siempre hemos tenido las tres a la vez. A veces hemos tenido que fortalecer una para poder avanzar con las otras. Pero cuando están presentes, cuando se refuerzan entre sí, el resultado es un equipo que puede entregar valor de forma continua, adaptarse, y crecer sin agotarse.

Ojalá este artículo te sirva para reflexionar sobre cómo trabajas, qué patas tienes más fuertes, y cuáles podrías empezar a equilibrar.

Monday, August 11, 2025

Optimize the Whole: From Lean principle to real-world practice

Introduction

"Optimize the Whole" is one of the fundamental principles of Lean and Lean Software Development. It means setting aside local improvements to look at the entire system, from the idea to the user—people, processes, and technology—and aligning everything toward a common goal: delivering value to the user quickly and sustainably.

In my experience, many teams believe they are being efficient because no one ever stops working, but in the end, the user waits weeks (or months) to see real value. I’ve learned that true improvement comes from a systemic vision, working together so that the flow of value moves without friction from end to end.

Fragmentation: The Legacy of Taylorism

The paradigm of software development has often—consciously or unconsciously—inherited principles rooted in Taylorism and Fordism, conceiving the creation of digital products as a fragmented "assembly line." Under this view, each phase (analysis, design, development, QA, operations) becomes a functional silo, where teams specialize in specific tasks and focus on optimizing their local efficiency.

However, what in physical goods manufacturing could generate economies of scale for mass production has over time also shown its limits by sacrificing flexibility and the ability to quickly adapt to changes in demand or user needs.

In software, this translates into chronic bottlenecks, costly handoffs, and a fundamental disconnect between those who define needs and those who implement them. This fragmentation breaks the flow of value, fosters the accumulation of "inventory" in the form of work in progress, and hinders rapid adaptation—resulting in features that don’t solve real problems or that take months to reach the user, undermining the promise of agility and continuous value.


Comparison of Taylorism, Fordism, and Lean Thinking


What Happens When We Don’t Optimize the Whole?

Over the years working with different teams, I’ve observed that when we don’t optimize the whole, we fall into the trap of optimizing locally—almost always with good intentions but with unintended consequences. Teams may become very “efficient” in their own internal metrics, but if they are not aligned with user value, the overall flow slows down. Bottlenecks appear, handoffs multiply, and work gets stuck somewhere waiting.

I’ve seen this especially when engineering or development is seen as a feature factory that “executes” or “implements” what others decide. The team just implements, without understanding the problem, the priority, or the real impact on the user—and without contributing their technical knowledge to decisions. The result: solutions disconnected from real needs, slow feedback, and features that don’t solve the problem.

In my experience, the root cause is usually a functional and fragmented organizational structure inherited from “assembly line” thinking. But I’ve learned that software doesn’t behave like a linear factory. Software needs product teams with end-to-end responsibility, without silos (backend, frontend, QA, ops, design, etc.), and with real autonomy to make decisions and operate what they build.

I’ve found that this is not just a matter of motivation: it’s the only way to optimize the total flow and deliver real value to the user quickly and sustainably.


Bottlenecks and the Theory of Constraints

The Theory of Constraints (TOC) reminds us that in any system there is always at least one constraint that determines the maximum delivery capacity. Identifying and managing that bottleneck is essential to improving the overall flow.




For example, at ClarityAI, in the beginning, features were released to production but could remain behind a feature toggle for weeks, waiting for product to decide when to expose them to users. Even though they were technically ready, value wasn’t flowing.

Another example: when workflows were separated by functions (frontend, backend, data engineering), any change could take weeks because each group optimized its own flow or backlog instead of thinking about the overall flow from the user’s perspective.

(Fortunately, these specific problems at Clarity AI were solved long ago, but they serve as an example of what can happen when we don’t optimize the whole.)

In my experience working with different teams, I’ve learned that speeding everything up indiscriminately only makes the backlog pile up and creates frustration. 
A necessary condition to identify real constraints is that all work is visible—not only development tasks, but also testing, operations, support, automation, documentation, analysis, coordination, etc. If a significant part of the team’s effort is hidden (because it’s not recorded, visualized, or considered “technical work”), it’s very easy for the real constraints to go unnoticed. As Dominica DeGrandis points out in Making Work Visible, what you can’t see, you can’t manage or improve. Making all work visible is a key step for informed decision-making, reducing work in progress, and better focusing continuous improvement efforts.

The key steps are:
  • Identify the constraint. Make it visible and prioritize it.
  • Exploit the constraint. Keep it focused, avoid distractions, and ensure it’s always working on the highest-value items.
  • Subordinate the rest of the system. Adjust rhythms and priorities so as not to overload the constraint.
  • Elevate the constraint. Improve its capacity through automation, training, or process redesign.
  • Review and repeat. There will always be a new constraint after each improvement.

Over the years, I’ve noticed that the more separate stages with queues there are between the idea and the value delivered to the user, the greater the chances of bottlenecks forming. Furthermore, if each stage belongs to a different group (organizationally speaking) that may even have its own agenda, there is likely little interest in optimizing value for the user. In these cases, each group may focus solely on improving its part of the process—or on avoiding being perceived as the bottleneck.



End-to-End Teams and Real Optimization

In every team I’ve built, I’ve insisted that they be product teams with end-to-end responsibility, without silos for QA, operations, security, or design. The reason is simple: if the team doesn’t control or understand the entire flow, it can’t optimize the whole, and it also risks not taking full responsibility for the complete product.

When the same team is in charge of conceiving, building, deploying, and operating, it eliminates the waste that arises in each handoff and accelerates learning. Every member understands the impact of their work on the end user and the value actually being delivered. End-to-end responsibility not only improves technical quality but also strengthens the focus on user value, avoiding unnecessary investments in local optimizations that don’t contribute to the overall goal.

In this work environment, more generalist profiles—often referred to as "T" (deep in one area and broad in others) or "M" (with several deep specializations and wide versatility)—are especially valued. These professionals, being able to contribute in multiple phases of development and having a more holistic view, are key in contexts where flow efficiency is a priority.

While pure specialists, also known as "I" profiles, are still needed in very specific domains, their role changes: they become enablers and educators, helping to scale their knowledge and train the rest of the team in various facets of the product.

In addition, keeping options open, working in short cycles, and making small deliveries allows for better adaptation to what the business and data reveal. Simplicity and vertical slicing reduce risk and facilitate rapid learning, freeing the team from the mental load of large, fixed plans and fostering autonomy.

This way of working is unfeasible when the product must pass through different silos before reaching the end user.

End-to-End Teams in Practice: Real Experiences

When I formed the team at Alea Soluciones, from the very beginning I pushed for us to take on all possible tasks and functions. I remember both the CEO and the CTO offering me the option to take on fewer responsibilities “to have less pressure and less work.” But I refused that proposal: I knew that if we only kept part of the scope, we would lose the global vision and the ability to optimize the entire system.

By taking on all areas—development, support, product ideas, operations—we always maintained a holistic view of the product. This allowed us to identify at any given moment where the real bottleneck was and act where we could have the greatest impact, without depending on other teams or functional silos. This meant we could decide whether, at a given moment, it made more sense to focus on support, to speed up key developments, or to think about new features—always optimizing the total flow of value to the user.

At Nextail and Clarity AI, together with others, I worked to evolve teams toward an end-to-end model, avoiding QA, operations, or product silos. In these cases, we applied ideas from Team Topologies to transform the structure: we moved from a function-based organization (infrastructure/operations, frontend, backend, data engineering, product) to a matrix of autonomous product teams.

The goal was always the same: to shorten the lead time of any change, from the idea to when the user can actually use it. With autonomous, end-to-end responsible teams, we could deliver value faster, learn continuously, and improve the product in very short cycles.

In all these contexts, I’ve found that the end-to-end approach has not only been a technical or organizational improvement—it has been the key to maintaining a user-centered mindset, reducing waste, and optimizing the whole, every day.


How Optimizing the Whole Helps Eliminate Waste

One of the fundamental principles of Lean is eliminating waste. When we focus only on optimizing local parts, it’s very easy to accumulate work that doesn’t add value, create unnecessary features, or generate invisible delays. In contrast, by optimizing the whole and looking at the complete system, we naturally reduce multiple types of waste.

In my work with different teams, I’ve observed that when we don’t think about the global flow and focus on optimizing “my part,” incentives appear to produce more features even if they don’t provide real value to the user. The priority becomes “staying busy” and completing tasks, rather than questioning whether they are necessary.

I’ve seen how, without early feedback and working in long cycles, teams advance without validating and end up building features nobody asked for or that don’t solve any important problem.

Moreover, when decisions are fragmented (product defines large packages, engineering executes without questioning, and QA validates afterward), the vision of impact is lost, and the backlog tends to swell with features that remain blocked behind a feature toggle or are never released at all.

By optimizing the whole and aligning each step with the complete flow of value to the user, each feature is reviewed with key questions:
  • Does it solve a real, high-priority problem?
  • Can we release it in a small version to learn quickly?
  • How will we know if it truly adds value?
In this way, we build only what’s necessary, learn early, and avoid turning effort into waste.
  • Avoid unnecessary features (overproduction): By prioritizing real user value and working in small deliveries, hypotheses are validated quickly. This avoids building large features that nobody uses or that the business decides not to launch.
  • Reduce waits and blockages (waiting times): By eliminating silos and working end-to-end, work doesn’t get stuck waiting for another team or function to pick it up. This speeds up flow and eliminates idle time.
  • Less rework and late fixes: Delivering in short cycles and validating early allows problems to be detected quickly and corrected at low cost. Otherwise, small local decisions can lead to large refactorings later.
  • Avoid useless local optimizations (unnecessary movement): Optimizing your own “department” or backlog can create a false sense of efficiency, but doesn’t generate value if it doesn’t move the complete flow forward. Looking at the global system avoids this kind of waste.
  • Reduce hidden inventory: Limiting work in progress and prioritizing constant flow minimizes the inventory of half-built or unreleased features, which consume energy and create confusion.
  • Lower opportunity waste: By having a clear view of the whole and being aligned with the business, we avoid investing in the wrong directions and respond quickly to new opportunities. This reduces the risk of missing the right moment to impact the user.

In my experience, when we optimize the complete system, every decision is made with the flow of value to the end user in mind. This way, every line of code, every validation, and every deployment helps reduce waste and maximize impact.

How to Optimize the Whole: Lessons from Practice

  • End-to-end vision: From the business problem to the running software operated by the team itself. Without fragmenting or handing responsibility over to “others.”
  • Flow over utilization: We stop measuring how much each person works and start measuring how much value flows to the user.
  • Enabling practices: Pair programming, TDD, CI/CD, limiting WIP, and visualizing flow… These are key tools to keep the system healthy, adaptable, and ready to learn quickly.
  • Small deliveries and immediate feedback: Every delivery is a learning opportunity. Working in vertical slices helps prioritize what truly matters, encourages simplicity, and reduces the fear of making mistakes.
  • Collaboration and psychological safety: Transparency, trust, and shared responsibility. Encouraging questioning, proposing improvements, and experimenting without fear.
  • Conscious empowerment: Teams take on more decisions as they demonstrate capability, always aligned with the business and focused on real impact.

Why "Optimize the Whole" Matters

Optimizing the whole is crucial because it addresses a fundamental contradiction in many organizations: the pursuit of resource efficiency versus flow efficiency. Traditionally, incentives have pushed for each person, team, or stage of a process to be as “busy” as possible, aiming to maximize individual resource utilization. However, this obsession with local resource efficiency (making sure no one is idle) is often catastrophic for flow efficiency—that is, the speed and smoothness with which value moves from the initial idea to the hands of the end user.

When each component of the system focuses on its own optimization, bottlenecks, waiting queues, and handoffs arise, breaking the continuity of flow. Paradoxically, when “everyone is very busy,” it’s often a clear sign that there is a serious problem with the flow of value to the user. Work piles up, deliveries are delayed, and the organization is investing significant effort in activities that don’t quickly translate into real value.

By optimizing the whole, we achieve:
  • Avoiding invisible bottlenecks that block value to the user, by having a global view of the system.
  • Drastically reducing waste: unused features, endless waits, unnecessary rework, and the false sense of productivity.
  • Enabling faster learning and the ability to build only what truly matters, as the feedback cycle is accelerated.
The true goal is not for everyone to look busy, but for the flow of value to the user to be constant, predictable, and sustainable.

Maximum busyness, minimal progress. Optimizing the whole means avoiding this.


Conclusion: The Transformative Impact

After years of experimenting with teams that truly optimize the whole, I can say you never want to go back. Teams become more resilient, grow faster, and find deeper meaning in their work.
I’ve learned that optimizing the whole is not just a principle—it’s a way of working that transforms teams and individuals, and above all, maximizes real impact for the user.
Are you ready to start optimizing the whole in your team? The first step is to dare to look at the entire system and stop obsessing over local metrics.

Related Articles and Other References



Sunday, July 20, 2025

Optimizar el Todo: del principio Lean a la práctica real

Introducción

"Optimizar el todo" es uno de los principios fundamentales de Lean y Lean Software Development. Implica dejar de lado las mejoras locales para mirar el sistema completo, desde la idea hasta el usuario —personas, procesos y tecnología— y alinear todo hacia un objetivo común: entregar valor al usuario de forma rápida y sostenible.

En mi experiencia, muchos equipos creen que están siendo eficientes porque nadie para de trabajar, pero al final el usuario espera semanas (o meses) para ver valor real. He aprendido que la verdadera mejora nace de una visión sistémica, cooperando para que el flujo de valor fluya sin fricciones de extremo a extremo.

Fragmentación: Herencia del Taylorismo

El paradigma del desarrollo de software ha heredado, a menudo inconscientemente, principios arraigados en el tayloismo y el fordismo, concibiendo la creación de productos digitales como una "cadena de montaje" fragmentada. Bajo esta visión, cada fase (análisis, diseño, desarrollo, QA, operaciones) se convierte en un silo funcional, donde los equipos se especializan en tareas específicas y se enfocan en optimizar su eficiencia local.

Sin embargo, lo que en la fabricación de bienes físicos pudo generar economías de escala para la producción en masa, con el tiempo también ha demostrado sus límites al sacrificar la flexibilidad y la capacidad de adaptación rápida a cambios en la demanda o las necesidades del usuario.

En el software, esto se traduce en cuellos de botella crónicos, handoffs costosos y una desconexión fundamental entre quienes definen las necesidades y quienes las implementan. Esta fragmentación rompe el flujo de valor, fomenta la acumulación de "inventario" de trabajo a medio hacer y dificulta la adaptación rápida, resultando en funcionalidades que no resuelven problemas reales o que tardan meses en llegar al usuario, desvirtuando la promesa de agilidad y valor continuo.


Comparison of Taylorism, Fordism, and Lean Thinking—highlighting their core principles and how each has influenced software development practices.


¿Qué ocurre cuando no optimizamos el todo?

A lo largo de los años trabajando con diferentes equipos, he observado que cuando no optimizamos el todo, caemos en la trampa de optimizar localmente, casi siempre con buena intención pero con consecuencias no deseadas. Los equipos pueden volverse muy "eficientes" en sus propias métricas internas, pero si no están alineados con el valor al usuario, el flujo global se ralentiza. Surgen cuellos de botella, se multiplican los handoffs y el trabajo queda atascado esperando en algún sitio.

He visto esto especialmente cuando ingeniería o desarrollo se ve como una fábrica de funcionalidades que "ejecuta" o "implementa" lo que otros deciden. El equipo se limita a implementar, sin entender el problema, la prioridad ni el impacto real en el usuario. Sin aportar su conocimiento técnico a las decisiones. El resultado: soluciones desconectadas de las necesidades reales, feedback lento y funcionalidades que no resuelven el problema.

En mi experiencia, la causa de fondo suele ser una estructura organizativa funcional y fragmentada, heredada del pensamiento "cadena de montaje". Pero he aprendido que el software no se comporta como una fábrica lineal. El software necesita equipos de producto con responsabilidad extremo a extremo, sin silos (backend, frontend, QA, ops, diseño, etc), y con autonomía real para tomar decisiones y operar lo que construyen.

He comprobado que esto no es solo una cuestión de motivación: es la única manera de optimizar el flujo total y entregar valor real al usuario de forma rápida y sostenible.


Cuellos de botella y la Teoría de Restricciones

La Teoría de las Limitaciones (TOC por sus siglas en inglés) nos recuerda que en cualquier sistema siempre existe al menos una restricción que determina la capacidad máxima de entrega. Identificar y gestionar ese cuello de botella es esencial para mejorar el flujo global.




Por ejemplo, en ClarityAI, al principio se sacaban funcionalidades a producción que podían quedarse semanas detrás de un feature toggle, esperando que producto decidiera cuándo abrirlas al usuario. Aunque técnicamente ya estaban listas, el valor no fluía.

Otro ejemplo: cuando existían flujos de trabajo separados por funciones (frontend, backend, data engineering), cualquier cambio podía tardar semanas porque cada grupo optimizaba su propio flujo o cola de trabajo, en lugar de pensar en el flujo global desde el punto de vista del usuario.

(Por suerte, estos problemas específicos en Clarity AI hace tiempo que los solucionamos, pero sirven como ejemplo de lo que puede ocurrir cuando no optimizamos el todo.)

En mi experiencia trabajando con diferentes equipos, he aprendido que acelerar todo indiscriminadamente solo empeora la acumulación y genera frustración. 
Una condición necesaria para poder identificar restricciones reales es que todo el trabajo esté visible. No solo las tareas de desarrollo, sino también testing, operaciones, soporte, automatización, documentación, análisis, coordinación, etc. Si una parte importante del esfuerzo del equipo queda oculta (porque no se registra, no se visualiza o no se considera "trabajo técnico"), es muy fácil que las restricciones reales pasen desapercibidas. Como plantea Dominica DeGrandis en Making Work Visible, lo que no se ve no se puede gestionar ni mejorar. Hacer visible todo el trabajo es un paso clave para tomar decisiones informadas, reducir el trabajo en curso y enfocar mejor los esfuerzos de mejora continua.

La clave está en:
  • Identificar la restricción. Hacerla visible y priorizarla.
  • Explotar la restricción. Darle foco, evitar distracciones y asegurar que siempre trabaje en lo que más valor aporta.
  • Subordinar el resto del sistema. Ajustar ritmos y prioridades para no saturar la restricción.
  • Elevar la restricción. Mejorar su capacidad mediante automatización, formación o rediseño de procesos.
  • Revisar y repetir. Siempre habrá una nueva restricción tras cada mejora.

A lo largo de los años, he observado que cuantas más etapas separadas con colas existan entre la idea y el valor entregado al usuario, más posibilidades hay de que se formen cuellos de botella. Además, si cada etapa pertenece a un grupo distinto (organizativamente hablando), que incluso puede tener agendas propias, es probable que ni siquiera exista interés en optimizar el valor para el usuario. En estos casos, cada grupo puede centrarse únicamente en mejorar su parte del proceso o en no ser percibido como el cuello de botella.

Equipos end-to-end y optimización real

En todos los equipos que he creado, he insistido en que fueran equipos de producto con responsabilidad de extremo a extremo, sin silos para QA, operaciones, seguridad o diseño. La razón es simple: si el equipo no controla ni comprende todo el flujo, no puede optimizar el conjunto y, además, corre el riesgo de no asumir la responsabilidad sobre el producto completo.

Cuando el mismo equipo se encarga de idear, construir, desplegar y operar, se elimina el desperdicio que surge en cada traspaso y se acelera el aprendizaje. Cada miembro entiende el impacto de su trabajo en el usuario final y el valor que realmente se entrega. La responsabilidad end-to-end no solo mejora la calidad técnica, sino que refuerza el enfoque en el valor para el usuario, evitando inversiones innecesarias en optimizaciones locales que no aportan al objetivo global.

En este entorno de trabajo, los perfiles más generalistas, a menudo denominados "T" (por su profundidad en un área y amplitud en otras) o "M" (con varias especializaciones profundas y amplia versatilidad), son especialmente valorados. Estos profesionales, al poder contribuir en múltiples fases del desarrollo y tener una visión más holística, resultan clave donde la eficiencia de flujo es prioritaria.

Si bien los especialistas puros, también conocidos como "perfiles I", siguen siendo necesarios en dominios muy específicos, su rol se transforma: se convierten en habilitadores y educadores, ayudando a escalar su conocimiento y a capacitar al resto del equipo en diversas facetas del producto.

Además, mantener opciones abiertas, trabajar en ciclos cortos y hacer entregas pequeñas permite adaptarse mejor a lo que el negocio y los datos van mostrando. La simplicidad y el corte vertical reducen el riesgo y facilitan el aprendizaje rápido, liberando al equipo de la carga mental de grandes planes cerrados y fomentando la autonomía.

Esta forma de trabajo es inviable cuando el producto debe pasar por diferentes silos antes de llegar al usuario final.

Equipos end-to-end en la práctica: experiencias reales

Cuando formé el equipo en Alea Soluciones, desde el principio empujé para que asumiéramos todas las tareas y funciones posibles. Recuerdo que tanto el CEO como el CTO me ofrecieron la opción de asumir menos responsabilidades, "para tener menos presión y menos trabajo". Pero rechacé esa propuesta: sabía que si nos quedábamos solo con una parte, perderíamos la visión global y la capacidad de optimizar el sistema completo.

Al asumir todas las áreas —desarrollo, soporte, ideas de producto, operación— logramos mantener siempre una visión holística del producto. Esto nos permitió identificar en cada momento dónde estaba el cuello de botella real y actuar donde más impacto podíamos tener, sin depender de otros equipos ni de silos funcionales. Así podíamos decidir si, en un momento concreto, tenía más sentido centrarnos en soporte, en acelerar desarrollos clave o en pensar nuevas funcionalidades, siempre optimizando el flujo total de valor para el usuario.

En Nextail y en Clarity AI, junto con más personas, trabajé para que los equipos evolucionaran hacia un modelo end-to-end, evitando silos de QA, operaciones o producto. En estos casos, aplicamos ideas de Team Topologies para transformar la estructura: pasamos de una organización basada en funciones (infraestructura/operaciones, frontend, backend, data engineering, producto) a una organización matricial de equipos de producto autónomos.

El objetivo siempre fue el mismo: acortar el lead time de cualquier cambio, desde la idea hasta que el usuario lo puede usar. Con equipos autónomos y responsables de extremo a extremo, podíamos entregar valor más rápido, aprender continuamente y mejorar el producto en ciclos muy cortos.

En todos estos contextos, he comprobado que el enfoque end-to-end no solo ha sido una mejora técnica u organizativa: ha sido la clave para mantener una mentalidad centrada en el usuario, reducir desperdicio y optimizar el conjunto, cada día.


Cómo optimizar el todo ayuda a eliminar desperdicio

Uno de los principios fundamentales de Lean es eliminar el desperdicio. Cuando nos enfocamos solo en optimizar partes locales, es muy fácil acumular trabajo que no aporta valor, crear funcionalidades innecesarias o generar retrasos invisibles. En cambio, al optimizar el todo y mirar el sistema completo, reducimos de manera natural múltiples tipos de desperdicio.

En mi trabajo con diferentes equipos, he observado que cuando no pensamos en el flujo global y nos centramos en optimizar "mi parte", aparecen incentivos para generar más funcionalidades, aunque no aporten valor real al usuario. Se prioriza "estar ocupados" y terminar tareas, en lugar de cuestionar si son necesarias.

He visto cómo al no tener feedback temprano y trabajar en ciclos largos, se avanza sin validar y se terminan construyendo funcionalidades que nadie pidió o que no resuelven ningún problema importante.

Además, cuando las decisiones están fragmentadas (producto define grandes paquetes, ingeniería ejecuta sin cuestionar, y QA valida después), se pierde la visión de impacto y se tiende a hinchar el backlog con funcionalidades que quedan bloqueadas tras un feature toggle o, directamente, nunca se lanzan.

Al optimizar el todo y alinear cada paso con el flujo completo de valor hacia el usuario, cada funcionalidad se revisa con preguntas clave:
  • ¿Resuelve un problema real y prioritario?
  • ¿Podemos lanzarla en pequeño para aprender rápido?
  • ¿Cómo sabremos si realmente aporta valor?
Así, se construye solo lo necesario, se aprende pronto y se evita transformar esfuerzo en desperdicio.
  • Evitar funcionalidades innecesarias (sobreproducción): Al priorizar valor real para el usuario y trabajar en entregas pequeñas, se validan hipótesis rápido. Así, evitamos desarrollar grandes funcionalidades que después nadie usa o que el negocio decide no lanzar.
  • Reducir esperas y bloqueos (tiempos de espera): Al eliminar silos y trabajar de extremo a extremo, el trabajo no se queda atascado esperando a que otro equipo o función lo retome. Esto acelera el flujo y elimina tiempos muertos.
  • Menos retrabajo y correcciones tardías: Entregar en ciclos cortos y validar pronto permite detectar problemas rápidamente y corregirlos con bajo coste. De lo contrario, pequeñas decisiones locales pueden acabar en grandes refactorizaciones posteriores.
  • Evitar optimizaciones locales inútiles (movimiento innecesario): Optimizar tu propio "departamento" o tu cola de trabajo puede dar una falsa sensación de eficiencia, pero no genera valor si no avanza el flujo completo. Mirar el sistema global evita este tipo de desperdicio.
  • Reducir inventario oculto: Limitar el trabajo en curso y priorizar flujo constante minimiza el inventario de funcionalidades medio hechas o pendientes de lanzamiento, que consumen energía y generan confusión.
  • Menor desperdicio de oportunidad: Al tener una visión clara del todo y estar alineados con el negocio, se evita invertir en direcciones equivocadas y se responde rápido a nuevas oportunidades. Esto reduce el riesgo de perder el momento correcto para impactar al usuario.

En mi experiencia, cuando optimizamos el sistema completo, cada decisión se toma pensando en el flujo de valor hacia el usuario final. Así, cada línea de código, cada validación y cada despliegue contribuye a reducir el desperdicio y maximizar el impacto.

Cómo optimizar el todo: aprendizajes en la práctica

  • Visión extremo a extremo: Desde el problema de negocio hasta el software funcionando y operado por el propio equipo. Sin fragmentar ni ceder responsabilidad a "otros".
  • Flujo sobre ocupación: Dejamos de medir cuánto trabaja cada persona y pasamos a medir cuánto valor fluye hasta el usuario.
  • Prácticas habilitadoras: Pair programming, TDD, CI/CD, limitar el WIP y visualizar el flujo… Son herramientas clave para mantener el sistema sano, adaptable y preparado para aprender rápido.
  • Entregas pequeñas y feedback inmediato: Cada entrega es una oportunidad de aprendizaje. Trabajar en cortes verticales ayuda a priorizar lo que realmente importa, fomenta la simplicidad y reduce el miedo a equivocarse.
  • Colaboración y seguridad psicológica: Transparencia, confianza y responsabilidad compartida. Se fomenta cuestionar, proponer mejoras y experimentar sin miedo.
  • Empoderamiento consciente: Los equipos asumen más decisiones a medida que demuestran capacidad, siempre alineados con el negocio y con foco en el impacto real.

Por qué "Optimizar el todo" importa

Optimizar el todo es crucial porque aborda una contradicción fundamental en muchas organizaciones: la búsqueda de la eficiencia de recursos frente a la eficiencia de flujo. Tradicionalmente, se ha incentivado que cada persona, equipo o etapa de un proceso esté lo más "ocupado" posible, buscando maximizar el uso individual de los recursos. Sin embargo, esta obsesión por la eficiencia local de recursos (que nadie esté parado) suele ser catastrófica para la eficiencia de flujo, es decir, la velocidad y suavidad con la que el valor llega desde la idea inicial hasta las manos del usuario final.

Cuando cada componente del sistema se centra en su propia optimización, se generan cuellos de botella, colas de espera y handoffs que rompen la continuidad del flujo. Paradójicamente, cuando "todo el mundo está muy ocupado" suele ser una clara indicación de que existe un problema importante con el flujo de valor al usuario. El trabajo se amontona, las entregas se retrasan, y la organización está invirtiendo un gran esfuerzo en actividades que no se traducen rápidamente en valor real.

Al optimizar el todo, logramos:
  • Evitar cuellos de botella invisibles que bloquean el valor al usuario, al tener una visión global del sistema.
  • Reducir drásticamente el desperdicio: funcionalidades no usadas, esperas interminables, retrabajo innecesario y la falsa sensación de productividad.
  • Permitir un aprendizaje más rápido y la capacidad de construir solo lo que realmente importa, ya que el ciclo de feedback se acelera.
El verdadero objetivo no es que todos parezcan ocupados, sino que el flujo de valor hacia el usuario sea constante, predecible y sostenible.

Máxima ocupación, mínimo avance. Optimizar el todo es evitar esto.


Conclusión: el impacto transformador

Después de años experimentando con equipos que realmente optimizan el todo, puedo afirmar que ya no quieres volver atrás. Los equipos se vuelven más resilientes, crecen más rápido y encuentran sentido en el trabajo.
He aprendido que optimizar el todo no es solo un principio: es una forma de trabajar que transforma equipos y personas y, sobre todo, maximiza el impacto real para el usuario.
¿Te atreves a empezar a optimizar el todo en tu equipo? El primer paso es atreverse a mirar el sistema completo y dejar de obsesionarse con métricas locales.

Artículos relacionados y otras referencias



Monday, July 14, 2025

Refined and Expanded: Custom GPTs for Lean Discovery and Delivery

A while back, I shared how I built a Custom GPT to help teams ship smaller, safer, faster. The goal was clear: challenge teams to focus on learning and delivering value in small, safe steps.

Since then, I've refined that original GPT and expanded the approach.


From broad to focused: eferro Lean Delivery

The original Custom GPT has evolved into eferro Lean Delivery. This version zeroes in on one thing: helping teams deliver value in the smallest, safest, most reversible steps possible — always with zero downtime and minimal risk.

Whether you’re planning a migration, thinking about a tricky rollout, or just trying to keep changes deployable at all times, eferro Lean Delivery is your partner in challenging assumptions and slicing work even thinner.

Check it out here: eferro Lean Delivery

New: eferro Lean Discovery

Alongside Delivery, I’ve created a new GPT: eferro Lean Discovery. This one is all about the upstream part of product work: ideation, problem framing, hypothesis creation, and finding the smallest meaningful experiments.

Where Delivery helps you move safely and incrementally once you start building, Discovery helps you figure out what’s really worth building in the first place. It asks you uncomfortable (but necessary) questions like:

  • What problem are we really solving?
  • What’s the smallest experiment to validate this idea?
  • What signals are we looking for before investing further?

Try it here: eferro Lean Discovery

Where to find them

You can find both GPTs — eferro Lean Delivery and eferro Lean Discovery — in the GPT marketplace. Just search for eferro Lean, and you’ll see them there.


Both tools are built on the same spirit:
Software is about learning. The faster (and safer) we learn, the more impact we create.

No tracking, no hidden agendas — just simple tools to help teams focus on what matters: delivering value continuously, with confidence and calm.

Sunday, June 15, 2025

Built a Custom GPT to Help Teams Ship Smaller, Safer, Faster

Most teams build too much, too early, with too much anxiety. They optimize for perfect architecture before users, comprehensive features before learning, elaborate processes before understanding real constraints.

The result? Endless discussions, delayed releases, building the wrong thing.

So I built: 👉 eferro Lean – your no-BS delivery copilot

A Custom GPT that works with any product development artifact—PRDs, tickets, code reviews, roadmaps, architecture docs—and asks the uncomfortable, helpful questions:
  • "What's the smallest shippable version?"
  • "Do we actually need this complexity right now?"
  • "What if we postponed this decision?"
  • "How can we make this change in smaller, safer steps?"
Perfect for anyone building products: developers, PMs, designers, architects, team leads.


Use it to:
  • Slice big ideas into vertical experiments and safe technical steps
  • Plan parallel changes, expand-and-contract migrations, or branch-by-abstraction
  • Challenge bloated PRDs or over-engineered solutions
  • Turn risky releases into incremental, reversible deployments
It challenges assumptions, slices features into experiments, and guides you toward the last responsible moment for decisions. Questions that create momentum instead of paralysis.

Software is a learning exercise. Every feature is an experiment. The faster we test hypotheses safely, the faster we learn what creates value.

No tracking, no upsell, no agenda. My only intention is to share what I've learned and keep learning from the community.

If it helps one team ship better—with less stress, more learning—that's enough.

Monday, April 14, 2025

Lean Software Development: Building with Quality

Part one of a series on how to build with quality based on Lean Software Development principles. In this article, we explore what “quality” really means, how it differs from the traditional approach, and what principles help us prevent errors from becoming defects.

Lean Software Development: Building with Quality

One of the main differences between Lean Software Development and traditional approaches lies in the treatment of quality—both in the resulting software or product and in the work environment (collaboration, tools, communication).

Lean Software Development considers quality as an integral part of the product’s value, essential to deliver value to the customer as efficiently as possible. From this perspective, all quality issues are considered one of the main wastes to eliminate.

In contrast, traditional approaches usually focus primarily on the quality of the final product. Lean, on the other hand, focuses on the continuous improvement of the processes and the system that generates the final product.

Quality control, which traditionally focuses on inspecting the product at the end of the process, becomes in Lean a fundamental part of each stage. In other words, instead of inspecting and validating quality at the end, quality is built in from the beginning and maintained throughout the process. This involves moving from a reactive approach to problems to a more proactive one, making any issues visible with the goal of solving them immediately and addressing root causes (system or processes).

We can summarize these differences as follows:

Focus

  • Traditional: Mainly on the quality of the final product.
  • Lean Software Development: Continuous improvement of processes and systems.

Quality Control

  • Traditional: Inspection at the end or at specific production checkpoints.
  • Lean Software Development: Built-in quality at every step (jidoka).

Problem Solving

  • Traditional: Reactive, addressing problems after they occur.
  • Lean Software Development: Proactive, highlighting and solving problems immediately.

In the end, Lean Software Development considers that all rework (incidents, bug fixing, repeated processes, etc.) caused by problems and defects is one of the major wastes to eliminate. Therefore, it focuses on introducing quality at every step of the process, minimizing waste, and fostering a habit of working with quality and continuously improving.


Quality is a broad concept that can cover various aspects: external quality (how it is perceived by the customer or end user), internal quality (related to the ease of evolution and maintainability of the code or system), and even the quality of our processes and work environment.

In this article series, we will place special emphasis on external quality, as perceived by customers or users. However, we will also address aspects of internal and process quality, since they are fundamental for sustaining high external quality in the long term. In addition, since Lean Software Development places strong emphasis on continuous improvement of both the processes and the system to ensure such quality, we will also address aspects related to process and work environment quality.

Basic Concepts

Let’s start with some concepts and definitions that will be useful throughout the rest of the articles:

  • Error: We consider an error as any deviation from the expected result. For example, in our application’s execution, an error may be a failed test, code that functionally does not meet expectations, among others.
  • Problem: In the context of Lean Software Development, a problem is any obstacle that prevents us from delivering value to the customer in the most efficient and effective way. This includes the gap between the current state and the desired state, but also covers situations such as
    • Ambiguous requirements leading to incorrect implementation.
    • Communication problems within the team that result in misunderstandings and delays.
    • Technical limitations preventing desired performance.
    • Inefficiencies in the deployment process causing delays.
  • Defect: A defect is an error that prevents the product from fulfilling its function or purpose, directly affecting customers. Defects are one of the main sources of waste identified in Lean Software Development (see “Eliminating Waste in Development”). Therefore, it is a priority to avoid them whenever possible and eliminate them immediately when detected. The linked article explores how Lean Software Development adapts the seven types of waste from Lean Manufacturing to software, focusing on eliminating activities that do not add value to the customer and promoting practices like reducing “Partially Done Work” and avoiding “Extra Features and Code.” See article for more details.

It is important to remember that defects are a subset of errors, and problems can include multiple errors and defects.

Although this classification may seem confusing at first, distinguishing between problem (a general situation that includes errors and defects), error (any deviation from expectations, like a failed test, an incorrect variable name, or a poorly implemented feature), and defect (an error that affects the customer or the system’s purpose and is a fundamental source of waste) helps us better understand the situation and define appropriate processes to address each case.

Lean Approach to Reducing Errors and Defects

  • Jidoka: Also known as "autonomation", this principle seeks to detect and correct defects automatically, stopping production as soon as an error is identified. A classic example in Lean Manufacturing is the use of “Andon Cards,” visual signaling systems that allow any worker to stop the production line upon detecting a problem. In our software development context, this translates to automated testing at different stages, alarms and monitoring, the use of a CI pipeline that stops deployment if tests fail, among other mechanisms.
  • Poka-Yoke: Translated as "mistake-proofing", this approach relies on systems and designs that prevent human errors. In software development, Poka-Yoke applies both to our internal processes and the user's interaction with the product.
    • In the development process, we implement Poka-Yoke through practices such as using strongly typed programming languages, tools with optimal default settings, automated tests, ValueObjects, and preconditions. These techniques help prevent coding and design errors.
    • In software usability, we apply Poka-Yoke through error-prevention systems, effective contextual help messages, and intuitive designs. This is where User Experience (UX) plays a crucial role. Although UX is not a direct Poka-Yoke mechanism in the technical sense (like a physical sensor stopping a machine), it shares the fundamental goal of preventing user errors. Good UX design anticipates possible mistakes, guides the user clearly, and provides immediate feedback, significantly reducing the chances of user error. In this sense, UX complements and reinforces Poka-Yoke principles, ensuring the software is as intuitive and error-free as possible for the end user.
  • Kaizen: This is the principle of continuous improvement applied to our processes and systems. As one of the pillars of Lean, it promotes the constant search for ways to reduce errors and improve quality, both in the product and in the processes and tools we use.
Majo statt Senf, CC BY-SA 4.0
  https://commons.wikimedia.org/w/index.php?curid=38767688

Avoiding Errors from Becoming Defects

In all the teams I’ve worked with, we make mistakes continuously. Some are just development process errors, while others are misunderstandings. The latter arise because we’re constantly learning about the problem. This is the reality: we make mistakes constantly, and everyone I know in this profession makes them. Some more, some less, but no one is error-free.

If we acknowledge and accept this reality, the important thing is to understand that the goal is not to completely avoid errors (something impossible), but to ensure that those errors don’t become defects that impact the final user experience. The article “Be humble, no rockstars allowed” advocates for humility and teamwork in software development, emphasizing that continuous learning and effective error management are crucial—rather than relying on individual “rockstars.” See article for more.

This is Lean Software Development’s approach: acknowledge and accept that we make mistakes, and focus on having a process that allows us to detect them, protect ourselves from them continuously, resolve them, and prevent them from becoming defects.

How do we achieve this?

  1. Incorporating quality in every phase of development, automated whenever possible (Jidoka + Poka-Yoke).
  2. Continuously improving the mechanisms and techniques that ensure quality at each stage (Kaizen).

In the next article, we will explore how to detect errors as early as possible, stop the flow when they appear, and learn from them without pointing fingers. This could mean stopping the CI/CD pipeline if an integration test fails, blocking code commits if unit tests don’t pass, stopping a pairing session if a critical error is discovered, or even temporarily halting new feature development to address a severe performance issue. Because working with quality also means having a strategy so that errors don’t become defects.

Monday, April 07, 2025

The Phrases That Power My Leadership

Over the years, I’ve noticed that certain phrases have become central to how I lead teams. They're not just casual remarks—they're powerful tools that shape our culture and drive our decisions.

My leadership style leans more on intuition than rigid structure. But through reflection, I’ve realized I often return to the same phrases. These serve as mental shortcuts that influence how we work, decide, and collaborate.

"What’s the worst that could happen?" encourages experimentation without fear. It reflects a mindset of calculated risk-taking and a commitment to creating a safe space for innovation. This question only works if we can confidently answer, “Nothing serious—and we can fix it quickly.” That confidence comes from a strong foundation: technical excellence, sound design, automated testing, and continuous deployment. 


When we trust our systems and processes, experimentation becomes second nature. Then, questions like “What’s the next seemingly impossible goal we’ll accomplish?” don’t sound wild—they become grounded ambition. This mindset grows by breaking down complex problems and making thoughtful decisions step by step.

"Can we avoid doing it?" and "Can we achieve the same impact with fewer resources?" drive us toward efficiency. These align with Lean principles: reduce waste, maximize value. They help us cut complexity and focus on what truly matters. "What if we only had half the time?" forces us to prioritize and think about vertical slicing, ensuring we get feedback sooner. When technical quality is high, it’s easier to identify what’s unnecessary, simplify with confidence, and adapt quickly. Even a suggestion like “Let’s remove it and monitor the impact; we can restore it if needed” becomes a safe, low-risk move. In an environment with solid observability, metrics, and rollback capabilities, deletion becomes just another experiment. Another phrase I often use is, “Don't do anything I wouldn't do.” This encourages a sense of shared responsibility and ensures that everyone feels empowered to make decisions within the established boundaries and values of the team. It promotes trust and reinforces that we're all in this together.

These phrases go beyond individual decisions. They spark a positive feedback loop:

  1. Technical excellence builds speed and confidence.
  2. That enables experimentation, learning, and impact.
  3. That impact strengthens the team’s autonomy and trust within the organization.
  4. That trust leads to more investment—and more progress.

It’s a virtuous cycle. It doesn’t happen overnight, but once it begins, it changes everything.

In the end, these phrases work because they reflect a way of working built on ambition, focus, and care. We aim for innovation and execution while supporting each other along the way. And they work because there are teams who don’t just understand them—they live them every day.

This approach is also only possible thanks to the patience and insight of my colleagues. Thank you for joining me in exploring new ideas—and for steering us wisely when needed.

These are just a few of the phrases that guide my leadership. I’d love to hear the ones that guide yours. Feel free to share them in the comments below!

Related Articles (for more context and related principles):


Ultimately, these phrases—and the principles behind them—help build a culture of trust, innovation, and continuous improvement. It’s about empowering teams to do their best work and make a real impact.


Thursday, April 03, 2025

Lean Software Development: Construyendo con Calidad

Primera parte de una serie sobre cómo construir con calidad desde los principios de Lean Software Development. En esta entrega exploramos qué significa realmente "calidad", cómo se diferencia del enfoque tradicional y qué principios nos ayudan a evitar que los errores se conviertan en defectos.

Lean Software Development: Construyendo con Calidad

Una de las grandes diferencias entre Lean Software Development y los enfoques tradicionales radica en el tratamiento de la calidad, tanto del software o producto resultante como del entorno de trabajo (colaboración, herramientas, comunicación).

Lean Software Development considera la calidad como una parte integral del valor del producto, imprescindible para aportar valor al cliente de la manera más eficiente posible. Desde esta perspectiva, todos los problemas de calidad se consideran uno de los principales desperdicios que debemos eliminar.

En contraste, los enfoques tradicionales suelen centrarse principalmente en la calidad del producto final. Lean, por su parte, pone el foco en la mejora continua de los procesos y del sistema que genera ese producto final.

El control de calidad, que tradicionalmente se enfoca en la inspección del producto al final del proceso, se convierte en Lean en una parte fundamental de cada etapa. Dicho de otro modo, en lugar de inspeccionar y validar la calidad al final, esta se construye desde el principio y se mantiene durante todo el proceso. Esto implica pasar de una aproximación reactiva a los problemas a una más proactiva, visibilizando cualquier inconveniente con el objetivo de solucionarlo de inmediato y atacando las causas raíz (sistema o procesos).

Podemos resumir estas diferencias de la siguiente forma:

Foco

  • Tradicional: Principalmente en la calidad del producto final.
  • Lean Software Development: Mejora continua de los procesos y sistemas.

Control de calidad

  • Tradicional: Inspección al final o en puntos concretos de la producción.
  • Lean Software Development: Calidad incorporada en cada paso (jidoka).

Resolución de problemas

  • Tradicional: Reactiva, abordando los problemas después de que ocurren.
  • Lean Software Development: Proactiva, destacando y resolviendo los problemas inmediatamente.

Al final, Lean Software Development considera que todo el retrabajo (incidentes, resolución de bugs, procesos repetidos, etc.) generado por problemas y defectos es uno de los grandes desperdicios a eliminar. Por ello, se enfoca en introducir calidad en cada paso del proceso, minimizando el desperdicio y fomentando un hábito de trabajar con calidad y mejorar continuamente.


La calidad es un concepto amplio que puede abarcar varios aspectos: la calidad externa (cómo es percibida por el cliente o usuario final), la calidad interna (relacionada con la facilidad de evolución y mantenibilidad del código o sistema) e incluso la calidad de nuestros procesos y entorno de trabajo.

En esta serie de artículos, pondremos especial énfasis en la calidad externa, tal y como la perciben los clientes o usuarios. No obstante, también abordaremos aspectos de calidad interna y de proceso, ya que son fundamentales para sostener una calidad externa alta a largo plazo. Además, dado que Lean Software Development pone un fuerte énfasis en la mejora continua tanto de los procesos como del sistema para garantizar dicha calidad, también abordaremos aspectos relacionados con la calidad de los procesos y el entorno de trabajo.

Conceptos base

Comencemos con algunos conceptos y definiciones que nos serán útiles en el resto de los artículos:

  • Error: Consideramos un error como cualquier desviación del resultado esperado. Por ejemplo, en la ejecución de nuestras aplicaciones, un error puede ser un test fallido, código que funcionalmente no cumple con lo esperado, entre otros.
  • Problema: En el contexto de Lean Software Development, un problema es cualquier obstáculo que nos impide entregar valor al cliente de la manera más eficiente y efectiva posible. Esto incluye la diferencia entre el estado actual y el estado deseado, pero también abarca situaciones como:
    • Requisitos ambiguos que llevan a una implementación incorrecta.
    • Problemas de comunicación entre el equipo que resultan en malentendidos y retrasos.
    • Limitaciones técnicas que impiden alcanzar el rendimiento deseado.
    • Ineficiencias en el proceso de despliegue que causan demoras
  • Defecto: Es un error que impide que el producto cumpla su función o propósito afectando de forma directa a los clientes. Los defectos son una de las principales fuentes de desperdicio identificadas en Lean Software Development (ver Eliminar desperdicios en el desarrollo). Por ello, es prioritario evitarlos siempre que sea posible y eliminarlos de inmediato cuando se detecten. El artículo enlazado explora cómo Lean Software Development adapta los siete tipos de desperdicio del Lean Manufacturing al software, enfocándose en eliminar actividades que no añaden valor al cliente y promoviendo prácticas como reducir el "Trabajo Parcialmente Hecho" y evitar "Funcionalidades y Código Extra". Ver artículo para ampliar. 

Es importante recordar que los defectos son un subconjunto de errores, y los problemas pueden incluir múltiples errores y defectos.

Aunque esta clasificación puede parecer confusa al principio, distinguir entre problema (una situación genérica que incluye errores y defectos), error (cualquier desviación de lo esperado, como un test fallido, un nombre incorrecto para una variable o una funcionalidad mal implementada) y defecto (un error que afecta al cliente o al propósito del sistema y fuente fundamental de desperdicio) nos ayuda a comprender mejor la situación y a definir procesos adecuados para abordar cada caso.

Enfoque Lean para la reducción de errores y defectos:

  • Jidoka: También conocido como "autonomación", este principio busca detectar y corregir defectos automáticamente, deteniendo la producción en cuanto se identifica un error. Un ejemplo clásico de esto en Lean Manufacturing son las "Andon Cards", sistemas de señalización visual que permiten a cualquier trabajador detener la línea de producción al detectar un problema. En nuestro contexto de desarrollo de software, esto se traduce en testing automatizado en distintas etapas, alarmas y monitorización, el uso de un pipeline de CI que detiene el despliegue si las pruebas fallan, entre otros mecanismos.
  • Poka-Yoke: Traducido como "a prueba de errores", este enfoque se basa en sistemas y diseños que previenen errores humanos. En el contexto del desarrollo de software, Poka-Yoke se aplica tanto a nuestros procesos internos como a la interacción del usuario con el producto.
    • En el proceso de desarrollo, implementamos Poka-Yoke a través de prácticas como el uso de tipado fuerte en lenguajes de programación, herramientas con valores predeterminados óptimos, tests automatizados, el uso de ValueObjects y precondiciones. Estas técnicas ayudan a prevenir errores de codificación y diseño.
    • En la usabilidad del software, aplicamos Poka-Yoke mediante sistemas anti-error, mensajes de ayuda contextual efectivos y diseños intuitivos. Aquí es donde la Experiencia de Usuario (UX) juega un papel crucial. Aunque la UX no es un mecanismo Poka-Yoke directo en el sentido técnico (como un sensor físico que detiene una máquina), comparte el objetivo fundamental de prevenir errores del usuario. Un buen diseño de UX anticipa posibles errores, guía al usuario de manera clara y ofrece retroalimentación inmediata, reduciendo significativamente la probabilidad de que cometa errores. En este sentido, la UX complementa y refuerza los principios de Poka-Yoke, asegurando que el software sea lo más intuitivo y libre de errores posible para el usuario final.
  • Kaizen: Es el principio de mejora continua aplicado a nuestros procesos y sistemas. Como uno de los pilares de Lean, fomenta la búsqueda constante de formas de reducir errores y mejorar la calidad, tanto en el producto como en los procesos y herramientas que utilizamos.
De Majo statt Senf - Trabajo propio, CC BY-SA 4.0
https://commons.wikimedia.org/w/index.php?curid=38767688

Evitar que los errores se conviertan en defectos

En todos los equipos con los que he trabajado, cometemos errores de forma continua. Algunos son simplemente errores en el proceso de desarrollo, mientras que otros son errores de entendimiento. Estos últimos surgen porque vamos aprendiendo sobre el problema de manera continua. Esta es la realidad: cometemos errores constantemente, y todas las personas que conozco en esta profesión los cometen. Unos se equivocan más, otros menos, pero nadie está libre de errores. 

Si reconocemos y asumimos esta realidad, lo importante es entender que el objetivo no es evitar completamente los errores (algo imposible), sino asegurarnos de que esos errores no se conviertan en defectos que impacten la experiencia del usuario final. El artículo "Be humble, no rockstars allowed" aboga por la humildad y el trabajo en equipo en el desarrollo de software, enfatizando que el aprendizaje continuo y la gestión efectiva de errores son cruciales, en lugar de depender de "rockstars" individuales. Ver artículo para ampliar.

Esa es la aproximación de Lean Software Development: reconocer y aceptar que cometemos errores, y enfocarnos en tener un proceso que nos permita detectarlos, protegernos de ellos de forma continua, solventarlos y evitar que se conviertan en defectos.


¿Cómo lo conseguimos?

  1. Incorporando calidad en cada fase del desarrollo, de forma automatizada siempre que sea posible (Jidoka + Poka-Yoke).
  2. Mejorando continuamente los mecanismos y técnicas que garantizan la calidad en cada etapa (Kaizen).
En la siguiente entrega, exploraremos cómo detectar errores lo antes posible, detener el flujo cuando aparecen y aprender de ellos sin buscar culpables. Esto podría significar detener el pipeline de CI/CD si una prueba de integración falla, bloquear la subida de código si no pasa los tests unitarios, detener una sesión de pairing si se descubre un error crítico, o incluso detener temporalmente el desarrollo de nuevas funcionalidades para abordar un problema de rendimiento grave. Porque trabajar con calidad implica también tener una estrategia para que los errores no lleguen a convertirse en defectos.