Software should be maintainable. Software should also be performant. Which is more important? Well, as it turns out, in order to optimize software for performance, it must be maintainable. Ease of change can easily be the most important factor in making something run well.
Premature Optimization
“In which everything is possible but nothing of interest is easy.”
– Alan J Perlis
Optimization up front often hinders evolution, because it’s designed to address a very specific concern without regard for future concerns. This is not to say that optimization is not important, it’s just something that should be done in such a way as to not hinder the ability to respond to change. Also, today’s compilers are a lot smarter than you are and can perform lots of optimizations themselves. Sometimes you simply aren’t smart enough to know where the bottlenecks occur, so it’s important to not optimize until you’ve actually proven via measurement where and why a performance issue occurs.
Programmers are really smart people, but unfortunately many programmers take pride in their ability to develop and understand complicated code. This is a danger that must be understood and avoided; particularly when it results in less maintainable code, or code in which only that single developer is capable of understanding and maintaining.
YAGNI
You Ain’t Gonna Need It. Resist the urge to optimize or implement functionality until it’s needed. This simple idea is actually the basis for much of agile software development. 90% of the functionality developed and shipped quickly is better than 100% of it shipped late or never. Why should you hold off on optimizing or implementing until it’s needed? The simple truth is that you don’t know what will be needed down the road, and so developing for it now will be a waste of time. Often times it turns out the code you prematurely wrote isn’t even needed, or your assumptions were wrong. So not only will you not need it, but even if you do, it won’t be in the right form that you are anticipating today.
Clarity and Explicitness
Writing code that’s clear and explicit is better than writing code that’s clever. Programmers are really expensive, so it’s to your benefit to write code that optimizes for their time, and the way to do that is to write code that communicates to people, not the machine. Write the code so that it can be understood now and in the future with little or no additional explanation needed about how it works.
Delete Code
Everyone has probably seen Andy Hertzfeld’s story of Bill Atkinson during the development of MacPaint:
In early 1982, the Lisa software team was trying to buckle down for the big push to ship the software within the next six months. Some of the managers decided that it would be a good idea to track the progress of each individual engineer in terms of the amount of code that they wrote from week to week. They devised a form that each engineer was required to submit every Friday, which included a field for the number of lines of code that were written that week.
Bill Atkinson, the author of Quickdraw and the main user interface designer, who was by far the most important Lisa implementor, thought that lines of code was a silly measure of software productivity. He thought his goal was to write as small and fast a program as possible, and that the lines of code metric only encouraged writing sloppy, bloated, broken code.
He recently was working on optimizing Quickdraw’s region calculation machinery, and had completely rewritten the region engine using a simpler, more general algorithm which, after some tweaking, made region operations almost six times faster. As a by-product, the rewrite also saved around 2,000 lines of code.
He was just putting the finishing touches on the optimization when it was time to fill out the management form for the first time. When he got to the lines of code part, he thought about it for a second, and then wrote in the number: -2000.
I’m not sure how the managers reacted to that, but I do know that after a couple more weeks, they stopped asking Bill to fill out the form, and he gladly complied.
This is a great example to follow when considering YAGNI. Not only should you resist the urge to prematurely optimize or develop, you should also aggressively remove unused or unneeded code.
Solutions?
How do you protect your code base from complexity and premature optimization?
The only real solutions here are as follows:
- Hire developers who understand YAGNI
- Hire developers who understand that a primary goal of their job is to use their code to communicate to other developers instead of the computer.
- Encourage a culture that understands that simplicity is better than complexity.
I’ll end with the same quote everyone slathers around the web, because even though it’s repetition is common, it’s still true.
“Premature optimization is the root of all evil.” –Donald Knuth
