You should lint your TODOs
I think you should decide on what formats you want to allow for your TODOs and extend your linter to make sure your TODOs conform to those formats. It makes TODOs searchable and scriptable rather than just being comments in your codebase.
Every team is going to have their own taxonomy of TODOs, but I like to break TODOs into four categories:
1. Tasks that can't be completed yet: // TODO $github_username $date
I often run into tasks that I can't complete yet: deprecating a route that some clients still depend on, bumping a dependency after a github issue is resolved, updating a component to pass a new query parameter once it's available, turning a feature back on after an attack is over, or going back to the main version of a package after a patch has landed.
These TODOs are all time-dependent and have an owner, and if we enforce those two facts in a consistent format like // TODO $github_username $date
, we can build useful tooling! Alerting a person or team when it's time to check on a task that they deferred makes life simpler for everyone. Without a reminder like that, it's far too easy to add a well-intentioned task that you forget after a month, and it's ergonomic to be able to add the task to the codebase right next to where the change should be.
(If it's helpful, here's a gist with a JS eslint plugin to enforce that TODOs match this format)
2. Dangerous temporary code: // DEV_ONLY
When I'm debugging something locally, I'll regularly make dangerous-to-push changes like an if (true)
, an early return, or commenting out blocks of code. If you have a large change, it can be pretty easy to inadvertently include something dangerous.
I like having a guard in place that ensures that I can't even push that dangerous code. When I tag something with // DEV_ONLY
, I have git hooks that will look for that exact string and fail the push, and I add a search for that string to my lint stage: if ! git grep DEV_ONLY -- . ':!git_hooks/*'; then exit 1; fi
.[1]
3. Blockers to calling a project done: // BLOCKER $feature_name
When working on a project, I like to have notes in the codebase that let me track the things I need to do to call the feature fully done. In theory, that's exactly what a TODO comment is! But because most codebases have a ton of TODOs, searching for TODO
isn't a useful way to identify the project-specific blockers that I've added. Right now, I'm experimenting with // BLOCKER $feature_name
as my marker, but I could see arguments for // BLOCKER $github_username $feature_name
or some other format.
4. Refactoring TODOs: // TODO make me better?
In some ways, I think refactoring TODOs are the canonical TODO, but I don't think they're useful. In my experience, they're often brief out-of-date messages that future readers will struggle to understand.
I think these "TODOs" should instead be regular comments that describe why something in confusing and why a refactor might make sense based on the knowledge that you have at the time. The information I'm most interested in isn't the TODO action item that was left in the codebase; it's the thoughts of the person who wrote the action item about why that particular refactor or change would be a good idea. It might not even be a good idea anymore!
If you do want to track future spots to refactor, I'd argue that you should still come up with a format that makes it easy to identify these points: // TODO FUTURE_REFACTOR
would let you search for only TODOs that are about future refactors, and it would let you see whether the number of pending refactors are going up or down over time.
(I do like Sophie Alpert's TODOs aren't for doing take on this, but I think calling it a TODO is confusing.)
/* TODO: write a conclusion */
Your taxonomy of TODOs might be different than mine! I don't want to convince you to use my categories. Instead, I want to convince you that deciding on and enforcing your TODO categories can make your TODO comments more useful and manageable. Using different strings and formats for deferred tasks, unmergeable code changes, project blocks, and notes about future refactors makes it easy to find those comments in your codebase and build useful tooling.
There's a nice GitHub Action plugin that does something pretty similar to this, but I'm forgetting the name and my search-fu is failing me.
// DEV_ONLY: don't deploy this blog post until you've tracked down the github action...
:-p ↩︎