179 comments

[ 2.3 ms ] story [ 300 ms ] thread
Ok but my tooling defaults recognize TODO and I have many pending deaths on other hills of higher precedence.
Exactly. Plus if I want to find things to fix in my code, searching for TODO is much easier than searching for each of a dozen or so other strings.
And I can add additional information next to the todo:

  // todo: todo
This is my real gripe. Let's not pretend "TODO" is the end of the comment.
Nobody did?

The article's goal is clearly to provide a quick categorisation of the TODO, rather than require reading the description to discover it: if I'm trying to debug something and reach a bit of code with a bunch of TODOs it's not going to help me much, if I see a FIXME or BUG I'm going to be a lot more interested.

Sometimes the TODO us sufficient through it context (e.g. a docstring empty but for a TODO stanza is obviously a missing doc), but often it's not and is the documentary equivalent of a goto.

The article is clearly to break our tools and search capacity. If you want to add categorization, do add, instead of replacing, like the GP does.
> The article is clearly to break our tools and search capacity.

Get yourself tools which are not hot garbage? All the ones I use let you customise markers however you want.

> All the ones I use let you customise markers however you want

Customisation requires everyone who ever works on that codebase to also do the customization. Defaults are important

> Customisation requires everyone who ever works on that codebase to also do the customization.

And they can go on the pile of all the others customisations necessary when you don't mandate all the tooling by fiat.

> Defaults are important

Defaults are a tool, when they hinder improvement you discard them.

As long as the second todo is also standardized (TODO: FIXME), so it will play nicely with grep.
As mentioned in the post, if you are looking for things to fix, you should be looking in an issue tracker. I was trained to put the issue number next to the TODO. Furthermore, we tag the issues so that we can easily identify simpler issues that can help spin up new team members.
I like that method. Where there is a TODO referencing the ticket number. Makes it easier to find the ticket, or where in the code the ticket references. And helps to ensure there actually is a ticket so it isn't forgotten about down the line.
++ to putting the issue number next to the TODO
Before I had tooling nudging me along, I used +++ as a strong visual cue. Yes, as in +++ATH0.
I pepper my code with FIXMEs while it's under development and I'm working on just getting the happy paths to run. Then I go back and fill in error handling and special corner cases that I skipped. That isn't a scenario where you can use issues.
I think todos and tickets have separate use cases. I use todos as short term work trackers. I put them in as I'm writing new code, then usually complete them before I check in, certainly before I merge my branch. Sometimes they slip past me and get into the main repo, but that's a better outcome than just forgetting about it entirely and I don't have to pay the cost of writing up and managing tickets for every loose end. I open tickets for things which will need to be done as a separate work item at a later time. I don't tend to put in a todo with the ticket number because usually something on that scale often doesn't have a specific place where it belongs.
I agree with this a lot. Issue ID(s) go into every commit in my shop. I'm going to think about how or if issue ID(s) should go into TODOs as well. That might be an upgrade to my existing process for preparing a work surface before upgrade.

Because of default highlighting support, I started using TODO. The most valuable part is the colored flag my tools generate to attract attention to code that needs it.

then put the tasks in your project management tool so you can prioritize them. How do you prioritize your todos in your code base? O(n) search?
My project management tool is todo.txt

As far as the hundreds of #todo throughout my code, they are prioritized based on when I'm using the program and decide that I've had enough of a particular issue.

If I sit down to work and I can't think of anything to start with, I do a global search for #todo and pick a random one to work on.

> My project management tool is todo.txt

THANK you. I only need a few concurrences to keep forging ahead with tools that work, but I do need a few.

