This triangle is a bit of a cliche, but there is definitely a nugget of truth in there. You really can't have it all, no matter how much you want it. The problem I have is that it's a bit hard to explain - drawing triangles out is a little bit abstract when you're explaining this principle - and more than once I've gotten the "well, let's just add some resources and make the triangle bigger" response.
The fundamental problem that we're trying to explain here is that releases are dependent on several factors:
- How many resources you have (people, machines, etc)
- How much time you have
- How many features you want
- How many hurdles (read: tests that prove something about the feature) it has to clear (aka "How good it has to be")
- How well-designed you want it
Changing any one of these changes the release itself. Now the other interesting thing about this is that the point in the project at which these become fixed varies. Well-designed, for example, often comes early. You're not likely to change your fundamental design at the end of a project. The same holds true for resources; at some point throwing more resources at the problem no longer helps. Time and quality tend to be something that can change up to the end of the project.
In trying to to explain this to people who don't work in software (or who don't work deeply enough in software to understand its limitations), I tend to wind up using a different metaphor. Here's the story I tell:
When we start on a release, we make a few choices that really govern everything else that goes on. We chose a basic scope of the release, and we choose a design.
In essence, we're pulling a bowl off a shelf. We can go back to the shelf and change bowls later, but it's going to cost us a lot, and as our bowl gets full (i.e., as we get later in the release), we are restricted in the bowls we can choose and still have everything fit.
Second, we choose the features we want in the release. These can be new features, enhancements to existing features, bugs, whatever. We wind up with a big set of marbles that we're going to work on.
As development continues, we pick the marbles up, work with them for a while, and then put them in the bowl. This is where things start to get interesting. If we've chosen a lot of big marbles, then we're not going to fit them all in the bowl. If we've chosen too many marbles, they won't all fit in the bowl. If we've chosen too few marbles, then we'll have a half-empty bowl.
We still have options at this point:
- We can take marbles off the table. This is the metaphor for removing features (or bugs or whatever) from the release. The catch is, once we've started work, it's harder to remove the marble from the table; that is, it's harder to pull the code out once we've started it.
- We can take marbles out of the bowl. If the marble (aka the feature) is too big and we want more of the smaller marbles, that's possible. It's a lot harder than if we hadn't put it in to start with, though.
- We can go get a different bowl. If we get a bigger bowl, it'll fit, but we lose some time changing the bowl. If we get a smaller bowl, then not everything fits and we've made a mess! (This is what we call a disastrous release!) This is the metaphor for changing the release size or design. It's doable, but there's increased risk with it.
So you have lots of choices and lots of ways to make a release happen - different bowl sizes, different marbles - but in the end there are some things that can't be changed. All you can do is pick a bowl, pick some marbles, and make sure the marbles fit inside the bowl.