Feb 6, 2025 Pitching the Refactor Language is the liquid that we're all dissolved in. Great for solving problems, after it creates a problem.

Truman Shuck

I am a literalist at heart. I don't mean that I dislike or avoid metaphor, but when it comes to methods, modules, and projects I tend to stick to "ah, does exactly what it says on the tin" territory. This works pretty well with code written for initiatives that are self-evidently valuable. Ah, the def send_email! method in module RetargetingCampaign which retargets folks who have dropped out of the funnel to give them another opportunity to give us money. Makes sense!

Things get a little trickier with engineering-led initiatives: Upgrade Rails, Refactor User Services, Clean up Auth. All of these become necessary to do at some point when aspects of the system start to cause a disproportionate number of issues. Edge cases are harder to spot in disorganized code, so risk increases. Legacy features need to be untangled before new ones are introduced, so velocity decreases. Engineers don't enjoy working with bad tools, so finding and keeping folks around becomes more difficult.

This is not a post about the technical debt metaphor, or a discussion of the distinction between "good," "bad," or "fine to leave alone for now" indebtedness. Eventually some extra attention has to be given to the care and feeding of a system. This is a post about the importance of language. It's about communicating the need to pause work on the thing that the non-technical leadership knows is good for the business — for the arcane and incomprehensible work of keeping a technical system well organized ("I'm sorry, did you say that we need to stop for a week to upgrade the 'gem'... 'nokogiri?' because of an issue with 'native extensions' for our 'ubuntu image???'") which is, of course, also good for the business.

Explaining Why

Technical debt is, itself, a metaphor constructed to help non-technical folks understand the responsibilities inherent in maintaining a system. But beyond the vague idea that most debts have to be paid eventually, this metaphor is not specific enough to be motivating. Prefixing a project as "Technical Debt: add test coverage" does very little to communicate the underlying value of the work. "This is a debt," the director of product says, "but we should defer payment while we smooth out the bumps that are causing drop-off in the funnel."

This is not an incorrect opinion, but a potentially under-informed one. "Good" code is not inherently valuable, but work that makes code better so that it can better serve people is. Adding test coverage is itself a worthless activity. "Reduce the likelihood of errors in the sign-up funnel" provides a clear indication of why the work is important to do, now.

When we can re-frame cleanup, refactoring, or other "tech debt" activities in terms of the value that they provide, we clearly communicate why they are worth doing in the first place. This process also serves to reinforce to ourselves that they are worth doing in the first place, too. And "value" does not always have to directly reference the end-user: "Untangle the Pit of Despair (User Model) which causes 25% of new hires to quit in a fit of madness" is also a useful, if hyperbolically verbose, project.

Aid Future Investment

Growth begets complication, and as a project grows there's always some specific decision that makes life especially difficult for continued development. It's choosing to hand-roll the Slack integration because it's just one simple message instead of investing in learning and configuring the whole library.

Sometimes it's better to do what's quick and easy, now. But later, when half of the internal tools are based on Slack bots, that home-grown integration becomes a tangled thicket to work within. Every additional feature requires more attention, testing, review. Every additional feature itself adds to the complication.

When maintenance is tied directly into recognized future value, it's even easier to communicate its importance. Yes, we can add a new internal Slack robot that helps our customer success team find answers to frequently asked questions — but we're going to include work to replace our custom integration with the off-the-shelf version. Yes, this will delay CSBot's roll-out a bit, but it will greatly speed up the next three chat features we saw on the roadmap.

Communicating is difficult, and doing it well requires a fair amount of empathy: understanding what the other person knows, where their priorities lie, how they'll interpret the one-line epic title that represents weeks of effort for the company. And look, I still don't really understand what EBITDA means, or how to weigh the ingredients in the "marketing mix," when the business folks describe what's important to them.

So taking time to frame necessary technical maintenance in a way that expresses its value — in addition to clarifying that value for myself — is one small way to help my coworkers. And to avoid a long conversation about how important it is, actually, to upgrade Rails because dependency management is starting to become a nightmare . And don't get me started about those native gem extensions.

Do you have strategies that help communicating with other folks at your company? Do they involve typing in all caps? We'd love to hear about them, below.

Thanks for your time and attention.

Leave a comment

Thoughts for our thoughts

We hope you find our writing useful and, perhaps, that it gives you something to think about. We read everything we receive and we'd love to hear from you.