Tidy First? by Kent Beck

Tidy First? by Kent Beck is a light, easy read about if, when, how, and why to “tidy up” your code.

The “?” in the title is not a typo. Tidy First? is not a how-to: it starts with a question it does not intend to answer. Beck provides a framework built from decades of experience in the craft that you can apply to answering that question for yourself and your own unique situation.

Make no mistake: this is not a book about refactoring. Beck and Martin Fowler have that covered in another book. Tidy First? is a small book about small changes. Refactoring and tidying have a lot of overlap, but Beck defines a tidying as the “cute, fuzzy little refactorings that nobody could possibly hate on.” Tidy First? is about making small structural changes that make behavioral changes easier, and how to make intelligent decisions about when you take time to do it.

The book is divided in three parts: Tidyings, Managing, and Theory.

Tidyings

Tidyings are small structural changes that make behavioral changes (features) easier later. Tidy First? defines and provides examples for 15 different types of tidyings. Some examples:

  • Deleting dead code
  • Adding comments to explain a complicated block of code
  • Deleting explainer comments after you’ve tidied up a block of code, making the comment redundant
  • Moving guard clauses to the top of a function to avoid deep nesting later
  • Normalizing symmetries. In other words: pick a way of doing things, and then do it that way consistently

Kent’s tidyings are pretty uncontroversial. The controversy around tidyings exists because software is written by humans, used by humans, and represents financial value and financial risk to humans too.

Managing

The first section of the book addressed how to tidy up. Managing addresses if and when to tidy up.

One could be forgiven for thinking that questions like “should I tidy up?” and “should I tidy up now or later?” are at best philosophical distractions or at worst actively harmful. Should we as experienced, responsible professionals, even entertain the option of not making our code clearer and more resilient to future change?

It turns out that in practice the reality of software being in part a social construct starts chucking rocks at that glass house we were living in. Other people review our code, and may have opinions about whether one pull request should include both structural and behavioral changes. Your team likely has value they are expected to deliver by a certain point, and so you can only spend so much time on the tidying treadmill before you hop off and do feature work.

Beck isn’t so bold as to trade in absolutes. He’s spent a lifetime in the trenches, holding his nose and making trade-offs like the rest of us. Tidy Up? doesn’t give us answers. It gives us strategies for reaching sound conclusions, in our own unique situations. It helps us make decisions about:

  • When to tidy: before behavior changes, after behavioral changes, later, or never
  • When to stop tidying
  • Whether or not to combine structural changes and behavioral changes (put tidying and feature enhancements in the same Pull Request)
  • When and how to batch

Beck’s advice gives you a list of questions to ask yourself to build confidence that, whether you decide to tidy now, later, or not at all, you’re making the right decision for the right reasons. It gives you a framework from which you can work with other well-meaning developers to resolve disagreements about if and when to tidy, and how to organize the work.

Theory

Tidyings helps you do your job as an individual contributor. It tells you how to tidy up. Managing frames tidying as something you to as part of a larger team working towards a shared vision of success and technical excellence. It helps the collective you make decisions on if and when to tidy up.

At this point we haven’t answered a really important question: why tidy up?

And as it turns out, “why tidy up?” is a question you should be prepared to answer. If you aren’t prepared to answer why, it’s easy for the Code People to position themselves at odds with the Money People, simply because they didn’t think they should have to explain why tidying actually supports revenue.

As Kent Beck says in the book,

“When geeky imperatives clash with money imperatives, money wins. Eventually.”

Kent Beck, Tidy First?

Beck tries to explain his position using financial markets and options trading as a metaphor. The metaphor flew straight over my thick skull. Fortunately I think I understand his direct arguments, because I’m an engineering manager and I’m constantly listening to the concerns of the Coders and the Money People, and helping all parties find balance.

His base points were:

  • Deliver value early. Delivering working code now is worth more than delivering tidy code later. You can profit off the delivered feature. You can collect direct feedback on how to make it better. So, sometimes tidying later is the pragmatic thing to do.
  • Create optionality. Tidying your code promotes, future change which provides options to do more, faster, in the future. Tidying is necessary to keeping the code ready to accept new features and deliver future value. It supports the money decisions.
  • Practice balance. Go through the mental exercise of making decisions about if and when to tidy up. Tidying is low-risk and low-effort. Doing the exercise will help prepare you for higher-risk, higher-effort decisions and disagreements later.
  • Make reversible changes. When possible, make changes that are easy to reserve. This makes experimentation lower-risk.
  • Coupling drives the cost of software. Coupling means two units of code must change together. Reduce coupling to reduce the cost of change. When tidying, consider reducing coupling. Be on the lookout for tidyings that will turn into rabbit holes that last hours, days or weeks, due to cascading coupling. Maybe tidy that up “after.”

Summary

Tidy First? is a book for anyone creating software but especially for those creating software with a team and organization behind it. The tidyings themselves are, in some cases, so obvious as to hardly need a paragraph, let alone a chapter. It is not a how-to, but rather a “how-to think” kind of a book. It provides a way to navigate the choices, conversations, and decisions we all run into while developing software. It helps us understand the “money people” and helps us form arguments that can help the “money people” understand us.

My understanding is that Tidy First? is the first short book in a longer series. I’m excited to see what Kent comes up with next.

Technical Debt for the Nontechnical

If you hang out with programmers long enough, you’re bound to hear one of them vent about technical debt. What is technical debt? Why is it so bad? And more importantly, why should you care?

Let’s begin with that classic cliché we all know and love, the dictionary definition.

