First published June 2017. Apparently I was already toying with the tidying metaphor, even if I could have sworn I didn’t start using it for another 4 years. Memory is a funny thing.
I have been tidying up server code and loving it. I’ve tidied up for thousands of hours over my career, and I have some rules for making this style of cleanup safe, fun, and efficient.
Tidying up works through a series of small, safe steps. In fact, Rule #1 is If it’s hard, don’t do it. I used to do crossword puzzles at night. If I got stuck and went to sleep, the next night those same clues were often easy. Instead of stressing about the big effects I want to create, I am better off just stopping when I encounter resistance.
Tidying up is concave [ed: this was also when I was digging in to 3X: Explore/Expand/Extract] in the sense that you have a lot more to lose by a mistake than you have to win by any individual success (more on that later). Rule #2 is Start when you’re fresh and stop when you’re tired. Get up and walk around. If I don’t come back refreshed, I’m done for the day.
Tidying up can happen in parallel with development, but only if you carefully track other changes (I messed this up with my latest diff). Rule #3 is Land each session’s work immediately (after review, natch). Unlike feature development, where it sometimes makes sense to land only when a chunk of work is done, tidying up is time based.
Tidying up requires little effort for any step, so I am willing to discard any step at the first sign of trouble. For example, Rule #4 is Two reds is a revert. If I tidy, run the tests, and encounter a failed test, then if I can fix it immediately I do. If I try to fix it and fail, I immediately revert to the last known good state.
Tidying up works even without a vision of the shiny new design. However, sometimes I want to see how things might play out, so Rule #5 is Practice. Perform a sequence of tidyings and revert. The second time will go much faster and you’ll be more familiar with which bumpy spots to avoid.
Try it. Move the declaration of a temp adjacent to its first use. Simplify a boolean expression (“return expression == True” anyone?). Extract a helper. Reduce the scope of logic or state to where it is actually used.
The Rules
If it’s hard, don’t do it
Start when you’re fresh and stop when you’re tired
Land each session’s work immediately
Two reds is a revert
Practice
Coda
I’ve made architectural changes strictly by tidying. I’ve extracted frameworks strictly by tidying. You can make big changes safely in this style. I think this is because, while the cost of each tidying is constant, the payoff is power-law distributed. I need both data and a model to explain this hypothesis.
Is your business looking to juice the value they get from software development. Consider my new workshop—Lead Geeks With Purpose. It makes an excellent holiday gift for the CEO who has everything.
I think that the scale of tidyings a developer can perform safely and comfortably can grow as the developer's experience with performing them grows. Do you agree?
For example, I can comfortably perform several changes that are slightly larger than many of the Tidyings you've described "at once" (ie, in one commit) in some code bases, but only now after 25+ years of experience in general and 15 or so in a particular language. I sometimes overestimate that ability and end up having to revert or spend more time than I should, but I feel safe because I'm aware of those triggers you've described - I just choose to ignore those "I've got a funny feeling about this" every once in a while.
Now, having written that thought down, I realize that certain code bases might be more "large tidyable" than others. It would be interesting to explore the characteristics of a code base that contribute to its tidyability scale.
So really 2 thoughts/questions here: 1) the individual developer's personality and experience level might contribute to the types and sizes of tidyings, and 2) the code base itself might contribute.
PSA: tidying is not the same as refactoring OOP code to functional because it's your style preference or creating many new abstraction without consulting the rest of your team regarding the agreed upon design patterns to use.