There is a common belief in the software development world that a tradeoff exists between speed of delivery and quality, an idea Martin Fowler calls the Tradable Quality Hypothesis. It’s the idea that, in a pinch, you can speed up software delivery by not worrying so much about quality.
As Martin points out, people have different understanding of what quality means, but the definition that counts from a delivery point of view is that it’s the attributes that make the software easier to maintain and extend. Developers can work more quickly on code that is easy to understand and free from bugs.
So in practice, teams that prioritize speed over quality tend to achieve neither, while teams that prioritize quality, in many cases, deliver code very quickly.
The complexity axis
However, this isn’t always the case. Some teams focus on quality, but end up taking forever to deliver simple things. What’s missing from the speed vs. quality tradeoff is a second axis, completeness versus simplicity.
Another word for completeness on this chart would be complexity, but this quadrant represents the aspirations of a team - what the team is trying to achieve - and no team aspires to complexity. Instead, teams try to design and implement software and systems which are complete.
A team that prioritizes completeness wants a system that can cope with anything. It can meet completely new requirements through configuration rather than code, easily scale to handle any load, and tolerate any conceivable or inconceivable failure.
The problem with this is partly described by the YAGNI principle. Most of what the team built isn’t actually going to be needed. A large proportion of the stuff that will be needed in the future is stuff that the team didn’t anticipate. But the real killer is that adding all this stuff adds more moving parts. It’s more stuff to implement, more stuff to go break, and then it’s more stuff to wade through when working on the codebase.
So the team sets out to build the perfect, well-engineered system, but over time the schedule comes under pressure, and the team realizes it needs to step up the pace. Elements of the design are dropped, leaving parts of the system that were already implemented unused, but still taking up space (and adding complexity) in the codebase.
There is a nearly inevitable slide into cutting corners in order to get things done, and before you know it, you’re trading off quality (“we’ll go back and clean it up later”) for speed. As we’ve seen, this leads to a quagmire of poor code quality which slows work down, made even worse because of an overcomplicated design and large amounts of unnecessary code.
High performing teams hit the sweet spot
What seems to unite high performing development teams is an obsessive focus on both quality and simplicity. Implement the simplest thing that will satisfy the actual, proven need, and implement it well. Make sure it’s clean, easy to understand, and correct. If something is wrong with it, fix it immediately.
Teams that get this focus right are able to reliably deliver high quality software remarkably fast.