# using heapsort instead of quicksort
# because we care about the worst case
heapsort(data)
Code alone cannot tell the reader why heapsort is chosen, nor whether that's how the code should be. And tests are unlikely to capture this either. # using heapsort instead of quicksort
# because we care about the worst case
heapsort(data)
Code alone cannot tell the reader why heapsort is chosen, nor whether that's how the code should be. And tests are unlikely to capture this either.Describing what a single code is doing is only useful, if the comment is easier to read than the code itself. That can be useful for arcane cases, such as dirty regular expressions, bash scripts with several layers of pipes, or non-standard pointer manipulation in C.
Much more important, is the why, as in your example.
But there is also the what when it applies to code design that spans more than a few lines of code. This requires documentation. As long as we follow a design pattern, the documentation is covered by the pattern description.
But if we invent a novel design, either a one-off or a new design pattern, it needs to be described in text and figures, not just inline in the code.
Similarly, and even to some extent when staying inside a design pattern, object models need a conseptual design, where the ideas and purposes behind each class or interface is explained, as well as where the relationships between classes are visualised.
I still maintain we're awaiting another generation of version control where commentary on code is cumulative, instead of just set at the time of commit.
For example, you could express the same information that the comment in your example provides in the following manner with self-documenting code.
enum PerformancePrioritization {
FastWorstCase,
FastAverageCase
}
function sort(data: List<TypeOfData>, performancePrioritization: PerformancePrioritization) {
if (performancePrioritization == FastWorstCase) {
heapsort(data);
} else {
quicksort(data);
}
}
...
sort(data, FastWorstCase); /*------------------------------------------------------------------------
; For the RR OPT, the class field is actually the size of the UDP payload,
; and the TTL field are a bunch of flags. We have a separate field for
; the UDP payload size, so here we make the adjustment behind the scenes
; so you don't have to know this crap.
;-------------------------------------------------------------------------*/
if (answer->generic.type == RR_OPT)
{
answer->opt.class = answer->opt.udp_payload;
answer->opt.ttl = ((data->rcode >> 4) & 0xFF) << 24
| (answer->opt.version & 0xFF) << 16
| (answer->opt.fdo ? 0x80 : 0x00) << 8
| htons(answer->opt.z & 0xFFFF)
;
}
I'd like to see how I could do away with the comment and make this more "self-documenting".[1] Code to encode/decode DNS packets: https://github.com/spc476/SPCDNS/blob/05aead581acf050edf610c...
But a sibling comment [0] did provide an example that would give a much simpler approach to accomplishing the same thing in this particular instance, with zero extra lines and runtime complexity.
import heapsort as worstcase_nlogn_sort
worstcase_nlogn_sort(data)Code can't lie (although it can be misleading with improper naming or bad abstractions).
Comments can be completely false (although they're easier to catch because the comments sit alongside the code)
Design docs almost always lies and it's hard to catch the lies because a design doc written 2 months ago is never going to match the resulting code perfectly. In my experience, people rarely update documentation unless there's a dedicated employee/developer advocate who is helping enforce and drive the culture.
But when you too lazy to update design docs, code and docs get out of sync. And it's always easier to just leave docs unchanged, because "hey, code works".
It's a bit similar to word processor compatibility issues on linux and windows. You can have perfect implementation of specification on linux, but Microsoft does some changes that are not specification compliant and now a doc created on windows does not open on linux. And from users perspective it's linux fault that file can't be opened, even though it's actually microsoft that is not following specs.
That depends how you're writing design docs. If a design doc contains arbitrary flowchars about what happens in the code, it will change.
But if you come up with designs similar to design patterns, you can document the pattern once, and use it in your code the way you use a design pattern.
Concepts that span a large codebase is also enormously paintful to figure out from reading the code. For instance object models / microservice architectures, complex state machines or security frameworks are hard to catch implicitly from reading the code.
I've worked on code older than I am and those little comments that probably should have been design docs were a godsend. Nothing else had survived.
I agree with you but in my experience unless you are writing this documentation in a regulated industry (with external incentives to keep the documentation up to date) the technical docs will eventually go stale or out-of-sync with the actual implementation.
We're talking about a line of code that has 2 words here. "A method to sort something" and "something to sort".