Category Archives: Software Development

Adam Tornhill on Tech Debt’s Multiple Dimensions

In the research for my book on technical debt, I ran into this talk by Adam Tornhill:

Adam has a similar perspective to mine: technical debt is multi-faceted, and the right strategy should address its various dimensions.

One of his examples is combining a code complexity metric with data from your source code repository to define low code health hotspots—areas where code is both complex and frequently changed. To find the hotspots, he built a tool to calculate this metric and visualize it. In the video he shows data from big open-source projects (like Android and .NET core) and pinpoints areas that would benefit from work to pay down debt.

Similarly, in my book, I identify eight dimensions of debt. Complexity is something I consider to be part of Resistance, which is how hard or risky it is to change the code. I would also incorporate low test coverage into resistance, as well as subjective criteria. Adam says that complexity is a good estimate of how many tests you need, which is true, and I give you credit for having the tests. I am mostly concerned by complex code that is undertested.

Like Adam, I believe that bad code only matters if you plan to change it. He believes that the repository history of changes is a good indication of future change, which I agree with, but to a lesser degree. In my book, I recommend that you look at the history and shared this git log one-liner as a starting point:

git log --pretty=format: --name-only --since=3.months | sort | uniq -c | sort -rg | head -10

That line will show you the most edited files. To find the most edited folders, I use this

git log --pretty=format: --name-only --since=3.months | sed -e 's/^/\//' -e 's/[^\/]*$//'  | sort|uniq -c|sort -rg|head -10

This data contributes to a dimension I call volatility. It’s meant to be forward looking, so I would mostly base it on your near future roadmap. However, it is probably true that it is correlated with the recent past. In my case, this data is misleading because I just did a reorganization of my code to pull out a shared library to share between the web and mobile versions of my app. But, knowing this, I could modify the time period or perhaps check various time periods to see if there’s some stable pattern.

Generally, my opinions about tech debt and prioritization are very aligned with what’s in this video, especially the multi-faceted approach.

Marbleized Code Fat?

I go back and forth on whether the name “Tech Debt” is the most useful term. In my book, I decided I can’t fight the term, so I use it, but in my opening paragraphs I make an argument that the problem we call tech debt isn’t like other debt.

The most common way I’ve seen tech debt is that it’s just everywhere. It’s not limited to a specific old module, it pervades the codebase like marbleized fat in a good steak, but not as delicious.

My Guest Article on Tech Debt for the Pragmatic Engineer

I started writing a book on Tech Debt in January and I posted a few chapters in the Spring. A few months later, Gergely Orosz from the Pragmatic Engineer reached out to ask me to write a guest post for The Pragmatic Engineer newsletter—it just went up today.

https://newsletter.pragmaticengineer.com/p/paying-down-tech-debt

If you want updates about the book, sign up here: Pay down tech debt to go faster right now

There are a lot of posts on this site about tech debt. Here are a few

Policies that reduce dependencies

Over time I have become skeptical of most dependencies. I wrote in Third-party Dependencies are Inherently Technical Debt:

[…] any third-party dependency is technical debt. Third-party? Here’s how I am defining it for the purposes of this article. You are the first party, the platform you are writing on (e.g. iOS, Android, React, NodeJS) is the second party. Everyone else is third party.

[Third-party dependencies are debt because] you need to constantly update them, […] they introduce breaking changes, […] they become unsupported, […] your platform adds their own incompatible implementation, [… and] they don’t update on the same schedule as the [platform].

To that end, I like policies that tend to reduce the number of dependencies you have. Here are a couple that I have seen work.

  1. Become a committer on any third-party dependency you take on. To be fair, you kind of owe that to the project.
  2. Donate to any third-party dependency you take on where you won’t become a committer.
  3. Fork the dependency and bring in updates carefully.

Seems like extra work, right? The extra work is why they work.

PM-led vs. Engineering-led Time

At Trello, on the mobile team, we had a formal way of allocating engineering time to either working on PM-led or Engineering-led initiatives.

A PM-led initiative was something that ultimately rolled up to a OKR that was well-understood by the business. The requirements came from the PM and the PM could assess acceptability. An Engineering-led initiative was something like tech debt, changing our dependency package manager, improving CI build times or anything where the requirements came from the team itself and the PM didn’t know or care about it (and neither did anyone outside the team).

