cat posts/2024-03-12-book-review-tidy-first.md
Book review: Tidy First?
The pull request that made me pick this book up was 1,900 lines long and did two things. It renamed and reorganized about a dozen files in our billing code, and somewhere in the middle of that, it changed how proration works when a customer downgrades mid-month. The reviewer approved the renames, which were most of the diff and obviously fine, and missed the proration change, which wasn’t. We found it in production a week later, from a customer who’d been charged $0.00 for a month.
Nobody did anything wrong there, exactly. The engineer did some cleanup on the way to the change, which is what I’d want. But the cleanup and the change were in the same pile, and a human reviewer can’t give 1,900 lines the same attention. Kent Beck’s Tidy First? (O’Reilly, last November) is about that pile, and the question mark in the title is the whole book: before you change this code, should you tidy it first? Sometimes. Sometimes after. Sometimes later. Sometimes never.
It’s short, about 125 pages, and it’s the first of a series Beck is planning on software design. He’s been writing it in public on his Substack for a couple of years, so some of it will be familiar if you read that.
The tidyings
The first part is fifteen tiny chapters, each one a small structural change you can make without changing behavior. Guard clauses. Deleting dead code. Normalizing symmetries (if the same thing is done three different ways in one file, pick one). Reading order and cohesion order, which are about moving code so it’s near the code it goes with. Explaining variables and explaining constants. Extracting a helper. Deleting comments that just restate the code.
Some of these chapters are a page long, and none of them will be new to anyone who’s been doing this for a while. I didn’t learn a single technique from this section. What I got from it was names, and names turn out to be useful in code review, because “can you split the normalize-symmetries part into its own PR” is a much easier comment to write and receive than “this is too big”.
The one tidying I didn’t expect is called One Pile. When code has been split into so many tiny pieces that you can’t follow it, Beck says, inline it all back into one big function, understand it, and then tidy it into pieces that make sense. That’s the opposite of the reflex I was taught, and of most of Clean Code, and it’s exactly what I’ve done by hand on every over-abstracted codebase I’ve ever had to fix. I wrote a few years ago that I’d take a 60-line function that reads top to bottom over fifteen three-line methods. It was nice to have someone with Beck’s credentials say something similar in print.
Separating them
The second part is about managing tidying, and it’s where the advice that’s actually changed how we work lives. The central rule is to keep tidying and behavior changes in separate commits, and ideally separate pull requests. Tidying PRs should be small, should be easy to review, and should get reviewed fast, because the reviewer’s only question is “does this still do exactly the same thing?”, which is a much smaller question than “is this change correct?”
Beck admits that’s not free. Separate PRs mean more round trips, and if your review latency is a day, splitting one PR into four costs you four days, which is why so much tidying never happens and gets folded into feature work instead. His answer is that if tidying PRs are slow to review, fix the review process, and he floats the idea of not requiring review for pure tidyings at all, which made me wince. I’m not there yet.
What we’ve done is a middle step. Since January, a PR labeled “structure only” is supposed to change no behavior at all, and reviewers are asked to turn those around the same day. Behavior PRs can come right after. The billing engineer’s next change went in as three small PRs and one tiny one, and the tiny one got the attention the proration change should have had.
The theory
The third part is where the book gets more interesting and also more hand-wavy. Beck’s argument for when to tidy is economic. Software creates value two ways: by what it does now, and by the options it gives you for what it could do next. A dollar today is worth more than a dollar tomorrow, which argues for shipping behavior first and tidying never. But a well-structured system is full of options, cheap future changes, and options are valuable in proportion to how uncertain the future is. So tidying is buying options, and whether it’s worth it depends on how likely you are to need them.
That framing is the most useful thing in the book for me, because it turns “should we clean this up?” from an argument about craftsmanship (which never ends) into an argument about which changes we expect to make in this code (which can actually be had). Code nobody’s going to touch again doesn’t need tidying, however ugly. Code we’re about to make five changes to does, and tidying first is cheaper than tidying after.
Then there’s coupling. Beck brings in what he calls Constantine’s Equivalence, from Larry Constantine’s work on structured design in the ’70s: the cost of software is roughly the cost of changing it, which is dominated by the cost of the big, expensive changes, which comes from coupling, where changing one element means changing others. I like it as a slogan. I’m less sure it’s as precise as the word “equivalence” suggests, and the book doesn’t really try to prove it.
The options section also skates past what an option is actually worth. The finance version comes with a lot of machinery for pricing them, and Beck uses the analogy for direction rather than for numbers, which is fair for a short book but left me wanting the next one.
I liked it more than I expected to after the first part. I’d hand it to a mid-level engineer before I’d hand them A Philosophy of Software Design, not because it’s better but because it’s smaller, and it gets them asking the question in the title, which most people never ask out loud. The customer with the $0.00 month, for the record, got a very apologetic email and a corrected invoice, and was more gracious about it than I’d have been.