So, this is why we use TODO as well, even though Godoc supports BUG natively and exports it into documentation. Nothing needs to change, everyone is on the same page. But each TODO is accompanied with a ticket, not just some loose "TODO fixme at some random time I guess?"
The IntelliJ IDEs recognize TODO and FIXME comments, highlight them differently, and can show a list with all items. You can also configure additional patterns that should be recognized (although I never did that): https://www.jetbrains.com/help/idea/using-todo.html
Yeah I use the TODO and FIXME with IntelliJ. I don't think it would be a good idea to start using other conventions that would force other developers to set up their IDE to support the same custom patterns as me, though, even though it's nice that IntelliJ supports the option. I'd rather just add more context in the comment.
The cultural fragmentation of TODO tags is worse than their inaccuracy.

I use the classic TODO, BUGBUG and my own (the last one is usually 'xxx' for brevity, and never in checked in to a public branch). That's it. Life is too short for needless complication.

The PM over there in the corner has just invented eight levels of TODO severity, and will soon multiply the truth by putting them in a database (somewhere), start a set of meetings to track them, and is already talking to tool vendors about building an Enterprise TODO Framework. Dry gulch that PM before you lose your sanity.

>pending deaths on other hills of higher precedence

This is the most obtuse way of expressing a concept. I like it very much.

Yeah? Well, this is why Jedis do not get their light sabers from Acme Megacorp.
My pet peeve is `XXX:`, which I see with distressing regularity in the codebase I work in. It’s non-specific, but vaguely ominous. Is it a TODO? A warning? A bug? An incantation to ward off evil spirits? Tell me!
I use it occasionally as a heads-up about tricky functionality, or to point out something that should be read by future developers, so yes, like a warning. It's similar to `NOTE`, but more important. There's nothing to be done, so `TODO` wouldn't make sense.
Why not `IMPORTANT:`?

I haven't seen `XXX:` anywhere, but it's immediately disconcerting as the icon is meaningless. If I have to reach-out to you to discover the meaning of some word you use, it's a bad word.

> Why not `IMPORTANT:`?

Like others mentioned, it's not as an established convention as `XXX`. And it's much shorter and quicker to type, particularly convenient when you just want to rant about something, which is the usual use case for `XXX`. ;)

At the end of the day, these labels are meaningless unless the entire team is following the same conventions. So using whatever your team agrees with using is the most important thing.

Does it really need to be something more important than NOTE? If you are working on the code you should be reading that NOTE anyways, so why not use a word with more specific meaning? Or even just IMPORTANT. Before this thread I would have never known what XXX meant, having never seen it before.

I suppose if its defined somewhere as a standard for everyone working on the code it may make sense. Just doesn't feel very intuitive to me.

I use XXX to mean "this code is ugly and not the intended design, but I don't see a great way to fix it". If I did, I would leave a TODO with steps. The XXX is a formalized "ugh", a note for anyone reading my code later to glean that I was unhappy. Often times the hardest thing about reading a codebase is rebuilding that mental model on how the code is ideally supposed to fit together at the high level, and an XXX explicitly marks a conflict between the code itself and that vision, and explains why.
I don't know if this is the exact incantation, but some IDE extensions will recognise some special comment annotations. TODO/FIXME support is in pretty much every IDE, but there are some special codes that some IDEs will recognise.

Visual Studio (not necessarily Code) will recognise TODO, HACK, NOTE and UNDONE, for example.

Java conventions mention XXX: https://www.oracle.com/java/technologies/javase/codeconventi...

    10.5.4 Special Comments
    
    Use XXX in a comment to flag something that is bogus but works. Use FIXME to flag something that is bogus and broken.

Using XXX in comments goes back to 1978, according to https://www.snellman.net/blog/archive/2017-04-17-xxx-fixme/

I'm not a huge fan of XXX as a warning, there are more descriptive names in caps available that your IDE will probably even autocomplete after using them for a while. However, the practice is common enough that it's just a General Programmer Thing, kind of like how some people prefer /* */ over // because they're just more used to it.

