Lean product development is unarguably an amazing strategy to mitigate product risk and to reduce cost of failure. Unfortunately you can’t apply it to everything: When you build something more complex than a standard web app, you’ll likely run into situations of high complexity and strong dependencies that can’t be necessarily addressed with best practice lean methodologies.
What Cats And Software Have In Common
Put kitty in an isolated room with a flask of poison that has a 50% chance of releasing its deadly content and killing the cat. Based on the Copenhagen interpretation of quantum mechanics, kitty is both dead and alive at the same time before it gets observed — it’s in a quantum superposition. When an observer opens the room, the cat is either dead or alive. Means reality collapses to only one possibility. This thought experiment (no actual cats died) is known as Schroedinger’s cat.
Before you release a new software component to your users, you deal with predictions on multiple dimensions. There a probabilities around feature adoption and KPIs (key performance indicator) as well as probabilities around the actual technical implementation (expected errors etc.). You can channel these probabilities by making more accurate predictions. But we all know how hard it is to predict things in complex systems.
So in the moment you ship your software it’s essentially in a superposition. Once traffic hits your new component, reality on every dimension starts to collapse. In reality you have an incredible large number of dimensions that can collapse within a complex software system. We can’t predict to what truth each dimension is gonna collapse. Everyone who worked on larger scale software systems with fast changing requirements would probably agree that it’s incredible hard to precisely predict how a certain feature will be used.
Deriving from that, also your assumptions regarding your testing strategy might prove as wrong. If it turns out your component is heavily used in an unexpected way, you’ll likely run into cases you haven’t thought about when writing your tests. Your goal should be to minimize the number of dimensions that will collapse once observed / hit by real-word usage.
Complex Problems In A Lean World
Uncertainty is inherent and inevitable in software development processes and products.
Ziv, Hadar and Richardson, Debra J.
The Uncertainty Principle in Software Engineering. (1996)
You should always be aware that things like user validation, testing and defining and executing on technical requirements happen under high uncertainty. To cope with this problem, in software development we usually split up new features in the smallest deployable tasks or stories possible. As it happens, printing is unfortunately not the most straightforward problem to solve. Due to the inherent complexity of dealing with operating systems, hardware and networks, we unfortunately can’t always apply lean methodologies to our product development.
When we work on lower level features, it sometimes takes weeks until we can ship the first iteration of a feature. Consequently the risk of breaking existing code and the risk of failing user adoption significantly increases. Dealing with complexity and strong dependencies is a situation you usually try to avoid running into as a startup because the cost of failure significantly increases. I think the best way of dealing with these fundamentally complex situations requires that your whole organization adapts and aligns their work process. This includes spending more time on user validation and evaluating the business value more carefully. Essentially you have to find a balance between keeping up the pace while avoiding the most costly mistakes.
The two most important things to consider here are the interface between business and engineering and the adaptability of the the feature or component you’re building. An open discussion between business and engineering leads to reducing risk by helping each party to align their requirements and expectations. Aligning expectations is incredibly important or you’ll end up responding to questions like “Why did it take two months to implement this button?” and more and more unsatisfied stakeholders over time.
Design For Adaptability
When it comes to the actual software design we usually tend to design for adaptability. This specifically means you design for easy extensibility and make assumptions about possible adaptations you might need to make after releasing your feature to the real world. Early on, ask yourself questions like “How hard is it to adapt feature XYZ if it turns out my users are using it differently than anticipated?” or “How strongly is it coupled with other existing components in my system and how can I reduce those dependencies?”.
Spending some time doing these thought experiments and adapting your software design and development process accordingly will save you a lot of headaches and costly failures. It sounds simple, but with everyone raving about agile and lean methodologies we sometimes forget that lower level systems still bear broad complexities that can’t be always split up in bite sized chunk.