"Doing it well now is much better than doing it perfectly later"
That sounds fine until hundreds of developers make this choice every single day, and your project is so riddled with technical debt that forward progress becomes hard to muster. I'll be the first to admit that I postpone or neglect Yak Shaving myself.
If we think about it the other way around, if we shaved yak every single time, then the herd would be shaved, and we'd be able to work without so many distractions.
I guess the big problem with Yak Shaving, at least for a dayjob, is that it doesn't always count towards making forward progress toward your goals or OKRs, or whatever we want to call them. I think we need to recognize the importance of Yak shaving and reward the shavers.
The boy scout rule is a good compromise. Whatever areas of code you touch, leave it cleaner than how you found it. It doesn't mean following every path that leads to or from it (yak-shaving), but it's also not introducing new tech debt.
To be honest, most discussions about anti-Yak Shaving are about willfully ignoring the fact that you're going to have to shave a Yak, then asking people to strategically pluck single hairs whenever they're walking past the Yak because razors are expensive.
That's where refactoring comes in. Start with simple, local things. Make sure all the variables are properly and consistently named. Fix the indentation. De-duplicate cut'n'paste code (carefully!) where appropriate. Expand out functions that are only called from one place, where appropriate. Convert awkward control flow into more natural flow. So on and so forth. Abstract out common functionality into its own functions/classes.
You'll be amazed how, after a few iterations of this approach, even the worst spaghetti turns into something that you can start to reason about. (In fact, I find myself mentally referring to this kind of refactoring as 'combing spaghetti'.) And if you're careful to make sure none of your changes alter the function of the code, you don't lose the 'tried-and-tested' advantage of the original code.
This is peephole refactoring. Architectural redesigns (the ones that result in 1/10th the code with the same functionality but more robust, maintainable, etc etc) aren't feasible to do incrementally like this. If you're resourceful and clever, you can sometimes get to a certain point with both the old and the new architecture in place at the same time, but at some point you have to make the hard cut-over, and redevelop all the old features/edge-cases in the new system.
Even if you're starting with a disgusting hairball, a bottom-up approach will still get you to something understandable. At this stage you'll probably find that you can fix it one subsystem at a time without doing a full blank-slate rewrite. And once all of your subsystems are nice and independent and well designed, changing up the high-level architecture is far, far easier and safer.
If we think about it the other way around, if we shaved yak every single time, then the herd would be shaved, and we'd be able to work without so many distractions.
In medium to large size orgs "not shaving the yak" means pressing ahead with your deliverables and sidestepping wider issues. Doing this makes you appear indispensable to most middle managers but encouraging this en-masse is a long-term disaster for the org.
The org culture compels the behaviour, and is not really an individual choice.
Comments
"Doing it well now is much better than doing it perfectly later"
That sounds fine until hundreds of developers make this choice every single day, and your project is so riddled with technical debt that forward progress becomes hard to muster. I'll be the first to admit that I postpone or neglect Yak Shaving myself.
If we think about it the other way around, if we shaved yak every single time, then the herd would be shaved, and we'd be able to work without so many distractions.
I guess the big problem with Yak Shaving, at least for a dayjob, is that it doesn't always count towards making forward progress toward your goals or OKRs, or whatever we want to call them. I think we need to recognize the importance of Yak shaving and reward the shavers.
The boy scout rule is a good compromise. Whatever areas of code you touch, leave it cleaner than how you found it. It doesn't mean following every path that leads to or from it (yak-shaving), but it's also not introducing new tech debt.
To be honest, most discussions about anti-Yak Shaving are about willfully ignoring the fact that you're going to have to shave a Yak, then asking people to strategically pluck single hairs whenever they're walking past the Yak because razors are expensive.
I was going to say this... every shortcut to avoid shaving a yak is just creating a new yak that will need to be shaved next time.
Pretty soon, you are surrounded by nothing but yaks, and even yak shaving requires shaving ten other yaks first.
If you are lucky! Sometimes I reckon it’s so impossible to reason about tangled code that the only option is to rewrite!
That's where refactoring comes in. Start with simple, local things. Make sure all the variables are properly and consistently named. Fix the indentation. De-duplicate cut'n'paste code (carefully!) where appropriate. Expand out functions that are only called from one place, where appropriate. Convert awkward control flow into more natural flow. So on and so forth. Abstract out common functionality into its own functions/classes.
You'll be amazed how, after a few iterations of this approach, even the worst spaghetti turns into something that you can start to reason about. (In fact, I find myself mentally referring to this kind of refactoring as 'combing spaghetti'.) And if you're careful to make sure none of your changes alter the function of the code, you don't lose the 'tried-and-tested' advantage of the original code.
This is peephole refactoring. Architectural redesigns (the ones that result in 1/10th the code with the same functionality but more robust, maintainable, etc etc) aren't feasible to do incrementally like this. If you're resourceful and clever, you can sometimes get to a certain point with both the old and the new architecture in place at the same time, but at some point you have to make the hard cut-over, and redevelop all the old features/edge-cases in the new system.
Even if you're starting with a disgusting hairball, a bottom-up approach will still get you to something understandable. At this stage you'll probably find that you can fix it one subsystem at a time without doing a full blank-slate rewrite. And once all of your subsystems are nice and independent and well designed, changing up the high-level architecture is far, far easier and safer.
Do yaks not regrow their fur in this analogy?
In medium to large size orgs "not shaving the yak" means pressing ahead with your deliverables and sidestepping wider issues. Doing this makes you appear indispensable to most middle managers but encouraging this en-masse is a long-term disaster for the org.
The org culture compels the behaviour, and is not really an individual choice.
In my experience, only doing it "perfectly" means it'll never get done.