I find a large fraction of the comments I put in code these days (in C, Java and Python) are 'FIXME', 'TODO', or 'XXX' comments. I try to make my code self-evident at a low level - I do have ModuleComments?
- but making a note of a tangential issue often seems more appropriate than solving it when it turns up.
There are useful distinctions between different tags. 'FIXME' is for things which are definitely broken, but where you want to not worry about it for the moment. 'TODO' is for useful features, optimizations or refactorings that might be worth doing in the future. XXX is for things that require more thought and that are arguably broken. Of course, you can make up your own categories, but I like these ones and they seem kind of standard.
Having decided on categories, it can be useful to implicitly or explicitly standardize on them in your workgroup, so that you can use grep, syntax highlighting, and so on. For comments that express somebody's opinion, it can be good to put a userid in there so that people can follow it up with the originator.
/* TODO: How about auto-correcting small spelling errors? */
/* FIXME: This won't work if the file is missing. */
/* XXX: This method badly needs refactoring: should switch by core type. <mbp> */
This is no substitute for defect-tracking or change-management, of course, but putting the note right next to the code it relates to has good side effects:
- Next time somebody works on the code, they can keep the work that needs to be done in mind
- If somebody tracks down a bug/misbehaviour, the comment may help them understand or fix it
- After writing the comment, it may seem easier to just fix it than to leave the comment in. So, writing them is a way to briefly pop up one DesignLevel? and think about what problem needs to be solved.
- Typing right into the code is easier than using a DTS, so it gives a balance between going off on tangents, and forgetting about things that need attention.
Alternatives to FixmeComments
Who said "If it can be expressed in the code, it should be." ?
Alternatives to comments are listed at CommentCostsAndBenefits
If you are into ExtremeProgramming
, it would make more sense to place all the FIXME's and TODO's in corresponding functional test suites. That way you can never forget about them, and the feedback about project progress will be more complete and more accurate. -- JuancoAnez
In my experience, it is quite naïve to think that any TODO comment can be incorporated into a test. Most of the TODO comments I write are remarking on implementation -- exactly the sort of thing I do not
want my tests to specify. How would you propose saying "this implementation sucks; we need to fix it" if not with a TODO comment? (Often I fix it right away, but there are times when I don't want to get distracted from whatever I'm supposed to be doing that got me into that area of the code in the first place.) --MarnenLaibowKoser
13 Mar 2011
Tool support for FixmeComments
- Running a perl script over the code base can then build per-developer lists of where the FIXMEs are. Makes a great (non-XP) project management tool. "We're down to 11 FIXMEs to fix for this release." I've tried several elaborations on this, including
/*FIXME(dws) needs to allow for multiple widgets */
- Eclipse automagically extracts all the FixmeComments? (including user-definable ones) into a ToDoList. Each tag can be specified as low, normal or high priority.
- RubyOnRails has a RakeMake task (rake notes) that does something similar. --MarnenLaibowKoser 13 May 2011
- VisualStudio (disclaimer: I do not work for Microsoft) has a "tasks" area that contains both errors and warnings and references to FixmeComments. The list of comments to recognize and put in the tasks area is user-definable. -- BenSchroeder
- In C++ functions I use 'int FIXME;' - local never used variable. The compiler warns me about unused variables. -- GregorRayman
- The vim editor (when run on a terminal capable of such) will highlight FixmeComments in a manner similar to errors.
- Emacs macro provided below.
- One can also extend the doclet for Javadoc and add custom javadoc-tags to generate the todo's and stuff to the documentation (of course, it should be able to get turned off, you don't want that docs to reach the customer). Then the comments look like this:
/** @todo This method is only stubbed... */
(this line to correct formatting)
- We use it, works great! One can also use the doclet to process just extract the @todos and @fixmes into a separate page. Incorporate this in your nightly build-process! -- JonTirsen
- In CeeLanguage or CeePlusPlus, use ToBeDoneMacro
Other suggested FixmeComment classes and recommendations
(MMFS = Must get Moose and Flying Squirrel?)
- I use '???'. I find it easy to search for, and so annoyingly ugly that the fixes happen quickly. -- EricUlevik
- Be careful with ??? if you program in C/C++. That sequence of characters is a TriGraph? (a way of typing certain tokens on terminals that don't include them - strictly a LegacyFeature?), one of the more dubious features of the ANSI C standard - sufficiently dubious that most compilers disable it unless you ask for it explicitly. But if it's enabled and your code mysteriously won't compile, it might be the TriGraph? being converted into some other token.
- I used to use FIXME, TODO, etc in my code. But ever since I've started with ExtremeProgramming, I've sort of have only one left, REFACT, and that is also almost obsolete. REFACT means something like this code smells but we couldn't figure out what to do about it. Then you try to capture the smell in a few sentences, and when you put together all the REFACT, you might discover what it is that smells. It's sort of a process for EmpiricalPatternDiscovery. -- NiclasOlofsson
- I've added the REMOVEME tag to my set - Nearly a synonym of Niclas' REFACT, I use it to mark code that I threw in for testing, or just as a workaround while the real code hadn't been written yet. Or when I find code that someone else has written that definitely needs to go away. -- WayneWerner
- I've been using LEGACY for things that are currently working, but should probably be changed to a better way and definitely should be documented, and would be useful to have gathered under a tag in any case.
At QCI, we call these "placards", like the signs on the back of trucks (BioHazard?
, Flammable, etc). Placards for common uses like marking workarounds for bugs, fixmes, and warnings are specified in the coding standard along with descriptions of the situations in which they should be used. They are condensed comments on the state of the following code and give maintainers, reviewers, etc., a good idea of where to look for future problems and issues and an explanation for non-standard practices. Some examples are FIXME, HACK, WORKAROUND, BLACK MAGIC, PORTABILITY, etc.
We don't tend to use these for problem tracking as much as for code clarity, although we do have scripts to scan code for particular placards and will often use them in release checks.
Is it worth while to try to standardize these cross organization a little? It would very nice if we could get people to use mostly similar comment markers and have tools highlight them for instance.
This is what I use for emacs. Unfortunately the version supplied by others does not work well with multiline comments because the emacs technique does not work. This fixes that but limits recognition to the first two characters.
(defvar c++-mode-comments-alist ())
(defmacro make-new-comment( mode face strcom color1 color2)
`(if (not (assoc ,strcom ,(intern (concat (symbol-name mode) "-comments-alist"))))
(setf ,(intern (concat (symbol-name mode) "-comments-alist"))
(append ,(intern (concat (symbol-name mode) "-comments-alist")) '((,strcom . ,face)))))
`(modify-face ',face ,color1 ,color2 nil t nil nil nil nil)))
(let ((pos (nth 8 state))
(if (not (null pos))
(let ((str (buffer-substring (+ pos 2) (+ pos 4))))
(setf face (assoc str c++-mode-comments-alist))
(if (null face)
(setf face font-lock-comment-face))))
(setq font-lock-syntactic-face-function 'cpp-font-lock-syntactic-face-function))
(setf c++-mode-hook 'cpp-mode-hook)
I use /*! */ for Qt style comments ( used by DoxyGen
) and /*++ */ for fixme comments.
(make-new-comment c++-mode font-lock-c++-mode-refactor "++" "Pink" "maroon")
(make-new-comment c++-mode font-lock-c++-mode-Qt "! " "misty rose" "DarkGoldenRod4" )
For emacs lovers, the following is a godsend:
'(("\\<\\(FIXME\\)" 1 font-lock-warning-face t)))
(modify-face (quote font-lock-warning-face) "Red" "yellow" nil t nil t nil nil)
so now every FIXME string on the screen stands out in angry red on yellow background. It *really* gets your attention.
for a ready-to-use lisp file.
That's quite wonderful :-) I changed it slightly to confine this angry face to fixme comments and not all warnings:
(setq fixme-modes '(erlang-mode java-mode c-mode emacs-lisp-mode scheme-mode))
(mapc (lambda (mode)
'(("\\<\\(FIXME\\)" 1 'font-lock-fixme-face t))))
(modify-face 'font-lock-fixme-face "Red" "Yellow" nil t nil t nil nil)
Also, every once in a while, I do M-x grep FIXME and hit the next error key to visit all the FIXMEs in the directory, one by one, to remind myself of what needs/is left to be done.
Is there an equivalent code method in XEmacs? The above code doesn't work for me on NT 21.2
Is that because you simply don't have grep
on your NT installation? If so, download CygWin
XEmacs has no font-lock-add-keywords; you have to do it in a more primitive way:
(defun my-c++-font-lock ()
(append '(("\\<\\(FIXME\\)" 1 font-lock-warning-face t))
(add-hook 'c-mode-common-hook 'my-c++-font-lock)
I have found the following useful:
(defun font-lock-add-keywords (mode keywords &rest args)
(append keywords font-lock-keywords)))
as font-lock-keywords is a buffer-local variable anyway, it shouldn't matter
to which mode we are appending... I hope :)
Our code standard supports @todo, @review, @bug, and @idea for "pending work" sort of things. We find them very useful. http://www.infospheres.caltech.edu/resources/code_standards/java_standard.html
. -- JosephKiniry
It would be interesting to know something about the life cycle of the FIXME. Do they increase without bound? Do they congregate or are they lone wolves? Are they really better than just doing a good enough job and then stopping? Are they invitations to violate YAGNI, or incantations against it?
My experience (on new development, not maintenance) is that FIXMEs tend to cluster in new modules initially, representing the rough edges that need to get filed down. As the module matures, the rough-edge FIXMEs get resolved. I don't have data beyond that. -- DaveSmith
In my experience, these pending work comments exhibit a bit of a bell curve - they grow during design (we use an extended version of BON), level off, then as development progresses, they decline slowly (though not monotonically). What is left is what I typically put into the top level TODO file that goes with the deliverable (i.e. good things to add for version N+1). I could write a little shell script or two that goes through every tagged snapshot of all of our projects and get some hard numbers, but that's for another night when I'm feeling bored and am done with my thesis. -- JosephKiniry
(To be pedantic, that's a Rayleigh curve.
I often work in LingoScriptingLanguage
, which has several limitations in its tacked-on-at-the-last-minute OO support. I find myself writing WorkAround
s for simple things like VirtualInheritance
. When I write WorkAround
code that might need cleaning up later, I'll use a HACK: comment to explain why I think the code is a hack. This is especially useful if I'm forced to break encapsulation. -- RobHarwood
I would recommend giving up the FIXME and TODO comments completely. If there is a problem, fix it. If you don't have time to fix it now, you give up the right to specify to someone else how to fix something. If something is required functionality, implement it now. If something is functionality you just thought up, ignore it until it is asked for. It is quite arrogant to place demands on the follow up programmers, so don't do it. -- WayneMack They're just notes on a todo list, not carved in stone. If you've noticed three FIXMEs, you can mark two while you attack one.
I almost agree about FIXME, and strongly disagree with TODO. As I peruse code, all kinds of ideas about how to improve it occur to me as I get in the zone on a given chunk of code. If I don't document them, I will have to recreate the thought process, or more likely the good idea will have evaporated forever. This is where the TODOs come in very handy. This is in no way "placing demands on follow-up programmers." It is a note-taking system integrated with the code. If it makes anyone feel better, I will place my initials by it as if to say "this is my job." But I think it is pathological to be offended by "TODO" comments in the first place.
I go one step further by prioritizing my TODO's. Things that must be done before the next check-in are level 0 TODOs. Things that I'd like to do before the next check-in if I have time are level 1 TODOs, and things I'd like to get to at some point are level 2. Then when I do the grep next-error check, the list sorts itself by priority. I am actually amazed that anyone is objecting to a TODO list. Do you not do chores at home until "it is asked for?"
I agree with BobAnderson?
. In particular, I disagree with "If something is required functionality, implement it now.". Often the customer gives me a list of required functionality. Rather than try to memorize that list, or keep referring to that list on paper or in some separate document, I copy that list into the source code as a series of TODO comments. I think this is called TopDownProgramming
. Perhaps WayneMack
would be happier if we split what are currently "ToDo
comments" into 2 categories: nifty ideas that we are currently jotting down (perhaps renamed something less demanding like IDEA: ?), and distinguish them from "The customer requires the program to do this in the final release, but it can wait until after the alpha test functionality has been implemented and tested."
I agree with Wayne almost. I'll put fixme comments in to remind myself to do something in a programming session. But when I pass the code off to the next guy all the fixmes should generally be fixed or removed. After all, its my job to fixme.
I use a lot of FIXME comments, but in practice am pretty bad about grep'ing them to see what I've left dangling. I kick myself when I'm chasing a subtle bug, and finally track it down to a function containing something like
%% FIXME: Think about what happens if X dies here. I should probably modify the compiler to print FIXME comments as warnings! -- LukeGorrie
I guess I (cautiously) disagree. I view the FixmeComment
s as part of the flow of implementation. I do agree that it's better to write a test (which fails) than a FIXME, if you can, but many times that's overkill. Stopping to write a story would be overkill too. So I suggest that every few weeks, we grep the FIXMEs into a report, have the team look over them and decides which ones are worth a TaskCard
for the current iteration. FWIW - there are currently 200 FIXMEs in our code base, and last time we did this, 10 of them warranted TaskCards?
. Perhaps we're much too liberal in writing FIXME?
Re-read the comments above. This sounds like a justification for getting rid of the FIXMEs, i.e. 190 out of 200 are apparently unimportant. Why are they there? If you get rid of that mass, you can probably take a closer look at the ones that remain, and see if they can't be eliminated as well. Hint: If you keep your tasks small (iterative development), you should not need to leave things hanging. -- WayneMack Yes, don't let the backlog get large or the signal will get drowned out in the noise.
In programming, and in life, I'm not a big fan of big to-do lists. (Sometimes they're necessary, but it's easy to confuse an extensive list with well-set priorities.) I've never used FixmeComment
s, mostly because it seems to me that if something in your code smells bad enough that you need to fix it, you'll notice it as you're dealing with that code. Is it actually common experience for people to want to do some refactoring, but not know what might need refactoring?
[11 Apr 2003] Perhaps someone else has data on whether that is common experience or not. Anecdotally, though, it is apparently very
common experience that the developer knows what needs to be done, but does not currently have the time to do it. Perhaps the incidence level of FIXMEs (as opposed to TODOs) is an indicator of how well the development methodology in use is working? Just a thought...
I find it a common experience that I know that *something* needs to be done, but I don't understand what. Our shipping codebase (not developed with XP methodology) has had more than 200 TODO comments in it for a long time. From time to time I go through them and try to resolve them, but usually I can only fix a small number of them. Most of them represent potential problems that I don't know enough to understand if they are real problems or not, and if so, what to do about them. When I can resolve an old TODO it is usually because I have come to a better understanding of the complexities involved and now know the proper way to resolve the problem. More often, I look at a 6-month-old TODO and I still have no idea how to fix it. I'm not sure if that is caused by my imperfect understanding of a complex domain, or simply by my lack of discipline.
I used a system with "NN"-TODO-"WHAT": description
- NN: stands for the id of the programmer (in my case AS)
- WHAT: stands for different hints like IDEA (good ieas), MEM (memory enhancements), PERF (performance can be better), ...
So it was very easy to find all "TODO"s (grep TODO *.*) or just my "TODO"s with a grep "AS-TODO" *.*. For example I used MEM for memory enhancements, if I knew that we can do it better but not yet because of real life timelines, I can do it afterwards. Just make a grep "TODO-MEM" and I get all memory enhancements.
Every TODO needs a description what we can do to make it better.
Hashtable managers = new Hashtable(); // AS-TODO-MEM: Put the managers into a class
BTW: I never used AS-TODO-FIXME or AS-TODO-BUG. -- AndreasSchweikardt
moved from ToDo
* @todo : take over world
This is a classic example of a 'todo' that will be NeverDone. They're like installing a broken window which cannot easily be fixed, (see FixBrokenWindows) if you look at it that way. -- MatthewAstley
I got interested in this subject recently so I tried to formalize/conventionalize these tags. I called them "Codetags". I just tried to get some feedback from the Python community by making a PEP out of it, but it is looking like that's not the best forum for such a proposal. Please check out [http://tracos.org/codetag/wiki/Pep
the PEP proposal] and feel free to add comments on that wiki, or just right here. Also let me know if you think there is a good place to post it. Thanks. -- MicahElliott?
You left out "wontfix", which is somewhat controversial, but indispensable in some circumstances, such as: it's agreed that something is a bug, but it won't be fixed because the entire module is going to be rewritten anyway, which will make the issue moot.
Despite Sun's attempt to impose a standard on FIXME vs XXX, there's already too many decades of chaos on that topic, and too many millions of developers who won't be influenced by Sun, so I think the two should be regarded as synonyms - and for XXX to be excluded from the standard list, since "FIXME" is completely mnemonic.
It is cruel to use opaque acronyms and abbreviations which drop vowels; it's hard to figure these things out. On that basis I hate: MLSTN RFCTR RFE FEETCH, NYI, FR, FTRQ, FTR WKRD RVDBY
I aesthetically dislike for the comment to be terminated with <> in the empty field case, and I'm not so sure I like <wNN pN DRM> as the terminator in the non-empty situation, either. The terminator should probably just be different than the field markers.
The fields that you propose seem fairly arbitrary. Workweek (wNN) for instance an uncommon time unit, and furthermore, TODO/FIXME comments tend to only rarely have estimated completion dates of any sort. Ok, the fields are optional, but you want to suggest fields that actually will be widely used.
The field for the initials of owner: should be more than just initials. Initials are common, but so are full names, ad hoc abbreviations ("DougM" and "DougJ" both on same project).
The priority level: As soon as I see priority, I wonder where "severity" went. The next thing I wonder is what the scale is; 0..9? Is 0 low priority or high? Then I also remember that people are always confusing priority and severity, and that some people are really
bad at judging priority and/or severity. Some people will always mark every bug as a showstopper - which implies that there must always be a name associated with priorities and severities, to know whether to take them seriously or not.
Which brings up the overall issue that some of these things will be automatically fed into bug trackers and PIM ToDoLists?
etc, so as long as you're including a few things related to bug trackers, you may as well include all of them (as with the "severity" example above), by looking at several bug trackers and seeing which kind of keywords they support.
In fact, I think that in an ideal environment, each and every single such tag would be automatically forwarded to the appropriate piece of software/person. Some people argue against FixmeComments?
because they should be in bug trackers or in project planners; I disagree (who's going to forbid me from commenting my code?), but setting things up so that the tags can be auto-forwarded when desired gives the best of both worlds.
It also then provides a framework for which tags should exist and which attributes they should have. The tags that don't seem appropriate to forward to any kind of tracking software might be candidates for deletion from the standard list. Or maybe they are a signal that we should invent a new kind of tracking software. ThingsThatFallThroughTheCracks?
-Catcher version 2.1 :-) -- DougMerritt
I've seen far so many systems littered with TODO comments that nobody has ever gone back and addressed that I've learned never to use TODO comments in my own code. If something absolutely must be done, I prefer to add a failing test to the test suite to demonstrate what is missing and then get back to the task at hand. When that is done, I can go back and address the failing tests until the bar is green. -- NatPryce
I prefer one tag that means anything: ###
the pound/hash character is very easy to see among hundreds of lines, and by only using one tag, you just search on ### to find all todo's, fixme's, refact's, etc.
See ReverseIndex ToDo ToDoList CommentCostsAndBenefits ToBeDoneMacro