I consider myself a perfectionist.
When I’m writing a program, I want my code to be correct. It has to get the job done. At the same time, I strive to produce code that is perfectly formatted, fast, and (to me) beautiful. That in itself wouldn’t be a problem if all I did was to follow the wisdom of Kent Beck to “first make it work, then make it right, and, finally, make it fast.” Kent is right, of course. His advice is entirely reasonable. However, and here is the catch, it only works if you know when to stop.
There’s nothing wrong with refactoring and optimizing code per se – in fact, it’s essential to programming. But trying to Make It Right™ at any cost can be dangerous. I know this first hand. After spending countless nights in front of my computer, hacking on open source projects, I know what it’s like to get lost in implementing yet another tweak – a minor change that is supposed to make a difference. I know how it feels like to rewrite the same piece of code over and over again, with no end in sight. It’s frustrating, to say the least.
I don’t strive for the best in everything I do, but writing is another creative endeavor where perfectionism used to get in my way.
The biggest problem I face [with publishing content] is that I’m a perfectionist. I have a hard time writing shitty first drafts and postponing editing until after getting something down on paper first. Instead, I often try to get it “right” the first time, thereby making the writing process unnecessarily painful. The number of blog posts I’ve published this year is evidence enough of my struggle.
I wrote this in September 2014. These days I still suck at drafting. Writing continues to be a painful process from time to time. While I’ve figured out how to publish articles on a regular basis – the not-so-secret secret is writing consistently – I’m fully aware of the fact that perfectionism is a formidable obstacle to getting things done.
I like the way Anne Lamott put it in her great book, Bird by Bird:
Perfectionism is the voice of the oppressor, the enemy of the people. It will keep you cramped and insane your whole life, and it is the main obstacle between you and a shitty first draft. […] Perfectionism is a mean, frozen form of idealism
Back to perfectionism and programming. Before you open your favorite editor and attempt to achieve an unattainable ideal, consider the following:
Unless you’re building low-latency trading systems or similar software where every microsecond counts, you probably don’t need to write the most efficient code ever conceived. Don’t fall prey to premature optimization. And unless you have a strong reason to believe that your current design is inadequate, chances are that another layer of perfectly crafted abstraction won’t save the day. Moreover, there is no need to thoroughly document every method of your code unless you’re providing an API that is actually used by somebody.
When I work on some piece of code and I feel the urge for perfection creeping in my head, I like to ask myself these questions:
- Does this change really make a difference? Is it worth my time? Consider engineering costs vs. value created. Think long- and short-term.
- Does it provide value to the users of my software? Users typically don’t care about internals like program code.
- Does it matter to my coworkers? My boss? My future self?
By all means, I don’t want you to ship crappy code. But I do want you to remember that you have a choice – and more often than not, settling for good enough is a valid choice to make in a tech world that values shipping above all else.
At this point, I feel obliged to remind you that the best code is no code at all. Perfectionist or not, always start by looking for solutions that don’t involve writing code.
Tools and practices
If you’re reading this, you’re probably a programmer yourself. I guess you’re looking for some advice that’s a bit more concrete. I hear you. Here are six things that help me overcome perfectionism in programming:
Tooling. Remember that I want my code to be perfectly formatted? For me, tools like gofmt are a godsend. Never do I have to worry about whitespace or other formatting issues again. Instead, I can turn my attention to more interesting tasks.
Pair programming. I’ve experienced that the desire to finish work increases when working in pairs, in particular, if the work seems to be too hard or too boring or both. (Pair programming offers much more benefits.)
Code reviews. Besides pair programming, requesting a code review and getting an “LGTM” from my colleagues is another helpful indicator that my changes are good enough.
Testing. For me, perfectionism is closely related to confidence, the confidence in the code I write. Passing tests certainly increase the level of confidence in my work, provided I know the tests themselves are valuable.
Spikes. Rather than losing myself in details by trying to Make It Right™ from the get-go, I prefer creating a spike first. A spike is a simple (and dirty) end-to-end solution to a given problem, which is meant to be thrown away after exploration.
Deadlines. Having a due date, ideally imposed by someone else, helps me overcome perfectionism and procrastination. Going back to writing for a second: to keep on schedule, I had to press the button for publishing the very post you’re reading.
Reading over this list again, it becomes apparent that it’s not only about fighting perfectionism, it’s also a set of established practices for producing quality software. I call this a win-win.
This piece was inspired by the spot-on post, Terrors of perfectionism. Among other things, it helped me realize how often we consider a solution to a problem to be flawed and therefore temporary. Then we end up using it in production until doomsday.