This site will look much better in a browser that supports web standards, but is accessible to any browser or Internet device.
Every bit of code we write is the result of trade-offs. Some seem like no-brainers: what language to use, which paradigm to use. Others are more subtle: how important is speed/maintainability/memory, fail fast or never fail, fix a bug quickly or rewrite to prevent that class of bugs.
One of the big trade-offs is between simplicity and complexity. Most good programmer at least pay lip service to the idea that we should keep our solutions as simple as possible. Unfortunately, most of us fall prey to the temptation to make our code a little more complex in the name of flexibility or future-proofing. All of these reasons really boil down to a belief that we can predict how the code will change in the future and code to protect against that.
There's only one real problem with this idea. Years of empirical evidence show that, individually and as a group, we are pretty lousy at predicting the future.
As a general rule, programmers are smart people (or, at least, believe ourselves to be). We are also somewhat attracted to complexity. (Honestly, would someone who truly abhors complexity learn to program computers?) We also like to solve problems (sometimes problems no one else cares about). This leads to the tendency to guess the future, convince ourselves we are right, and code to prevent problems that only we are bright enough to see. You only have to be sort of right once (or read about someone who was) to get the idea that you can do this repeatably.
All human brains are well suited to finding patterns. Some research has suggested this is one of the most important features of our brains. In my experience, programmers seem to have even more finely honed pattern-matchers behind our eyes than most people. This sometimes causes us to jump to a general solution for a pattern that we have recognized that may not actually exist. In many cases, this general solution is much more complex than the original solution to the specific problem we started with. We justify the extra complexity based on the problems it will solve in the future.
We know that a simple solution is easier to understand and maintain. A simple solution is also easier to evolve as necessary to cover new needs in the future. Most good developers try to make simple solution to begin with, but it gets more complex the longer we work on it. Although some of that complexity comes from a better understanding of the problem, you have to admit some of it comes from us wanting to be clever.
A lot of this cleverness manifests from a desire to predict the future and code for the issues we can foresee. The problem is that predicting the future is quite hard. Any complexity that we add to deal with potential future needs will still need to be maintained between now and the future time where it is needed. That's a cost. If we never reach the predicted future where this complexity helps, then this extra cost is a waste.
Extreme programming had a really blunt term for this YAGNI. The idea is to avoid adding functionality until the point in time that you actually need it to fulfill a customer requirement. Until that time, you do not need the feature and, therefore, should be spending your time on actual customer requirements. Any time you start designing for potential future needs or generalizing so that we can support potential changes later, you really need to remember YAGNI.
I tend to use this term ruthlessly. I have spent a large part of my career maintaining code that is too general or too feature-rich for the current need. Sometimes, I have seen people fix bugs or speed up real functionality by removing code intended for a future that never happened. Because of this, I try to remember YAGNI every time I consider making a change for the future.
Posted by GWade at November 12, 2014 07:18 AM. Email comments