You’re probably familiar with yak shaving: that is, an infinite recursion of tasks theoretically in support of your original task, but each of which is progressively less related to the original task. You know, you run into a bug with a Ruby gem that’s fixed in the latest dot release, so you try to upgrade, but then you realize that you need to build a support library from source to do so, and then you remember that you hadn’t get installed gcc after a from-scratch install of Leopard, but that reminds you that you left your OS disks at home, so you need to…
This, of course, can be a serious waste of time and loss of focus. Managers at big software companies are kept awake at night thinking about the fact that half their dev team might be off shaving yaks even though the deadline for their project is two weeks away. At small startups without any managers, it can simply lead to the death of the company. How many startups have spent years building some really impressive architecture or toolset with which they intend to build their product, but not the actual product? I can think of a few. In fact, my very first software job was at a company that did exactly this.
There’s another side to yak-shaving, though. Sometimes you really do need to enhance underlying tools or architecture to enable your current task, and future related tasks. Whether it’s rearranging your directory structure, streamlining the build process, or writing some diagnostic tools, a project can only stay agile if it has the proper infrastructure.
The counterargument to that (is that a counter-counterargument?) might be: sure, but work on the infrastructure some other time, when you’re not focused on a particular task. This seems compelling, but experience tells us that it doesn’t really work. You can’t see what needs to be done to fix the problem unless you’re in the thick of something that needs the fix.
For example: it’s hard to do any kind of serious refactoring just ‘cause. You can know that a codebase is due for some serious janitorial work, but without a specific goal in mind it’ll be hard to focus your efforts.
Let’s say you’re trying to diagnose a bug. To understand what’s going on you need to see it in isolation, so you need to write a test that triggers it. In trying to write a test, though, you realize that the way the object’s methods are laid out can’t be tested in isolation. Perhaps the methods need to be broken apart, and use parameters and return values instead of modifying object member variables directly. But to do that you may need to modify other places in the code which call the object. So here you are, changing code which has absolutely nothing to do with the bug you’re trying to fix. Sound familiar? That’s yak shaving, alright.
But in this case, now is the time to write that test and make those changes to that object. You could just struggle by and fix the bug without it, and then make a note to come back and write the test later, but you probably won’t. Because you won’t need it then. But the next time something in that same code breaks, suddenly it will all come into focus again…
So sometimes the yak DOES need a haircut. Just be mindful as you do it. Am I shaving this yak because it will be very valuable to my current goal and the project as a whole? Or am I doing it because I followed a rabbit trail of dependencies, and no one will care one way or the other whether the yak is shaved tomorrow?