TODO is vital for my development process. Sure, maybe there's better programmers who don't use or need TODO, but for me, it's a critical method for the following reasons.
1. It prevents my "flow" from being sidetracked by micro-optimizations that are probably too early to consider necessary anyway.
2. It helps me to retain my short term memory on the code I am working on. If I branched out at each TODO to implement some improvement or method, my brain typically needs to context switch to focus on the fine details of the subject. By the time this is done, and I switch back, I have forgotten key aspects of what I was working on and it slows me down again (i.e. local names, structs, etc.)
3. It allows me to re-approach something with a completely different mind set (given that I come back to it after a signicant amount of times). Half the time I realise that what I wrote was indeed "good enough" and no further time should be committed to it unless a reason exists to do so.
4. It gives opportunity for other developers to see, think, comment and contribute on the subject. I find that typically if I TODO an area, it's good for a second set of eye balls to see it. There's far smarter people than me around, and there's a good chance one of them will find it and propose a better solution.
5. On the rare "quiet" day, I can grep for TODO and just work through them.
Obviously these points are only valid if the TODO labels are being added in situations that will benefit from the above.
It's critical for me too, for exactly the reasons you listed.
RE point 2., it also applies to issue trackers and other "proper" way of encoding TODOs - if I tried to branch out to file a ticket in such situation, or even make a TODO entry in the Org Mode files that always accompany my projects, I'd very quickly lose the flow. Context switch is deadly here.
RE point 5., I try to work through them as I go. I consider this to be a part of cleanup after a main task - I go over all the TODOs in the area I worked in, and implement the simple ones, delete the stale ones, move the serious ones into issue tracker, and leave the rest for future reference.
All of this applies also to FIXME, HACK and NOTE comments - three other types I use. Out of these, NOTE are informative, "seriously please pay attention" comments.
I date them all. I have a Yasnippet for all the above, which expands "todo" into "TODO: $ -- My Name, 2019-12-30", $ being where the caret stops after expansion. Same for "fixme", "hack" and "note".
I think it makes sense to refine the levels a bit more. We use FIXME, TODO and OPTIMIZE in order of decreasing importance.
- FIXME should really not even be committed, except in a proof of concept
- TODO should be fixed eventually, preferably before release to production
- OPTIMIZE is a "nice to have" that gets fixed on a quiet day
Furthermore, TBD (to be done) indicates where new expected functionality is expected to appear, deliberately different from TODO because the JetBrains editor flags TODO / FIXME for confirmation before commit, and will ignore TBD.
I was actually just thinking about implementing this type of importance based flags.
In addition to these, I'd like review stubs. Something like:
- REVIEW: can this be done better?
I'd like junior devs to be able to note things as they're thinking about it, not try and remember it later during review. Especially since there may be nothing wrong with the code, it may be as good as it can get[1], so a reviewer wouldn't catch it. Though, I'm mildly concerned about cluttering up code. I suppose you could just remove them on the fly down the line, since they made it past review and etc.
[1]: As good as it can get.. that the reviewer knows of heh
> RE point 2., it also applies to issue trackers and other "proper" way of encoding TODOs - if I tried to branch out to file a ticket in such situation, or even make a TODO entry in the Org Mode files that always accompany my projects, I'd very quickly lose the flow. Context switch is deadly here.
It sounds like the ideal thing to do here, in order to stay in flow, is for these notes to be inline TODOs while coding, but for them to somehow get turned into issues before anyone else sees them. I.e. by a pre-commit hook, or by whatever tooling you use to squash commits when building PRs/patches. If you write them in a standardized format, something should be able to parse them out.
Yes, and it's entirely doable. In case of my own Org Mode notes, I could probably hack together something that does that pretty quickly in both directions (move the note from source file to Org Mode, and display notes from Org Mode inline in the code, at appropriate places). A small alteration could make this work with an issue tracker API.
But that would still be very fragile. I don't think there's a good way to record spatio-temporal coordinates of a piece of a file in a way that's resistant to changes. The usual way is to record file position + preceding and following context, but that'll break whenever someone does some bigger changes immediately around the note you're tracking. Perhaps there is some good trick to solve this, but you have to ask yourself - why go to all this ridiculous amounts of trouble to avoid putting TODO notes in comments? It's not like most of them would fit well in an issue tracker either - they tend to be too small or too context-specific to form a nicely packaged unit of work, and making this level of detail visible to managers is just tempting them to cause a disaster for the company.
Beyond it being pretty fragile to have pre-commit hooks edit code, the problem is TODOs are usually very context sensitive. They are usually only understandable given the surrounding code and part of their benefit is they follow refactorings. Tickets wouldn't have that.
> if I tried to branch out to file a ticket in such situation, or even make a TODO entry in the Org Mode files that always accompany my projects, I'd very quickly lose the flow.
Why not both? You can refactor todos with a ticket number before you commit the code. So the TODO can have some more context associated with it and maybe a discussion.
I might do that after I'm done with the code and about to commit it, but in my experience, there's very little overlap between the kinds of things you'd want to track on your company's issue trackers and the things you want to just jot down inline with the code. The latter tend to be too small.
> I date them all. I have a Yasnippet for all the above, which expands "todo" into "TODO: $ -- My Name, 2019-12-30", $ being where the caret stops after expansion. Same for "fixme", "hack" and "note".
why is that necessary ? git blame gives it to you already
Because running git blame on code breaks the flow. Because git blame may give you wrong author and date (say someone edited the code around the note, changing its indentation level; EDIT: or rebased it, as 'daemin says). Because git blame is not a grep-friendly solution. Because code sometimes lives longer than version control systems (I've worked with codebases older than git). Because very often code lives longer than the repo it originated in, so you can easily lose history (many new projects get started by copy-pasting pieces of a previous project).
I agree with all your other points but I want to point out that if `git blame` breaks your flow I recommend that you look up how to better integrate git with your code editor, it's a huge time saver IMO. With vim-fugitive I can just ":Gblame" on any code I'm currently browsing and immediately I get a side-pane with the annotations for every line. ":Gdiffsplit" shows me the diff between my version and HEAD etc...
But beyond that I agree completely, `git blame` is not the right way to track the authorship of annotations in a file.
It's C-x M-g b in my Emacs, but doing this annotates the whole file, which gets distracting enough for this particular purpose. Still, I use it frequently.
You can rewrite the git history when you squash commits for example.
One case I've heard is that some people no longer have their names on git commits they made to various Google open source projects because their commit went inside, where it was rebased, merged, integrated, squashed, and then what the public sees is a single git commit by a Google insider that is the result of thousands of individual commits.
This is a beautiful example of the general case «why don’t you just use X tool that was designed for this?» but can’t because someone made a decision that makes X tool unusable.
Workflows are full of trade offs. Different people & teams value different features in different ways. It’s what makes software development such a vibrant ecosystem.
Because it becomes more compact. Most of the time git commits are things that don’t make sense to have at a more macro level. Squashing into a single commit that represents a coherent improvement, particularly for large projects, is the best way to read its history.
I prefer a small branch with many individual commits (cleaned from fixups or not) and a merge with main branch which adds the whole feature. Then you can have two levels of reading.
There are many contexts where blame info is not visible by default: dumb editors, code review browsers, search results, etc. It's a low-effort signaling about the age of TODO as well as whether the person who left it is still around.
It's a similar reason for why you sometimes leave implementation comments in the code, not in git commit messages.
That's a fair point regarding visibility. I'll have to reconsider the pluses and minuses because before now I only really saw it as a "too lazy to make a ticket" thing.
Yes. At that point in time, these comments are by definition a list of things that still needs to be done. Removing that will lead to forgetting it, and may create a false impression that the committed code is 100% complete.
Back in my Microsoft development days, I fondly remember Visual Studio automatically adding todo comments to a dedicated little docked window in the corner of the IDE. It was very efficient and would always be in the corner of my eye and I would always circle back to them as a result.
I still use this feature, it comes under the "Task List" window. Adds any "TODO" comments in realtime by default but it's also possible to extend what tokens show up alongside "TODO" [0]. I've added "Hack" or "Perf" for temporary implementations that definitely can be improved but not necessarily critical.
Intellij Idea has this feature as well. Also it checks for new TODO comments when you commit and warns you about them, so you won't forget to fix if you wanted.
It was a while ago since I used Eclipse, but I think it greps all the TODOs in the source code or project workspace, and list them as a list of TODOs :-) for you to work through.
Not sure if it still does this but I found it to be a really good feature.
Eclipse still has this and even better you can define your own tags that are also added to the list view. You can then filter by tag name in the list view.
I found this handy when doing large refactorings (e.g. that took multiple weeks or months). I could define a custom TODO for that refactoring for labeling tasks that I knew I would need to resolve before completing the refactor but was not able to tackle immediately. It made it less stressful knowing I would be easily able to find the tasks again and the central list made it efficient to clear them all.
At work we made it a policy to allow TODOs to remain until code review. At least there, with the help of a second pair of eyes, they should be resolved, removed or made into an issue.
This is a good approach except it breaks the link from the TODO location to the issue. Are you replacing the TODOs with an URL for the issue or something like that? How do you know a file has issues/todos by just looking at the file in your editor/IDE?
Yeah, I dislike banning TODO comments from passing through both for the reason that they're so coupled to the code they reside along that turning them into an issue is rarely helpful, at least as I write them, and that they can convey a lot of information to future readers of the code about intent, about parts of the code the author regarded as shortcuts and maybe a pointer on how to shore them up, about likely shortcomings or gotchas, and so on. Unless you just allow TODO-like comments to remain but without literally having "TODO" in them, which is silly.
It makes a lot of sense if you are only a few people working the code. If not, maybe spend some minutes at the end of the day to register them as issues?
If that’s to cumbersome or difficult, something is wrong in the process or tooling, IMHO.
It makes me go crazy when I find todo scattered everywhere - often these todos are short, hard to decipher and ownership and priorities become jumbled.
What you describe in the points above actually looks like an issue tracker to me.
When I find todos I tend to cut them and paste them as issues trough slack bot integration.
It keeps an ok flow, although I get annoyed that my fellows could not be bothered...
To each their own I guess, and whatever works!
Edit: I love in-line comments and documentation though. Just not todos. :)
I use a macro to create an unit test for reason 1 and 2 and name tests with what to test_conditions_expectedResult and add assertTrue(false) as body. I forget to check for todos before I commit, but a failing test is harder to miss
There is alway conceptual TODO at a given stage of development, whether you spell it out or not. If you develop "depth first", these are few and mostly transient, and there is no real benefit to spelling them out. You work through the details before continuing. If you instead program "breadth first" you will ignore many details for the time being and instead queue them up for a future look, and tools like post-its, TODO comments, task management tools become really helpful.
My main gripe with TODO is that they're comments. Comments don't age well. Sometimes they're not written well. I'm sure that a lot of the 3000 TODOs in the Linux kernel are either things that are already done or things that are no longer considered goals. Some of them are surely hard to figure out by now. Personally I only commit a TODO comment in some limited circumstances. Most of the time I make sure that there are not TODO left before I commit. The ones that may be left at the time I want to commit are great candidates for tasks on an agile board or new user stories.
In routine application development (which, to be fair, is a slightly different problem than a kernel,) TODO comments are probably at their best when identifying code deficiencies that you don't actually have plans to fix, pointing out refactoring opportunities, and documenting other hacks. If you put this sort of a thing in a bug tracker or other system, no one will see it when they browse the code.
(On the other hand, the bug tracking system is definitely the place to put things which should actually get done.)
Ideally, every TODO should quickly result in an item on your issue tracking system. The item should point to the TODO in the code so it's easily found. That makes it easy to clean it up once it's not necessary anymore.
Fully agree on the workflow impact. What I usually do is:
1. Write the synopsis of the todo in the code
2. On creation of the MR/PR start discussions on each todo.
3. For each todo which has no quick fix or obvious solution a new issue is created referring to the todo.
This way I get to stay in the flow and record it in a big tracker for further discussion.
Great points, especially 1 - 3. For me it is also often not so much about optimizations, but rather additional use/edge cases that might need consideration, but I'm not sure yet because I haven't e.g. fully fleshed out an interface yet. Often times I will ultimately just delete the note (going back to your third point), but other times it might result in an additional test case, for example. Whenever I'm starting out on a new project (which might just be a new module in an existing code base) my mind tends to bombard me with these hypotheticals, so it is tremendously relaxing to just whip up a quick note and know that it will be dealt with by future me :).
To actually enforce this, for the past couple of years I've been using NOCOMMIT comments, together with a git hook that actually prevents me from committing those lines. I rely on this workflow so much now that I can't even imagine going back. I also get really nervous in pair-programming scenarios when someone will say "Yeah, I'll change/fix/adjust that later" - all I'm thinking is "but will you remember?!".
Instead of NOCOMMIT, I keep the "is it final" bit in short-term memory (maybe helped by reviewing staged changes) and start the commit message with "WIP:" if necessary. It's a convention from the Qt project that its CI understands. The advantage is that it doesn't block other work until resolved. Sometimes what's missing is even a good/better commit message, which is awkward to remark in the code.
Yes, automatic enforcement is invaluable. Instead of a commit hook you can also use a pre-receive hook on the server. This allows rebasing, wip commits etc. locally and doesn't require any client config.
Your points are valid, and I've used it as well many times, but ther's always the risk you find yourself in a situation where there's just a growing number of TODO items. Which isn't (always) a problem per se, but severely limits there usefulness and could be a sign of ever-expanding problems all over the code base. Worst I've seen is REALLYTODO popping up, then you know the ship is probably beyond sinking. Then again, in principle this is no different from growing todo lists, ever expanding issue tracker issues, ... But at least you can search those for context more easily imo.
To be fair, I believe many projects simply lack the second set of eyes which would downgrade those TODO to basic comments or along the lines of FUTURETODO
One of the more entertaining activities at work is to make fun of ancient TODO comments in our giant codebase. There are some all-stars most of us know by heart such that they made it into the internal company jargon. Tl;dr we ask to resolve TODOs during code review and don't allow them in now.
I try to remove the TODO’s before I commit, or at least before I push changes to master.
It’s always useful to look at your diffs one last time before adding them to the commit history.
Most of the TODOs I leave are a form of late code review. There’s some sketchy code at the periphery of what I’m working on and I don’t have the time, budget, or inclination to tackle that problem too.
If memory serves, usually for code that won’t respond to a simple refactor. For instance code with complex tests that have locked in the wrong outcomes. Write more two line unit tests, children.
TODOs are fine but only if you also have associated cross linked tickets in your bug tracker. You shouldn’t ever commit TODOs in your code without a ticket number or exactly this will happen.
I think you are ignoring all OP’s points about short term memory and not getting side tracked on optimizations. The latter of which gets me all the time.
So you would recommend instead of moving a long he drops what he’s doing and go link the ticket number back into code just to leave a TODO that in high likelihood is him working on eventually or not anyhow? Weird flow but ok.
I used to have a pre-push hook, I think, that would cancel the push if there were any TODOs or FIXMEs in the codebase, displaying them out nicely, with their location. I ultimately turned it off :P
1. It prevents my "flow" from being sidetracked by micro-optimizations that are probably too early to consider necessary anyway.
2. It helps me to retain my short term memory on the code I am working on. If I branched out at each TODO to implement some improvement or method, my brain typically needs to context switch to focus on the fine details of the subject. By the time this is done, and I switch back, I have forgotten key aspects of what I was working on and it slows me down again (i.e. local names, structs, etc.)
3. It allows me to re-approach something with a completely different mind set (given that I come back to it after a signicant amount of times). Half the time I realise that what I wrote was indeed "good enough" and no further time should be committed to it unless a reason exists to do so.
4. It gives opportunity for other developers to see, think, comment and contribute on the subject. I find that typically if I TODO an area, it's good for a second set of eye balls to see it. There's far smarter people than me around, and there's a good chance one of them will find it and propose a better solution.
5. On the rare "quiet" day, I can grep for TODO and just work through them.
Obviously these points are only valid if the TODO labels are being added in situations that will benefit from the above.