Bad Reasons To Write Comments
When writing software we need to leave important information behind. Some of this is the “documentation” of the code, JavaDoc etc. I can assure you that this sort of annotation is very important to me, as is evidenced by the docs on open-source projects I’ve produced.
While there’s always something useful to add to the boundaries of a system, regarding the semantics of using it, and this includes producing OpenAPI specs too, the subject of code comments is a different one.
The programming language we use is itself a way of expressing algorithms and purpose. Though in some cases, the code CANNOT explain WHY something is the way it is, or WHAT precisely is going on, in a particularly gnarly bit of trickery, our default approach should be to write code that’s so self explanatory that comments simply are not necessary.
Optimisation MAY fight against this, leading to some weirdnesses:
However…
Virtually none of our code ever needs to be optimised for runtime beyond some basic hygiene.
With JIT compilers, self-optimising runtimes, and things never being as slow as you think, the majority of our performance problems will be nothing to do with the way we’ve written the code for readability.
So make code that’s so readable that it doesn’t need comments.
This means:
- Write at a consistent level of abstraction
- Refactor relentlessly
- Have small functions with good names and single responsibilities
This really isn’t rocket science.
But but but…
Anyway, here are some rebuttals of common arguments in favour of comments:
- The junior programmers won’t understand the code – write less cryptic code, don’t use your codebase as a programming textbook, train your juniors
- This is a long method and it can’t be digested – break the method down
- I don’t want loads of small functions everywhere – why? are you on a budget?
- These self-explaining function names get a bit too long: it’s hard to type – this implies that you think a comment is shorter than a function name, or that function names take up too much memory, or that you have to type, rather than auto-complete functions while coding… literally NONE of that is true
- I don’t need to reuse this function, why extract it – re-use is nothing to do with function decomposition
- How can I see the whole if it’s made of lots of small pieces? – yeah, I made that mistake once too, there should be higher level things which compose the small pieces, those higher level functions should explain the whole as they have a good name, and they pull together some well named pieces
- I need my future self to understand this code – write better code
- I need to explain the business case – if your business case documentation is spread through the code that might be bad – it’s possible that some high level documentation is needed – perhaps in the README or elsewhere
- Self explanatory method names are wordy – not as wordy as comments, plus improved patterns of decomposition can help reduce the word count – practice makes perfect
- What if something in the code needs to be left alone or it’ll break – do we need a comment here? – possibly, though writing a unit test that acts as a sentinel for that behaviour to make sure it’s present is possibly more powerful
- You just can’t express the meaning in a function name – complex functions are hard to name, break things down into small pieces – essays in code cannot be skim read and slow you down more
- What about the performance cost? – if it’s really slow… like in real life… then sure, refactor it for performance, in reality it’s not – I’ve almost never needed to optimise code to reduce function calls from code decomposition
- What about the call stack if there are lots of sub routines? – how shallow is your call stack? They’re usually deep? And why do you assume that this will go down deeply, vertically. Decomposing a monolithic function will create a depth that’s a logarithm of the total complexity – each tier will go wider than it goes deep
- What if the dev team moves on and someone has to pick it up – they’ll appreciate simple self-explanatory code MORE than pages of excuses about why the following code is hard to understand
- I need to leave a diary of what happened – why? don’t you use source control
- I can’t express my thoughts in just code – go and do something you’re good at, then
- This doesn’t make sense at first glance – can you not make it better, then?
Don’t get me wrong. I write comments. 50% of them I write for good reasons. Many could be removed and many of them are admissions of my own failings where I’ve not taken time to make the code better.
And then sometimes there’s a damned good reason to leave a warning to the future developers and I absolutely do what’s necessary.
But I don’t think comments are virtuous. They’re an occasional necessity when the code can’t be done well enough to avoid them.
The overall conclusion I have here is:
Prefer simple self-explanatory code to comments.
But Performance in Embedded Software
Ok… there are edge cases where you’ve got no memory and every CPU cycle counts. Perhaps you’re coding in a high-level language which compiles down to low level code, and perhaps there’s no optimiser… I mean, it’s possible. It’s unlikely… but there are edge-cases. So, start with the most readable code, then optimise it. Don’t go crazy. Your profiler is your friend.
Published on Java Code Geeks with permission by Ashley Frieze, partner at our JCG program. See the original article here: Bad Reasons To Write Comments Opinions expressed by Java Code Geeks contributors are their own. |