Maybe it's used to mark NSFW code (which your boss shouldn't see)?
We had a recommendation in one of my previous companies to replace all TODO's with XXX. Their rationale was that the TODO tags sounded like an unfinished product to the customers. So they wanted to replace all those TODO labels with XXX so that the customers wouldn't find them when grepping. Even if they find a XXX label while reading the source they wouldn't have any clue as to what it is.
"XXX:" is short for "BULLSHIT:" or other profanity to me, generally imply that life sucks.

usually to indicate some horrible hack which is required because we can't quite blow up the codebase to fix it all, and i'm not thinking of a simpler solution today.

it also exists to point out that even though the code looks maybe mindlessly overcomplicated that someone shouldn't just come in and refactor it to make it simpler because it'll blow up some edge condition if you do that. They're the long-term nuclear waste warning messages of a codebase.

I use it with parenthesized clarification. So `# XXX(dependency-version): Reason why we can't have nice things` is code that can be updated when `dependency` of at least `version` can be assumed. The clarification is there so that if the reason itself goes away, we can just remove the conditional. Repeat for things like `cmake-3.23`, `macos-10.14`, `python-3.8` and so on. It's just an easily greppable string and Vim highlights it differently.
No I won't. TODO is much easier to remember than DOCME or TESTME.
I use TODOs liberally while I'm working on a feature branch. When I've figured out a partial solution to the problem at hand, I'll implement that and leave descriptive TODOs wherever necessary. My IDE will warn me about them if I skip them before pushing and simple notImplemented()s will go unnoticed.

Sometimes I leave a TODO because a feature/fix must land before a certain date and I don't have the extra time to optimise the code before that. Customers prefer a slow feature over a nonexistent feature. Known bugs can be annotated with a FIXME and an issue number so that nobody will waste time on that part of the code if the bug isn't important enough to be fixed in the current sprint.

That said, "TODO: implement" should never ever reach merge requests or code review. Suboptimal implementations may be acceptable, but missing implementations are just bugs or incomplete code.

Broke it down to 4 annotations: DEPRECATED:, FIXME:, INFO:, TODO:
How about stop telling people what TODO. Especially when the complainer can't even comprehend that TODO can be specialized.
(unless you’re spanish)
I use them for when I'm working on code but someone needs me to switch to something else. It's a great way to improve context switching. Otherwise I come back to the code and go, cool where the heck did I leave off.
This post reminds me of my new book, titled "You Aren't The Boss Of Me And You Don't Know Me: Stop Telling People What They Need To Do From Your Blog"
(comment deleted)
At some point convention at Google on many teams I was on switched from:

TODO(username): blah blah

to almost-mandatory:

