14
.
11
.
2023
22
.
12
.
2017
Ruby on Rails
Software

TODO not. Do, or do not.

Stanisław Zawadzki
Ruby Developer

source: http://tiny.cc/447mkz

(source: http://tiny.cc/447mkz)

How often do you encounter #TODO: Fix this ? Too many times? Do you even notice it anymore, or does your sight slides through without noticing? If the answer for this question is positive, then this post is for you! People generally tend to procrastinate the work that is not necessary at the moment - and this is a good way of doing things. Too many time people over-implement a feature that turns out to be unnecessary for anyone – only wasting time and giving no value. Sometimes, while developing, one can spot a place for possible improvement, refactoring or much needed fix. But the worst that can be done here is to place a #TODO only. Why? Read on to find out.

#TODO is present only in the source code. This means that no one besides developers will be aware of it. Not even each developer will know about it unless he works on this particular piece of code. Neither project managers nor the system architects usually access the source code of application and they are almost always oblivious aware of the idea of improvement. As a consequence they will not take it into consideration during their development plans - and as such they will not give programmers time to develop such fix, even when it's much needed. Other developers also won't benefit from this information - they encounter it while doing different task, they don't have to know what author of #TODO had exactly in mind. And it also goes other way around – if you’re assigned to task that is actually mentioned in one of #TODOs you’ll still spent time to examine the flow and eventually find this #TODO – instead of knowing this place right away from task description. Better situation is if we have both #TODO and a task reported somewhere in the system that the company uses. In case of such linked #TODO-task situation we get rid of both problems – the managers know that there is an issue pending, and the developer can always check what this #TODO refers to. But also this approach has its drawbacks - it's much easier to bury a task in the system, and it's way more difficult to coordinate removing actual annotation in the source code.

You may ask if my point is actually valid - as many of IDEs support #TODOs by default and helps us dealing with them? Even frameworks itself have those features (for ex. Rails have rake notes:todo). Well, in theory you’re right, you can usually find all #TODOs in a convenient way. But it comes down to one simple question: Do you even use it? IDEs and frameworks tend to have many features that are barely used and this one seems to be one of them. Developers and project managers tend to have a big scope of duties and unless someone is directly forced to do this, they’re really not likely to do it. Especially when the number of things to check regularly is always increasing as the project grows more complex with time. And last, but not least, what would you do with the results even if you do actually use this feature? Go to the client and tell him “Next two weeks we’ll be making multiple #TODOs, ok"? Not gonna happen. Clients tend to care what they pay money for and don’t want to improve features unless they directly know that it will either benefit them or fix an already existing error. If it’s the first case – then we should have it reported in a system beforehand, if the second – it shouldn’t be a #TODO in a first place.

#TODO tend to stay, very often they last in code long after the author of this comment has already forgotten he worked in the company. They tend to stay even if the idea behind is already gone, and the code changed so much that the intended change is no longer viable. Nobody deletes them, as it's not included in the scope of their task and sometimes they even believe some day this #TODO will fulfil its destiny.

It won't.

So what can we do, when we have an urge to add #TODO to our code?

  • Do it immediately. Job will be done, nothing has to be remembered. This will probably mean that the task will take longer, so this factor should be taken into consideration if we plan to do it that way. But on the other hand you already are in a proper environment and you know exactly what you want to do.

  • Report it in the system. Jira (or any other tool) is a great way for storing such tasks - it won't disappear, managers will be able to see it and if it's important to the project. Assign it to yourself, your superior or your manager - this way it will be remembered. Maybe it will never be done, but this is no longer your responsibility. The good practice here is to describe it as good as possible – event with small implementation details – as it would much help if another developer will cover this in future. In this situation adding a #TODO in the code with the reference to the task is available option

  • Forget it. Sometimes even when you notice a place for improvement, you don't have resources for making them or the effort is too big for the potential gains. Projects are never complete. If somebody tells you that he finished his project, he’s simply lying. Improvement are always possible, updating libraries can always be done. That’s why managers create MVPs – because a developer will always find something to work on. Usually things don’t have to be perfect, they have to be good enough.

As always, there has to be exception to the rules. There are situation where you can safely use #TODO marker. When you’re developing a major task that requires several days or even weeks of work, you may treat #TODO as sticky notes for this task. But only put it where you’re actually planning to develop in following days, not for a hypothetical developer who will work on in unforeseeable future. And remember to check that all #TODOs are gone when you submit your code for review. I think that #TODOs are also acceptable if you develop an application only by yourself and share the positions of developer, manager and even a client. In such case reporting tasks to external services may be a little overkill.

Examples of #TODO

Good example

def index 
   @projects = Project.all
   #TODO Filter the project listed by default. Task: PRO-1  
end

Bad example

def index 
   @projects = Project.all
   #TODO Filter the project listed by default.  
end

Very bad example

def index 
   @projects = Project.all
   #TODO Fix that
end

How does it look like in real life? (state of 01.09.2017)

TODO table (Source: My own research)

As we can see – the well known ruby projects didn’t eliminate the “TODOs” entirely, but the number of them is relatively small (1 TODO on 1-5k LOC). And this is understandable, as sometimes you slightly can bend the rules. The problem is that when you have few TODOs on 100 LOC file. There is almost no chance that you will do them and either you will eventually delete them or they’ll stay there till the bitter end. Because, as always, the temporary solutions are usually staying in the project for a long, long time.

Stanisław Zawadzki
Ruby Developer

Check my Twitter

Check my Linkedin

Did you like it? 

Sign up To VIsuality newsletter

READ ALSO

How to become a Ruby Certified Programmer Title image

How to become a Ruby Certified Programmer

14
.
11
.
2023
Michał Łęcicki
Ruby
Visuality
Vector Search in Ruby - Paweł Strzałkowski

Vector Search in Ruby

17
.
03
.
2024
Paweł Strzałkowski
ChatGPT
Embeddings
Postgresql
Ruby
Ruby on Rails
LLM Embeddings in Ruby - Paweł Strzałkowski

LLM Embeddings in Ruby

17
.
03
.
2024
Paweł Strzałkowski
Ruby
LLM
Embeddings
ChatGPT
Ollama
Handling Errors in Concurrent Ruby, Michał Łęcicki

Handling Errors in Concurrent Ruby

14
.
11
.
2023
Michał Łęcicki
Ruby
Ruby on Rails
Tutorial
Recap of Friendly.rb 2024 conference

Insights and Inspiration from Friendly.rb: A Ruby Conference Recap

02
.
10
.
2024
Kaja Witek
Conferences
Ruby on Rails

Covering indexes - Postgres Stories

14
.
11
.
2023
Jarosław Kowalewski
Ruby on Rails
Postgresql
Backend
Ula Sołogub - SQL Injection in Ruby on Rails

The Deadly Sins in RoR security - SQL Injection

14
.
11
.
2023
Urszula Sołogub
Backend
Ruby on Rails
Software
Michal - Highlights from Ruby Unconf 2024

Highlights from Ruby Unconf 2024

14
.
11
.
2023
Michał Łęcicki
Conferences
Visuality
Cezary Kłos - Optimizing Cloud Infrastructure by $40 000 Annually

Optimizing Cloud Infrastructure by $40 000 Annually

14
.
11
.
2023
Cezary Kłos
Backend
Ruby on Rails

Smooth Concurrent Updates with Hotwire Stimulus

14
.
11
.
2023
Michał Łęcicki
Hotwire
Ruby on Rails
Software
Tutorial

Freelancers vs Software house

02
.
10
.
2024
Michał Krochecki
Visuality
Business

Table partitioning in Rails, part 2 - Postgres Stories

14
.
11
.
2023
Jarosław Kowalewski
Backend
Postgresql
Ruby on Rails

N+1 in Ruby on Rails

14
.
11
.
2023
Katarzyna Melon-Markowska
Ruby on Rails
Ruby
Backend

Turbo Streams and current user

29
.
11
.
2023
Mateusz Bilski
Hotwire
Ruby on Rails
Backend
Frontend

Showing progress of background jobs with Turbo

14
.
11
.
2023
Michał Łęcicki
Ruby on Rails
Ruby
Hotwire
Frontend
Backend

Table partitioning in Rails, part 1 - Postgres Stories

14
.
11
.
2023
Jarosław Kowalewski
Postgresql
Backend
Ruby on Rails

Table partitioning types - Postgres Stories

14
.
11
.
2023
Jarosław Kowalewski
Postgresql
Backend

Indexing partitioned table - Postgres Stories

14
.
11
.
2023
Jarosław Kowalewski
Backend
Postgresql
SQL Views in Ruby on Rails

SQL views in Ruby on Rails

14
.
11
.
2023
Jan Grela
Backend
Ruby
Ruby on Rails
Postgresql
Design your bathroom in React

Design your bathroom in React

14
.
11
.
2023
Bartosz Bazański
Frontend
React
Lazy Attributes in Ruby - Krzysztof Wawer

Lazy attributes in Ruby

14
.
11
.
2023
Krzysztof Wawer
Ruby
Software

Exporting CSV files using COPY - Postgres Stories

14
.
11
.
2023
Jarosław Kowalewski
Postgresql
Ruby
Ruby on Rails
Michał Łęcicki - From Celluloid to Concurrent Ruby

From Celluloid to Concurrent Ruby: Practical Examples Of Multithreading Calls

14
.
11
.
2023
Michał Łęcicki
Backend
Ruby
Ruby on Rails
Software