Many in the Agile software development community espouse the advice that “Done is better than Perfect”, meaning that it’s better for a software development task to be functional in some way (”done”) than it is for it to feel fully complete in every way (”perfect”). While I’m sure the Borg won’t appreciate that, it is useful for individuals or teams that are struggling to ship, or that lose sight of their goal of delivering value to the customer and instead get pre-occupied with their personal pride in their work. Don’t get me wrong, having pride in one’s work is fine, but when it becomes a pre-occupation (i.e. obsession), it’s harmful to customer-oriented productivity.
My issue with this mantra is that it is too simple and has therefore developed a cargo cult (as all simple precepts can). Seeking perfection is obviously foolish, but contrasting “perfect” with “done” creates a false dichotomy where anything off the shortest path to a minimally-functioning (i.e. barely done) implementation is foolish. This can lead to an inadvertent habit, or even the explicit goal, of shipping debt-heavy, barely-done code. Such code is unsustainable and therefore is itself foolish. Done ain’t necessarily better than Perfect.
What the mantra attempts to do is discourage work that doesn’t add significant value, but it’s heavy-handed simplicity overreaches. I prefer to avoid prideful, non-valuable work by repeating the much more pointed mantra, YAGNI (along with what I perceive to be its corollary, “ASAYNI”, as soon as you need it, which encourages useful investment in code rather than taking on technical debt). For example, by following ASAYNI in my own exploration of quality code, I discovered that as you refactor code into stable underlying structures (forming a “framework” if you will), the codebase not only becomes more consistent and predictable, but a strong “opinionation” also emerges. There are two things to note about this.
First, ASAYNI promotes investment, not only in projects but in developers. The opinionation yielded by the commitment to refactoring has ongoing effects on correctness and maintainability/readability for the life of the project. Also, I am now armed with better refactoring skills, and can refactor more efficiently on future projects (which further improves my refactoring skills). These are effects that compound with time. Despite this, refactoring into anything resembling a “framework” is often looked at as bad practice, not only when YAGNI, but because to exceed barely done is to foolishly seek perfection.
Second, although it’s obvious in hindsight, I did not expect strong opinionation to emerge from extensive and aggressive refactoring. I did expect a tangible increase in re-use and a standardization of code, but not the intangible feeling that I built an over-arching “way” of doing something. Despite study of refactoring, I’d never applied it so aggressively, and this experience of something unexpected happening hammers home the idea that some things can only be learned by experimentation. Sure, not all experiments yield unexpected discoveries, but by limiting yourself to “barely done”, you categorically cut yourself off from finding them.
Software development is a balancing act, the necessary accommodation of multiple orthogonal concerns (correctness, maintainability/readability, performance, security, extensibility, defensiveness, re-usability, development cost, testability to name a few). If we’re constantly focused merely on reducing development cost, not only are our projects constantly tipping over, but we also never get good at balancing them.