So, let’s say we decided the split was 60% on product manager led initiatives and 40% on what we called engineering-led. The split is arbitrary—the EM and PM agreed on what was appropriate for their team and set it for the year.

Then, any individual engineer at any one time (for a couple of sprints) was on either a PM-led project or an Engineering-led project. We did not want a single engineer to be split across PM/Eng-led work. This made it easy to know we were allocating correctly (without having to track time on individual stories or cases).

So, if it was 60/40 and we had 10 engineers, 6 would be on PM-led, and 4 would be on engineering-led at any one time, but it rotated.

This just needed to be mostly right over the course of a year—on any specific month it could be a little off if over the long-term, it matched.  For example, If the PM didn’t have work ready, we could do more engineering-led work temporarily.

Dropping if-bombs

On June 25, 2012, I tweeted:

I believe I just coined a new programming term: if-bomb: adding a bunch of heinous if’s for a special case “Dropped an if-bomb on my code”

To be clear, this is a well-known anti-pattern, covered in Patterns of Enterprise Application Architecture by Martin Fowler. I started calling them “if-bombs” to discourage their use. One remedy is the Special Case pattern, but there are others. A special case of the Special Case pattern is the Null Object pattern, which is used when the special case handles null references.

Build a Progress Bar for Your Work

When I begin a coding session, I start by taking the task I need to do and breaking it down in fine detail. For example I am working on personal productivity system, which has a “Project” concept. In my first pass, Projects just had a name field. I was just working on getting the relations right. Now, I want to flesh it out a bit. I have a Jira issue with the title: Add “color”, “startDate”, and “endDate” fields to Projects.

Here’s how I break that down:

  1. Add fields to DB entity
  2. Add fields to DB createProject, updateProject
  3. Test DB
  4. Add fields to server GQL createProject, updateProject
  5. Add fields to client GQL createProject, updateProject
  6. Add fields to client GQL project query
  7. Add fields to client model and redux initialize
  8. Add fields to redux createProject, updateProject
  9. Add fields to API/Optimistic updateProject, createProject
  10. Test API/optimistic update/redux
  11. Add a color picker for setting color
  12. Add UI to create project dialog
  13. Add UI to update project dialog
  14. Test UI

I could get more granular, but this is about the level I like. I put them in my task manager to keep me on track and to make sure I’ve thought the problem through. This will roughly be the order I do it and the commits I make.

It guides the session and keeps me on track. If I don’t finish, I just move the incomplete tasks to the next day, which lets me preserve some of the momentum from the previous one. Also see: Green, Refactor, Red, where I end the session with a failing test for the next task I want to do.

Paying off Tech Debt Makes You Happy

Chapter 1 of Joel Spolsky’s User Interface Design for Programmers is titled “Controlling Your Environment Makes You Happy” and contains a story of Joel’s time working in a bakery which concludes:

The more you feel that you can control your environment, and that the things you do are actually working, the happier you are.

This is why I Use My First Commit to Fix CRAP. It takes 5-10 minutes and lets me exert some control on my environment. I start each day with a small success. If I feel frustrated later in the day, I just do it again.

Passive Voice Commit Messages

I saw a suggestion to use Subject-First Commit Messages to make it easier to scan the log. I switched over to this about two weeks ago and like it.

When you write commit messages this way, they tend to result in passive voice sentences like “Project cleared from project prompt dialog when closed” and “Title added to date prompts”. Many style books suggest that you not use the passive voice, which is then repeated as a rule. But, the passive voice is useful, and is often used by the best writers (go check your favorite). Even those style books (like Strunk and White) give exceptions.

When writing a sentence, it’s important to control the subject. In most commit messages, the implicit subject is the programmer. For example, in “Added title to date prompts”, the subject “I” is dropped. Since we know that the programmer is making the commits, we don’t need to constantly repeat it. It’s better to pick the most important noun in the sentence and make that the subject, and to do that (in English) you have to use the passive voice.

I talked about this in Write While True Episode 37: The Passive Voice Was Used. If you want to see a thorough take-down of anti-Passive Voice zealots, watch Larry McEnerney analyses the Gettysburg Address, which I discuss in the podcast episode.