TOOD(bug#): blah blah.

Gonna write a TODO? Make a ticket for it, and follow up

I've really liked using a template that looks like this:

    // TODO ${username} $[date} (ISSUE) - message
Having a who and a when is very useful for quickly determining what it's about.

The username is helpful for myself for quickly finding my own TODOs, the date is useful for others, as if the issue is so small nobody has bothered fixing it for years, then odds are it's probably not ever going to get fixed and then the TODO can probably be removed.

been using this approach for a while. it also comes up in PRs to encourage either fixing the issue now, realizing it doesn't need the TODO, or saving it for later. and +1 on searchability when searching ISSUE-XXX and seeing all relevant comments. Would make for a good tool
I like the concept. IntelliJ IDEs (which I primarily use) recognize both TODO and FIXME by default, and can be configured to recognize other values.

Admittedly, I probably won’t adopt these new values since I tend to attach a Jira ticket and a few sentences to many of my TODOs; however, I can see how the concept would help some teams/individuals who tend to be less verbose with their comments.

IMO, I only use three tags: DREAM, FIXME, and HACKS. The whole point is to write less code and better establish when to revisit things.

- DREAM tags let me focus on getting things shipped and avoid over optimizing/generalizing things that won't provide immediate value. When working in a professional context, they are always accompanied by a ticket. This adds a nice binding for whoever comes next to pick up the task.

- FIXME is also used to help maintain focus, but with the rule that no code ever gets merged with this tag still in place. For personal projects my branches tend to be quite large, so I'm comfortable accumulating some small number of these.

- HACKS calls out unintuitive behavior: breaks in abstraction layers, worst-practices that have better implementations than best-practices, or anything that smells "clever".

Everything else is just comments that future me/team can look back on and say "he must have been drunk when he wrote this, but thanks to these comments I can clearly understand the context and at least what was intended."

Another reason for a system like yours is TODO is just another backlog but one that no one tracks and grows stale.

I much prefer either

- TODOs are resolved before merge (your FIXME)

- TODOs are moved (not copied) to the team backlog (maintaining in both places just gets them out of sync)

- TODOs are converted to documentation explaining the approach (e.g. HACKs)

I may switch to using FIXME for my personal mid development comments. But I do like having the TODOs maintained with a ticket number in the backlog. Such that you can find the relevant code easily, but there is a ticket and its not forgotten. Especially when it relates to weird behavior in a specific section of code. It also lets people know that that section still needs work when they see it while working in the codebase. Maintain the meat of it in the actual ticket for sure. But `TODO: ABC-123 - brief description` shouldn't really get out of sync. At least hasn't so far for projects I have worked on.
This is absolutely my second system, and one often preferred over my ... um... preferred system :D. In other words, I have my personal bias, but this approach is far easier to scale with a team over time.

I still tend to keep the "HACKS" thing though, simply because they localize the documentation right where you need to be aware of it.

4th option:

- Create ticket in team backlog and add ticket number to TODO comment (and have CI pipeline check that ticket number is valid)

You need to check both that its valid and that its still open. Many times I've seen TODOs with issues in code where the issue was closed. Since nothing gates the Issues being closed, you've now broken CI by closing them.

Say you do get past that hurdle, you've added friction to the process of managing the backlog because the code now needs to be updated when Issues are rejected.

The sad part? With almost 10 years on a 20-30 year old code base with many millions of lines of code that are littered with TODOs, I don't think the presence of a TODO was ever helpful when we decided to actually fix an issue.

I've been tempted to put issues in the repo, which would solve this problem (and create others).
> The sad part? With almost 10 years on a 20-30 year old code base with many millions of lines of code that are littered with TODOs, I don't think the presence of a TODO was ever helpful when we decided to actually fix an issue.

Makes perfect sense. TODOs are comment, meaning they're as reliable as comments, meaning they often aren't (and the more time passes and code churns around them the less they are).

Totally agree. I've found that adding a timeline to _remove_ TODOs/DREAMS (whatever the team choice is) from code as a CI check is very applicable -- what you thought might be good at some point in the past may (and likely is) not applicable later down the road!

Clean the code, comment actualities later, etc. -- it helps with knowledge share to find ways to make you attend to cleaning things up.

I've done this too (commenting with the ticket # - well, link to ticket), and it's worked quite well for me/us. It's fairly easy to follow the link & check on it, and it can also serve as a tombstone for why a particular issue isn't being addressed.
Something I've built for myself a couple times is the ability to decorate a test with a ticket number so that the test is expected to pass if an environment variable (usually TICKET) is set to that number, and otherwise is expected to fail.

I also sometimes include a stricter version that includes a test for the current behavior, on the theory that someone changing the current behavior might be in a good position to fix the ticket.

> Something I've built for myself a couple times is the ability to decorate a test with a ticket number so that the test is expected to pass if an environment variable (usually TICKET) is set to that number, and otherwise is expected to fail.

I don't understand that use case.

Do you mean that if you set the envvar, the test now becomes "normal" because the assumption is you're trying to fix the ticket, and thus make the test pass?

I guess that makes sense if your workflow is to "clock in" on tickets, to which you can hook env updates?

You have it right, although "clock in" sounds a little formal; I'd probably just say "start work".
> that no one tracks and grows stale

On the contrary; since they are right next to the thing that needs work you always encounter them Just In Time. And you can just delete them really easily if you decide they're truly stale. This may not lend itself to planning or management visibility, but for a small private project I prefer them to the overhead of separate tracking.

> for a small private project I prefer them to the overhead of separate tracking.

For a small private project there's no organisation which doesn't work.

Actually, I'm increasingly finding that because my work on these types of projects happens sporadically, it's easier for me to get stuck not remembering what I did or need to do.

I don't have anything resembling an issue tracker, but I've begun collecting brain dump style notes in either a gist or the Apple notes app.

I'm the same. I fully expect all my side projects to be interrupted / paused for months at a time. This for me this does include a ticketing system, version tracking, rationale documents, wiki etc aren't optional for me.

Some of my side projects have more process around them than my work projects because the side projects will definitely get shelved at some point and resumed much later. Future me is always happier when the process was applied.

> since they are right next to the thing that needs work you always encounter them

That means they become scenery, not something in the foreground. They are lost.

I like the idea of DREAM. I find that there are lots of things I would like to improve, but not worth it at this time. Or even maybe ever. But it doesn't feel 'standard' either. While I am sure a team could set up custom highlights and the like, but it has seemed better to just use the standard ones that get picked up by most tools.

Is the use of HACKS just to highlight the importance of a comment? I tend to just stick those in a regular comment. Or if extra important NOTE at the beginning. For instance I refactored code the other day forgetting why it was the way it was, it didn't work, and then made a NOTE for it so I don't do it again.

The point is to avoid having to search these out. IMO you're playing a losing game if you find yourself doing this.

For "DREAM" there is a ticket for proper tracking. For FIXME, code review prior to merge is sufficient. For HACKS, you really only need to care when you happen to be working in that space.

And yes, HACKS is to highlight the importance of a comment. It also signals an intentional deviation and an opportunity for someone to offer a suggestion on how to improve things.

I love this. I'm going to try using this going forward.

Edit: I just added this into my editor but it's not highlighted by default. I wonder if there's a way to highlight it.

Well then that depends on the editor, but surely it’s possible in whatever you’re using.
TODO: Add highlighting by default.

There, fixed it.

What about a hack, that needs to be fixed, but in reality fixing it is only a dream?
For hacks, I use REVIEW to declare that this code is the way it is but an aspiring soul is welcome to submit a PR that replaces this code with a working version of the "right way to do it". It shifts the burden from the developer who made it work to the developer who would prefer it work some other way which allows the project to make progress.
(comment deleted)
I've had good success using a system with two levels of severity:

- // STOPSHIP: the presence of this string anywhere in the codebase causes a production build to fail.

- // TODO: for everything else.

What about "// TODO !", "// TODO !!", and "// TODO !!!". Where the number of !s indicates the urgency - the more the urgent.
My one tweak would be that in projects in development, the hard rules are less applicable. Sometimes I've found hard-coding some things (e.g. FIXME items) are to make it into production when developing a prototype and testing (< 1.0.0).

Once you're reaching 1.0.0, you know these can no longer be sliding through, and you can support all of this in CI.

Committed @TODO in code is a junk drawer for people who don't like ticket systems. If you are working alone, sure. But in a team, please show your peers some respect and allow them to prioritize/document todos via a ticket system so a product manager can drop it or assign someone else on it. But don't litter the code with a bunch of TODOs.
At our company, we have a rule: when you want to add a TODO you must create an issue in the issue tracker (which is added to the backlog) and place the issue ID after the TODO. This way you have a full context/description what was the intent (is it a bug? is it a feature we abandoned for now? is it a temporary hack?) and since it's in the issue tracker you can do all sorts of things such as sort/group by tag, date, priority etc. It's also easy to find all places in the codebase which need to be touched, by searching for the issue ID.
I try to never merge TODOs in master. I do use these in feature branches, but if it was not important enough to fix while working on a PR and there is no ticket for it, the probability that it ever gets done is low and it ends up cluttering the code. Considering I want to delete my TODOs before I merge, it's much easier to cleanup if it's all the same line prefix (TODO).
If you have so many todo’s you need a syntax to define them more precisely, perhaps use less of them?
Hum... Ok, just standardize those names so we can have tooling support, and make them as fewer as possible so they are easy to remember.

Honestly, the article has a very expensive proposition and a completely unsatisfying reasoning. If you want to add some explanation, well, add it after the tag. The tag is exactly that, a tag, not some part of your comment.

> "If you can’t tell, this isn’t a super serious post. You can easily describe what you want to do in myriad ways using the classic TODO and beyond."

HN is one of the best discussion sites out there now, but I wish that we weren't so formulaic and repetitive. So many things get over-pushed, simply due to the familiarity of popular structures such as "X Considered Harmful" or "Why I Don't X".

If you actually read this blog post, the thread here is taking this way more seriously than the actual author was.

And that's why you came to HN for the headlines, but stay for the comment section my friend!
It feels like the post was meant to spark discussion. Which is has. It doesn't feel like anyone is taking it all that seriously to me. Just discussing what has and hasn't worked for them. I have even learned a few things from it.
You have to include disclaimers like that or else people on the web will come after you. But yeah, the hope was that it would spark some discussion on the topic.
There's not really a lot to discuss.

Most tools support automatic aggregation and review of code comments starting with "TODO". Maybe some of these tools can be configured to support other prefixes as well. But they all support "TODO" by default, and it's pretty trivial to just put your shorthand descriptors after the "TODO".

Also, if you're pushing commits with a ton of "TODO"'s, then you're probably doing something wrong. Many tools will warn you by default, and many CI/CD pipelines will block your commits altogether. If something is small enough to be addressed right now, then you should address it right now. If it's large enough to require addressing later, then it should be a tracked ticket rather than a loose code comment.

This article seems to have been written by someone who doesn't use grep.

I don't want to remember a complete ontology of greppable signifiers. I would prefer to just 'grep -R "TODO" <dir>' or 'grep -R "TODO(zomglings)" <dir>' than use a more complex grammar as the author suggests. We can stuff those kinds of semantics in the TODO message.

To me, TODOs are the equivalent to keeping thousands of tasks in a growing backlog. It just adds noise for stuff that probably won't be addressed ever. And if it is addressed, chances are that it will be from a new task. Just forget it! If it's important, it will come back on its own.

I just don't write TODOs in my code, as I have never seen a useful TODO in a codebase... The worst being "TODO: improve this". Sounds like a way to say "I wrote shitty code, I know it, please merge it anyway", which is completely useless IMO.

> Sounds like a way to say "I wrote shitty code, I know it, please merge it anyway", which is completely useless IMO.

This is not a TODO issue, this is a merge criteria issue. TODO and its variants are only as useful as the process enforced surrounding their use.

If a dev team agrees that code can't be merged until certain types of TODO-variants are addressed, then the comment may be useful.

But of course, if no such process exists, they may not be useful. But that's a team/process issue, not a fundamental problem with using TODO comments.

I'm a fan of using the extensions the author mentioned when I'm exploring a problem space. I scaffold out the overall design for the problem in terms of modules and functions so that the code reads correctly, type checks, and works for an extreme subset of inputs. Anywhere that I haven't actually implemented the real solution I put in a "NO-MERGE" comment. Then when I feel that I've solved the problem at that scale, I can go through all of my NO-MERGE comments and implement them correctly. As the name implies, these are never merged in to main/master. They just act as bookmarks which should be obvious when reviewing my changes.

Personally, I try not to commit any TODO comments. They're sort of like warnings. Unless you're religious about clearing them out, they're just going to build up and be ignored.

TODOs to me are pretty useless. Usually, they end up lying around for a long while and just create clutter. Opening a ticket is usually much better