Debt: a state of being under obligation to pay or repay someone or something in return for something received.

Merriam-Webster Dictionary

Technical Debt is created when we accept technical trade-offs for a short-term advantage with long-term consequences. Technical debt is a bargain we strike with our future selves. If we don’t want to suffer the consequences, it must be paid back.

I’m Not a Programmer. Why Should I Care?

“I’m not a programmer. I’m in sales, marketing, customer service, the C-suite, or somewhere else. Why should I care about your technical debt techno-babble?”

Why do we write software, and who do we write it for?

For most of us the cold, capitalist answer is we write software to make money for our organization. But that’s an outcome of doing the job well, not the reason we do it. We write software because we’ve identified a problem we can solve for customers. We code to solve problems, delight our users, and keep them coming back. If we do that, the money happens.

You have a stake in all of that too. Other roles in the organization have customer and market insights critical to the software team and the product’s success. If sales, marketing, and the rest of the organization are rowing in different directions, the right customers won’t know we solved their problem, and software won’t succeed. We’re all in this together.

So if we’re not careful, good intentions on the part of the rest of the organization to boost revenue, get a product or feature to market faster, or close a sale can create perverse incentives to take on technical debt.

Even worse: if a nontechnical person asks the technical team to sacrifice “doing it right” in order to “do it cheap” or “do it quick,” if they get what they want and don’t see a consequence, they’re going to keep asking for it.

This works, until it doesn’t.

And so, anyone that can influence software’s direction can create the conditions where technical debt can flourish and lead to failure. That’s why you should care about technical debt.

The consequences of technical debt. "goto" by XKCD

Examples of Technical Debt

Technical debt can be created all sorts of ways. Below are a few examples of what this looks like in practice:

  • Putting sloppy code in production. The code “works” but is poorly written. The customer may get the feature faster but the choice slows down future development because the work is hard to understand, buggy, hard to change, brittle, or inflexible.
  • Progress by Copy-and-Paste. You deliver new features by copy-pasting old ones. In the short-term this may deliver immediate value. But you’ve multiplied the complexity and time required for future changes, enhancements, and bug fixes.
  • Putting inefficient code in production. You know your code hogs resources. The customer may get your changes faster, but their experience suffer from poor performance, and the software may be significantly more expensive to host.
  • Putting code with known security vulnerabilities in production. You know your code has potential security risks and choose to release it anyway. The customer may get the feature faster, but you’ve introduced code that puts all customers, and your organization’s credibility, at risk.
  • Skipping Documentation. You don’t document your code in order to release it faster. In the future, developers have to stop and build an understanding of the “old code” before they can make any changes. Progress slows going forward. If you skip public-facing documentation, you may fail to build institutional and user-level knowledge of changes, missing the chance to educate and advocate for your own product.
  • Skipping Automated Testing. The code “works”… so you think. But you skipped automated testing to release faster. You miss bugs. You introduce regressions in features that used to work before. You eventually find yourself buried in toil: work that is pure overhead, devoid of long-term value, because you chose to skip QA.
  • Building in Toil. The software works but processes that could be automated are built on human intervention. This may help the product or feature release faster. But it introduces friction into the user’s experience of the product and results in a product that can only scale by adding more humans. (And those humans usually require salaries.)

These are examples of technical debt. And to reiterate: some debt is okay, so long as you pay it back.

What Are the Consequences of Technical Debt?

In the financial world, failing to pay your debts has consequences. The bank starts taking stuff, and eventually life starts sounding like a country tune.

A chart illustrating that technical debt causes the cost of change to increase over time.

In software, failing to pay your debts has consequences too. It results in a high Cost of Change. In other words, a product with high technical debt will be harder, slower, and more expensive to build on than the same product with less technical debt. Think of it like inflation: the same dollar buys less new feature development today than it did yesterday.

Here are some examples of what it looks like when software is over-leveraged on technical debt.

  • Too Much Toil. Developers are spending the majority of time engaged in toil: work that is pure overhead and has no long-term value to the organization. But without it, the system eventually grinds to a halt. 
  • Stagnation. If you’ve spent enough time expecting “fast” solutions over “good” solutions, this eventually catches up with you. Your developers can’t get to new feature development because they are buried in fixing bugs.
  • Inefficiency. Adding a programmer to the team doesn’t result in “1 programmer worth of value to the organization.” You’ve just added an additional rower to a rowboat stuck in peanut butter, instead of water.
  • Turnover. You can’t keep talented developers because they want to solve interesting problems, not make a career of cleaning someone else’s code.
  • Declaring Technical Bankruptcy. Your software may become so cumbersome to maintain that the only sane path forward feels like starting from scratch (which has it’s own set of problems).

Summary

So sum it up all up: technical debt is created when trades-offs are made to accept worse code in exchange for short-term gains. This can be strategically useful, but only if you honor the promise to pay it back.

Anyone that can influence software decisions can create the conditions for technical debt. We’re all in this together, and should default to promoting mature, sustainable engineering practices over shortcuts taken for short term gains.

Over-leveraging on technical debt has very real consequences that may not surface right away. If you’re progress stagnates because your engineering resources are stuck fixing problems caused by a history of ignoring mature, sustainable engineering practices, you’re probably over-leveraged on technical debt.

But now you know what technical debt is, and what it looks like in practice. You also know how to spot evidence that your organization has taken on too much in the past. Armed with this information, you’ve got the opportunity to help your organization make smarter, more sustainable decisions to reduce technical debt, and avoid creating more in the future.