TL;DR; : You are always coding for a fellow programmer, not for a machine. You should put the most energy to make it easy for he/she to understand your code. The machine will be fine anyway. Dead or commented code is like false trail signs that only befuddle people, so avoid it at all costs.
I spend a lot of time reading code – mine, my colleague’s, and others, when asked to “take a look” on a given codebase. On several recent occasions, I found myself staring at two versions of dead code: commented code and unused code. You may think that dead code is not good – and you’d be wrong. Dead code is far worse than that – it is actually rotting your code base. I wanted to take the opportunity to explain why.
Commented code – the memory devil
Commented code can appear quite easily: you are replacing some existing implementation by another, and willing to let everything work until you are sure of the “new way”, you just comment out the parts that will no more be used. Then, at some point, you forget about it, letting some puzzling piece of code prefixed by “//” or “#” or something like that.
Now, when I ask why it is “still” there, I get several kind of answers, that I could screenplay like this:
- Why is this code commented out?
- This one? Because it is no more needed, we are now doing Y which is much better.
- Great! Why it is still there then?
- Well, we changed it for the best, but the old approach did work, so it is there “in case of”.
- But it is commented, right? It does not do anything more?
- No, it is just to be able to use it again should it be needed.
- Don’t you use Git (SVN, CVS)?
- Yes, why?
Again, as outlined above, I think there is a perfectly valid case for commented out code: during a refactor. I do not wipe out everything when I’m refactoring, I’m moved pieces bits after bits, and the comment part is very useful. But, the commented code should be gone before any other person could see it (except my imaginary friend the pair programmer). By the time my pull request is ready, it should be long gone. Be careful, it is easy to forget.
There is one thing commented code is very efficient at: spreading FUD. Not for the machine, of course, it discards it immediately, but at your fellow programmers. Comments are supposed to be a trail, like little bread crumbs dropped by the previous programmers to help you find your way. Each of them is a sign, which means you should ponder them : how easy would it make for the person following you to follow this trail ? How straightforward is it ? Having no trail signs at all make the road difficult, but false or contradictory ones can be even worse.
The conversation above can seem funny, but it is the easy case, where there is someone to answer. There is not alway someone, and stumbling on commented code leaves me uneasy: why did the previous programmer remove it? What was the flaw in? Why did he let it there? Is it because we can still need it? In which case? I do not remember a lot of cases where the reason for commenting was itself commented.
Again, the best way is to remove it, and commit the reason in the log. This would leave the future programmer every chance to understand the code, and release him from the need to understand every step of the history of it. We need the code history, but we have a splendid tool for code archeology: the VCS. There is no need to double down its job.
Unused code – the insidious devil
Of course, commented out code is only the lesser evil, compared to his far more dangerous cousin: unused code. Code that is not commented out, but is “normally” no more used. Like in “should be no more used”.
This is far worse because it is not only sending incorrect message about the code base, it also costs in maintenance – I may well do some refactoring, and take tim
e to fix code that is actually just dead meat. Identifying dead code is no simple job, but facing the expression outlined above, I tend to urge to remove it as soon as possible, using tests to validate that it was really not used.
The “we let it there just in case” is even weaker here than in the previous case: again, the VCS is your friend, let it work. The smaller, leaner the code base is, the faster the new features will be done, and the fewer bugs will be introduced. I like to paraphrase the Agile Manifesto: the best code is the code you do not need to test, which exists: it is the code that you delete (or do not write at all).
This is one of the situations where it is very important to remember a primordial truth in programming: the primary target of any code should always be another human being, never a machine. That means that you should always write it to make it as easiest possible to grasp by that human being, not by the machine, for several reasons:
The machine will be able to understand it anyway, thank you. It does not need your help for it, nor does it really care about how impossible to read it is, as long as it is syntactically correct.
You can think that sometimes, it may make the code a little less efficient, but this is tricky to determine, and compilers are disgustingly good at running code, so chances are good that they can optimize it better than you can. Anyway, the day you code this kind of optimization, you are not forbidden to comment it extensively.
Most of the works on a codebase happen in maintenance, not in the initial glory days of greenfield development.
Finally, chances are good that that “other human being” is actually you in 3-6 months. So do you a favor, and remove this dead code today.