Perfectionism is a poor developer's excuse for not getting the work done.
Larry Wall, in the glossary of the first edition of Programming Perl, famously notes:
We will encourage you to develop the three great virtues of a programmer: laziness, impatience, and hubris.
In the second edition of the book the terms are further defined:
Laziness: The quality that makes you go to great effort to reduce overall energy expenditure. It makes you write labor-saving programs that other people will find useful, and document what you wrote so you don't have to answer so many questions about it. Hence, the first great virtue of a programmer. Also hence, this book. See also impatience and hubris. (p.609)
Impatience: The anger you feel when the computer is being lazy. This makes you write programs that don't just react to your needs, but actually anticipate them. Or at least pretend to. Hence, the second great virtue of a programmer. See also laziness and hubris. (p.608)
Hubris: Excessive pride, the sort of thing Zeus zaps you for. Also the quality that makes you write (and maintain) programs that other people won't want to say bad things about. Hence, the third great virtue of a programmer. See also laziness and impatience. (p.607)
While Perl is not everyone's cup of tea, the ideas expressed in the above quote apply to programming in general. Very recently I assigned what I thought was an easy task to a relatively new developer, and gave him explicit guidelines to skip certain "best practices". The task was performance sensitive, a background process that would receive a huge lump of XML from a webservice (that we didn't control), transform the data, do a couple of simple checks and then store them in our database. The size of the XML data was huge and we expected it to get gigantic in the very near future, this thing needed to be fast. Really fast.
What he came up with, a week later, can only be described as an over-engineered piece of crap (honest assessment). It worked, flawlessly, for some smallish XML files I've given him to test the data transformations on, but when hooked up to the actual webservice it just couldn't cope, stuff started crashing at random, as they typically do when a background process faces performance issues. When I reviewed his code I found out, to my horror, that he had completely ignored me, the code was full of... design patterns! Poor noob had beautifully scribed an almost academic example of the strategy pattern for what was essentially a smallish switch statement, amongst other things.
Now, don't get me wrong, he applying patterns wasn't the root cause of the performance issues we were facing, however he had spent all week trying to write the "best" code possible when he should have quickly hacked the code in a day or two, and then spend the rest of the time stress testing the damn thing and identifying bottlenecks. And now I had to dig through thousands of uneccessary lines of code to even start getting an idea what was going on. No chance of me wasting my time like that, just scrapped the whole thing and wrote it from scratch in a few hours.
I discussed his code with him, and my conclusions are:
- He had just discovered some of the concepts he applied, and was too eager to see them in action, and
- He, unknowingly, wanted to impress (not me, but the team in general).
Enthusiasm is great, rushing to apply concepts you might not yet fully understand in your code is not. Even if you do fully understand them, more often than not you don't actually need them. One of the guiding principles of Extreme Programming is "You ain't gonna need it" (YAGNI), and it's a principle that I always try to pass to newer developers. Ron Jeffries, one of the founders of XP, explains:
Often you will be building some class and you’ll hear yourself saying "We’re going to need...".
Resist that impulse, every time. Always implement things when you actually need them, never when you just foresee that you need them. Here’s why:
- Your thoughts have gone off track. You’re thinking about what the class might be, rather than what it must be. You were on a mission when you started building that class. Keep on that mission rather than let yourself be distracted for even a moment.
- Your time is precious. Hone your sense of progress to focus on the real task, not just on banging out code.
- You might not need it after all. If that happens, the time you spend implementing the method will be wasted; the time everyone else spends reading it will be wasted; the space it takes up will be wasted.
- You find that you need a getter for some instance variable. Fine, write it. Don’t write the setter because "we’re going to need it". Don’t write getters for other instance variables because "we’re going to need them".
The best way to implement code quickly is to implement less of it. The best way to have fewer bugs is to implement less code.
You’re not gonna need it!
Several of my answers on Programmers advocate for best practices, however I hope I haven't mislead anyone into thinking that applying those best practices is a goal in itself. The goal is to get things done, done is better than perfect. Don't just blindly follow dogma, without a deep understanding of the concepts and practices, and an itch to scratch you are just setting yourself for a world of trouble.
Keep it simple, stupid!