
Keeping track of technical debt in source code - philou
http://philippe.bourgau.net/a-seamless-way-to-keep-track-of-technical-debt-in-your-source-code/
======
tchaffee
I thought this technique was such common knowledge that I kept waiting for the
punchline in the article. It was a good reminder that even the simple stuff
deserves to be written about and revisited every so often.

~~~
cjhanks
They were even written as a PEP nearly 12 years ago.

[https://www.python.org/dev/peps/pep-0350/](https://www.python.org/dev/peps/pep-0350/)

~~~
metaobject
It appears that the status of that PEP is "rejected".

------
reledi
My advice is to never place TODO comments in your code. It will become a
graveyard for TODOs and annoy fellow programmers who come across it for years
after it was written.

Instead

1\. Quickly experiment with refactoring but stop if it feels wrong. We often
underestimate how quickly we can improve the codebase. It's often better to
try something quickly than waste time planning to do it.

2\. Defer if it's a big refactor or you're on a very tight deadline. Write a
reminder in your physical notebook so you don't prematurely pollute your
board. If it feels high priority after that and you still haven't had time to
do it, then make a chore ticket for it.

~~~
Normal_gaussian
I completely disagree

Placing TODO and ASAPs in code helps ensure you don't leave any loose ends,
and if you call another developer onto your feature branch allows them to get
a feel for how you're getting on and how complete the code is.

Using a physical notebook distances the workload from the code and hides the
fact something is incomplete from others.

A TODO graveyard can be prevented when you review the code - a developer who
thinks a feature branch littered with TODO annotations is complete code is
either dreaming up future use cases or failing to complete the work assigned.

~~~
TeMPOraL
I'm with you here.

> _Using a physical notebook distances the workload from the code and hides
> the fact something is incomplete from others._

Exactly. In fact, I use both (except the notebook is an org-mode file, not a
dead-tree book). TODOs / FIXMEs in code are for things very context-dependent
and connected to code, for which it's important to see them in surrounding
context. In more abstract cases, I just log a task in my notebook, to be done
later.

Examples of both - code:

    
    
      //TODO resourcify
    

(i.e. move to external string resources database later)

vs. notebook:

    
    
      ** TODO Refactor the refactor of the SomeClass class.
    

\--

Also, often TODO / FIXME comments serve for me as anchors in some larger
refactoring processes. I tend to label them specifically for easy grepping
(e.g. with unique Unicode chars like ). The point is, refactoring process may
take few days, during which I also may need to do some other tasks, so
whenever there's a piece of code that needs to be redone but _not right now_ ,
I tag it for later; I can then use grep/IDE search to check if I didn't miss
anything.

~~~
throwaway2048
I like the XXX idiom

    
    
         //XXX this is bad
         //XXXX this is more bad
         //XXXXX this is EXTREMELY bad
    

Allows for easy grepability and a rough, at a glance evaluation of the
seriousness of the hack/debt

------
skybrian
TODO's are for things that are optional to fix and probably won't be fixed.
Sometimes not fixing something is the right move, but you leave a signpost
that you deliberately skipped it. Someone else, later, can pick it up, if they
choose.

Whether fixed or not, it's valuable to future readers to know there's a gap.

~~~
degenerate
This is exactly what I use them for and it works well. They are like the
"falling rocks" signs on roads. The "TODO" is to make the entire cliffside
completely safe, but as long as everyone is watching for rocks when driving
(coding) in this section, that suffices.

------
mfukar
In no codebase or organisation I've ever worked in were comments actionable
information.

Some technical debt spans multiple lines, or across files, modules, etc.

Issue trackers are everywhere nowadays. You've found something that needs
doing? File an issue. Treat it like any other, it's not special.

~~~
maccam94
There's different sizes of TODO. For anything beyond small cleanups, yeah, an
issue is probably warranted. But, filing tasks in the issue tracker aren't
always the best solution either. They often become out of sync with the state
of the code, and who's going to trawl through all of those low-priority issues
on a regular basis? To mitigate the de-synchronization, I tend to embed links
to the issue in the comment like: # TODO: Frob the foobar issue #4376

~~~
mfukar
The only way an issue about technical debt becomes irrelevant is the debt is
not there any more. I don't know how others treat an issue tracker; on my
team, we go through issues at the start of every sprint and possibly re-
prioritise. Issue became irrelevant? Close. Move on.

------
luke-stanley
To find the todos I can do:

git grep -EI "TODO|FIXME"

Then if I want numbers I can do:

git grep -EI "TODO|FIXME" |wc --line

Credit to [https://www.commandlinefu.com/commands/view/12842/get-a-
list...](https://www.commandlinefu.com/commands/view/12842/get-a-list-of-all-
todofixme-tasks-left-to-be-done-in-your-git-project)

~~~
ziikutv
Same, but I use AG.

~~~
softawre
Same, but I use rg.

~~~
rok3
Same but I use: cat | Mk1 eyeball

In all seriousness, the great thing about a standard like this is that it is
tool agnostic.

------
partycoder
Technical debt becomes harder to refactor as more code depends on it.

Then, there needs to be awareness and a sense of urgency. Technical debt
accrues interest.

In my case, I use deprecation tags:

\- @deprecated on javadoc for Java
([http://download.java.net/java/jdk9/docs/api/java/lang/Deprec...](http://download.java.net/java/jdk9/docs/api/java/lang/Deprecated.html)),
JSDoc for JavaScript ([http://usejsdoc.org/tags-
deprecated.html](http://usejsdoc.org/tags-deprecated.html)), Yard for Ruby
([http://www.rubydoc.info/gems/yard/file/docs/Tags.md#deprecat...](http://www.rubydoc.info/gems/yard/file/docs/Tags.md#deprecated))

\- Obsolete attribute on .NET ([https://msdn.microsoft.com/en-
us/library/22kk2b44(v=vs.90).a...](https://msdn.microsoft.com/en-
us/library/22kk2b44\(v=vs.90\).aspx))

\- deprecated pragmas and macros in C++

\- DeprecationWarning on Python
([https://docs.python.org/3/library/warnings.html#warnings.war...](https://docs.python.org/3/library/warnings.html#warnings.warn))

By doing this:

\- You get a deprecation warning.

\- Some editors may highlight it.

This signals people to stop using that code.

This creates a sense of urgency to switch to or create a refactored
alternative that is cleaner.

~~~
doctorpangloss
> Then, there needs to be awareness and a sense of urgency. Technical debt
> accrues interest.

An alternative interpretation is that technical debt depreciates. That is, in
a Darwinian way, clearly the product survived WITHOUT implementing the changes
someone thought it needed. So is it really technical debt, or just baggage?

Sometimes, debts are written down.

~~~
webmaven
Sure, and sometimes you have to declare tech bankruptcy, and just do a rewrite
from scratch (often accompanied by a switch in framework or programming
language).

Whether it is "baggage" or "debt" depends on whether it is accumulating
interest (that is, it makes other changes such as adding features harder and
harder to do).

------
TeMPOraL
My way is simple - I occasionally grep the whole codebase for "TODO", "FIXME"
and "HACK", and review the results, trying to either immediately fix them or
turn into actionable items.

At my $dayjob I do Java, for which the IDE also lets me conveniently view the
TODO/FIXME entries. I also have Sonar, which reminds me of them through low-
importance warnings.

~~~
jbernardo95
This tools helps you with that process [https://github.com/ahmadassaf/code-
notes](https://github.com/ahmadassaf/code-notes)

~~~
TeMPOraL
Thanks for the link, it looks nice. I'll consider it if I ever start doing
anything in Node. At the moment, however, I prefer it simple:

In Fish Shell I have:

    
    
      function grp
         grep -rni $argv
      end
    

and I simply do "grp todo", "grp fixme", etc. Example output (it's actually
also colored):

    
    
      src/main.lisp:63:    ;; TODO FIXME introduce at some point a mapping for page list -> generation function, or something.
      src/main.lisp:89:;;; FIXME deprecated
      src/main.lisp:94:;;; FIXME unused and probably throwaway
      src/site-components.lisp:9:  ;; FIXME use some page structure map to map from (name language) to base filepath
      src/site-components.lisp:31:  (let ((colorize:*css-background-class* "no-paren-fx")) ;FIXME make configurable maybe?
    

That's good enough for me :). Also I have appropriate highlights set up in
editors & IDEs I use :).

~~~
PerfectDlite
IDEA has separate TODO tab, which can also display TODO regarding your scope -
e.g. your current changes.

------
webninja
Meanwhile, at the Indian contracting company where I currently work, I came
across a few lines of code in a phone application that no longer logged data
to a log file. I was told that it had been there for a number of years. As I
went to instinctually remove it, I was told by my supervisor that "we don't
remove anything unless we get a Code Cleanup task". Cleaning up the code now
would be "Out of Scope". It's no wonder now how this project has 1M lines of
code and 10K files... Garbage in, nothing out.

~~~
Too
Engineers who only do _exactly_ what management tells them to do should be
thrown out with the head first. If management knew exactly what has to be done
there wouldn't be a need for engineers in the first place.

------
sambe
This pre-supposes a team of people who care about technical debt. I remember
Eclipse in the early 2000s was already doing this (FIXME, TODO and something
else IIRC).

In my experience there are lot of productive programmers who, overall, add
value (stuff gets done, it's not a bug-infested disaster) but simply don't
care. Might not even have heard the expression technical debt. Might care more
about short-term reputation wins from Getting Stuff Done. They aren't going to
leave TODOs.

~~~
johnfn
If the programmers are productive in the code, as you admit, then why would
they need to spend time clearing TODOs?

~~~
sambe
Short-term productive.

------
plandis
On my team at work we require all todos to link to a tracking issue (think
like JIRA, etc...)

That way it's

1.) Clear what the context on the todo is 2.) It's clearly in our backlog and
can be prioritized accordingly.

We have some scripts that run at build time to verify all todos have the
appropriate issue as well as manual code reviews on all changes and I honestly
don't remember the last time it was done incorrectly.

------
bobbytherobot
You can pair the TODO with the issue tracker.

    
    
        // TODO(<Issue Number>): <Short message>

------
jsdalton
Interesting that the author highlights CodeClimate's "support" of TODO
comments via the FixMe engine.

The problem is that the TODOs get flagged as failures in the context of a pull
request and require a manual override. The overall attitude in the tooling is
TODOs as a code smell or problem vs. a solution.

Maybe this is not a big deal (since you can interpret the information however
you choose) but it creates cultural resistance to embracing TODOs. We've
recently started dabbling with TODOs again on my team but I still haven't
overcome a bit of guilt I feel, like maybe "I'm doing it wrong" \-- even
though I think TODOs are a perfect fit for highlighting small tidbits of
technical debt as the author describes here.

~~~
brynary
(Founder of Code Climate here.)

This is really good feedback, which we are addressing. We're going to change
things up so that by default TODO issues are emitted as "Info" severity
instead of "Minor", and we are going to change our PR integration so it does
not fail PRs on "Info" issues.

As an aside, on Tuesday we launched a Grep engine, which is much more powerful
than FIXME:
[https://codeclimate.com/changelog/58ecfa297705a149790008b2](https://codeclimate.com/changelog/58ecfa297705a149790008b2)

It allows full customization of the emitted issues.

------
mnarayan01
More in reference to the comments here than the actual article, but TODOs in
the comments can be used to transmit what I find to be useful information:
$THING was on the writer's radar, but $THING is not handled (correctly or not)
in some non-obvious manner.

If your project uses them to indicate e.g. things that _can_ not be merged
into master, then obviously that's one thing, but when they're simply
comments, the hate here seems misplaced. Other than (maybe) redis, I don't
think I've _ever_ seen code that did not have "potential things to do" that
would have been nice to see commented.

------
snird
In my opinion, this is a bad practice. 1\. It prevents discussion. Whomever
wrote the "TODO" solemnly decides what is there "TODO", without the ability to
discuss options. 2\. It does not allow prioritization of tasks easily. 3\. You
need yet another tool to discover issues. 4\. It prevents ownership of an
issue.

All those issues have already been solved with a simple ticket system (github
issues, JIRA tickets etc'). Why reinvent the wheel? What is the benefit here?

~~~
pavel_lishin
> _All those issues have already been solved with a simple ticket system
> (github issues, JIRA tickets etc '). Why reinvent the wheel? What is the
> benefit here?_

The #TODO comments live close to the code. If it gets updated (whether that's
an actual fix for the tech debt while working in the area, or removing code
altogether due to refactoring, there's no guarantee that the ticket will get
updated - and then you spend time trying to figure out which actual tech debt
tickets are up to date or not.

It also means that they're easily discoverable - you can stumble on one while
working on something, without having to hunt through Jira for what to fix.
You're also likely to understand how to fix it without having to come up to
speed, since you're already working in that code.

------
Safety1stClyde
The simpler you can make these things, the more robust they will be.

------
lloydde
In a couple of work environments, people would initial the TODO -- I'm trying
to remember if Joyent is one of those companies. I liked this, because it was
extra honesty about the craft and I could pick the person's brain if there
were issues in that code. It would also seem to allow to get a TODO brain dump
when someone is planning on leaving the company or assist in who to bring to
the table for refactoring of a large component.

~~~
veneratio
Tagging TODOs is really useful. I can always look at source control, but
that's more effort than seeing a name or bug number. At Google our linters are
actually configured to create errors for any TODO/FIXME that isn't immediately
followed by a user id or bug number: e.g. TODO(12345) or TODO(myname). I
thought it was a little annoying at first, but over time I've realized how
much faster it is to have that additional context.

~~~
dmi
I think it's important to highlight that it's definitely about context rather
than ownership when adding a name or bug number to a TODO comment.

"// TODO(dmi): update after moving to Java8" doesn't necessarily mean that
it's _me_ that has to fix it, but that someone can come to me and say "Tell me
more about this". This took me a while to learn/remember, but it's very
helpful. The hardest part for me to keep in mind was that someone else's name
on a TODO shouldn't mean I ignore it.

------
NicoJuicy
I thought this was only in Visual Studio, guess i'm wrong.

PS. In VS - Go to View: "Task List", it gives an overview of all TODO's.

~~~
matwood
Intellij also has this functionality. I use it as a task list when working on
features that span different sections of a project.

------
x21
I recently finished writing my master's thesis on "the impact of self-admitted
technical debt on software quality" [2], we use the same approach this article
advocates to identify this type of technical debt, which we call "self-
admitted technical debt" (SATD) [1].

We examined the impact of SATD on software quality for forty open-source
projects. To measure this, we took into account three criteria commonly
associated with quality: (i) on the file level, the relationship between
defects and SATD; (ii) on the change level, the potential of SATD to introduce
future defects and (iii) the complexity SATD changes impose on the system. The
results of our study indicate that: (i) SATD and defects exhibit no
correlation at the file level, (ii) SATD changes make the system more
susceptible to future defects than non-SATD changes do and (iii) SATD changes
are more difficult to perform on the system. [2] (an abbreviated version [3])

There are more patterns to identify technical debt than "TODO, FIXME or XXX".
You can find the rest of the patterns here [1].

It is very interesting to see developers confessing their workarounds and
hacks through source code comments, as it can alert later contributors to the
technical debt induced.

References:

[1]
[http://das.encs.concordia.ca/uploads/2016/01/Potdar_ICSME201...](http://das.encs.concordia.ca/uploads/2016/01/Potdar_ICSME2014.pdf)

[2] [https://www.scribd.com/document/345197805/Sultan-Wehaibi-
mas...](https://www.scribd.com/document/345197805/Sultan-Wehaibi-master-s-
thesis?secret_password=Zq5b32lVkHiyitBuQ1nQ)

[3]
[http://das.encs.concordia.ca/uploads/2016/01/Wehaibi_SANER20...](http://das.encs.concordia.ca/uploads/2016/01/Wehaibi_SANER2016.pdf)

------
heisenbit
This may be a technique to support tracking of technical debt IN your source
code IFF it can be attributed to a specific place. Some of the more vexing
debt is across the code, in the systems around the system being build or in
the tool chain and needs other types of tracking.

------
tyingq
Curious why you would track tech debt separately from other things that drive
code changes...new work, defects, etc.

Is this because it allows the devs more control over priority...like putting
it in the work queue might result in outsiders deciding priority?

~~~
wruza
You don't want to create 15 detailed issues each time you refactor 5-15 hour
old project or feature branch. Merging these into trunk/master is obviously
less meaningful. // FIXME bad wording?

Todos (and fixme, xxx) are very useful as review or editing anchors.

~~~
tyingq
That makes sense...It was the tie to "tech debt" that made it sound long
lived.

~~~
wruza
It really depends. My usual routine for brand new projects is to init
RCS/tracking only once something meaningful emerges, and that time may vary.
For "research" projects I simply don't do that, because initial refactoring
history has no value and project is copy-and-throwaway anyway. Marker comments
may be the only tracking method there. Once code is moved into real workdir,
all todos are subject to regular issue tracking.

------
gtrubetskoy
I like the way the Golang team handled the introduction of Contexts. Adding
them required a lot of re-thinking, and so they added a Context.TODO() method
which returned a context stub essentially.

Something similar could be used with todo comments in general, e.g. in your
favorite language something along the lines of:

    
    
       import todo
    
       todo.add("Fix this later")
    

Which would keep track of those and you can somehow automate reporting,
various restrictions and what not.

[1]
[https://golang.org/pkg/context/#TODO](https://golang.org/pkg/context/#TODO)

------
Cerium
I've been taught to keep these out of production code. If your code fails in a
way that gets you in a lawsuit you won't want to be explaining what that
"TODO: looks like a xxx here" means to the judge.

~~~
Ensorceled
I guess you don't file bug reports either?

~~~
Cerium
We file bug reports and fix the bugs, but we are not allowed to ship a faulty
product to our customers.

~~~
TheCoelacanth
Then you must either have NASA level QA or never ship a product. Most software
companies can't afford either of those.

------
retreatguru
I have been doing this for years. I find it helpful when going to refactor a
part of the app that has problems. I then go look in the code and see TODO
comments I added a while ago. Then I am 100% sure I really should fix that up.
Yes they can get stale but usually they tend to be helpful.

I really like reading todos written by other devs to see where a feature was
left incomplete. It's so much easier to see it right in the code rather than
lost in a ticketing system.

------
gumby
I was weirded out by this line: "Some tools, IDEs in particular, tend to
assume that you should fix all your TODOs before you commit anything."

Holy crap that's fragile!

I'm still looking for the value add of an IDE. I'm not negative toward them (I
know many many people use them and get a lot of value out of them) but I
personally have never found one that was easier than simply writing and
compiling code. Could be my use cases (the kind of code I write/projects I
do).

~~~
l0b0
Ditto until relatively recently. Vim, Emacs, jEdit, Notepad++ until about four
years ago when I tried IntelliJ IDEA. Never looked back. It was also an eye
opener about the limits of tool support in loosely typed languages.

~~~
gumby
I have a colleague using IDEA for the part of our project that's in Java.
There's a continuous stream of curses coming from his desk and he's been
programming in Java since it was first announced by Sun.

Part of the problem I think is taking your hands of the keyboard to manipulate
the mouse.

------
dugmartin
I added this VS code extension recently that highlights TODOs:
[https://marketplace.visualstudio.com/items?itemName=wayou.vs...](https://marketplace.visualstudio.com/items?itemName=wayou.vscode-
todo-highlight)

Works well for me as I'm working through new code or refactoring since it
makes the TODOs stick out so much against the dark theme I use.

~~~
Tempest1981
VisualAssist has a hashtag feature that also works nicely:
[https://docs.wholetomato.com/default.asp?W574](https://docs.wholetomato.com/default.asp?W574)

Eg: // #TODO refactor

------
peterwwillis
A lot of hate for TODO/FIXME in the comments... We've been using them
successfully in open source for decades. I would never rely on them between
releases, but during active development of a single release they are handy.

A single line is not enough to explain work needed to be done or getting said
work done, but it can be enough to explain existing work, sometimes.

------
tonto
One way I thought of doing this would be to just have every commit tagged with
some subjective score given by the committer (in commit message), probably
just 1,2,3 to avoid too much weird subjectivity of a x/10 ranking, that gives
how much the user subjectively thinks a commit is janky. then you will get a
map of source code quality over time

------
iopuy
The best solution I have found is to use TODO (so it is grep-able) but then
add a colon followed by your initials. E.G.

    
    
        //TODO: JTF, Use new error handling strategy here 
    

This way it is clear who put it there and makes it MUCH easier to keep track
of your debt and not your buddies.

~~~
OJFord
Or just `git blame` the line?

~~~
iopuy
No, this will take into account any changes in spacing which are legit changes
that sometimes need to be made but have no effect on the logic of the
commented routine.

------
paulddraper
1\. If you are going to write TODO, write TODO(paul) or similar, so that you
easily know the originator.

2\. Unless the dev team is very small, most TODOs belong in your issue
tracking system. That's where they can be enumerated, described, discussed,
prioritized, assigned, etc.

------
gregshap
I see TODO's in production code as only somewhat better than commenting out
'almost working' code.

It helps me understand the original intent of the developer, but I don't trust
that it's actually the right thing to do, and mostly shouldn't be there.

------
ascotan
The google style guide for c++ actually has a recommended format for TODO's
where the author is in parens:

// TODO(author): fix this

that way you know who was TODO'ing

------
antirez
The first comment in the blog post is great about using XXX, TODO and FIXME
for different types of debt.

------
dorianm
Maybe every comment is a TODO, as some better, clearer, simpler code wouldn't
need comments?

~~~
andrewfong
[http://ericholscher.com/blog/2017/jan/27/code-is-self-
docume...](http://ericholscher.com/blog/2017/jan/27/code-is-self-documenting/)

~~~
tchaffee
Lately I've been finding a thorough test suite to be better at documenting
code than comments. But I have to chuckle at "self documenting" every time I
hear it.

------
stuaxo
I've been doing this for a while, you need to be sparing with it though.

------
awaisraad
There's also // FIXME

------
jwineman
A good way to minimize technical debt is to block PRs that have TODOs until
the author completes them, therefore eliminating the technical debt they would
have otherwise introduced.

~~~
crusso
Although I wonder how much self-censorship that encourages. Whether or not to
put a TODO in your code is a judgement call. If you tell some developers that
admitting to a TODO means that they can't submit, they might not admit to them
as often.

It's a bit case-by-case, but I think I'd rather encourage contributors to
admit to the lacks in their code and accept them - but get them to commit to
follow ups that will fix the problems.

