
“Good Code Documents Itself” and Other Jokes You Shouldn’t Tell Yourself - ohjeez
https://hackaday.com/2019/03/05/good-code-documents-itself-and-other-hilarious-jokes-you-shouldnt-tell-yourself/
======
SubuSS
Code will definitely tell you how something's done with enough energy.

It will NEVER tell you WHY everything was done a given way - which is where
the comments come in. The trick is to keep them updated, versioned and
restricted to WHY.

Nothing worse than the template java comments that are filled in for the sake
of it. I can't think of any codebase where I was able to reasonably rely on
those anyway: except for publicly released API.

~~~
pmoriarty
I try very hard to avoid writing clever code. Instead, I strive for maximum
clarity and simplicity. But on rare occasions I do have to write something
clever, because the simple and clear thing would either be less efficient, or
much much longer, or involve lots of boiler plate code reuse.

In those cases I may have to explain not only why I wrote the clever part, but
also how it works, because it might not be immediately obvious unless the
reader digs really deep in to the code to figure it out. I'd rather save them
(or me at a later date) the trouble.

Yes, this risks having the documentation drift away from the code if I ever
change the code (or if I make a mistake in the documentation), but it's a risk
I'm willing to take in small doses.

------
notacoward
"Comments are bad" is the "fake news!" of programming. Yes, it's reasonable to
point out that there are comments that are either inherently bad or become
counterproductive as the code moves on without them being updated. OTOH, using
those minority examples to cast the whole _idea_ into disrepute is just
cherry-picking to rationalize one's own faults. Good commenting _complements_
good code structure, naming, etc. to make code easier to maintain/extend.

~~~
MaulingMonkey
I've seen code where bad/counterproductive doc comments are the majority
examples, not the minority, as a lazy way of meeting some "100% doc comment
coverage" mandate. While it still doesn't and shouldn't cast the whole idea
into disrepute, they're useful cautionary tales, and a way to help distill
down "what makes for a useful comment?" by showing what _isn 't_ useful.

~~~
mannykannot
I could only wish that excessive and redundant commenting was somewhere in the
top five problems I face in writing software.

~~~
Bartweiss
I mean, my experience is that these aren't actually opposing problems; it's
wretchedly common to find a file where informative comments are scarce,
uninformative comments are too numerous, _and_ all the substantive comments
are out of date.

If code had one problem or the other, we might be able to judge which issue
was more common and push people the other way. As is, it tends to have all
three diseases at once and I'm not sure what the cure is except screaming "do
better!"

~~~
mannykannot
It is also not uncommon to have code where the various elements do not live up
to the claims made in their identifiers.

If a programming language is expressive enough to create self-documenting
programs, it is expressive enough to imply things that are not true.

The point is that if you are not going to trust the words a programmer puts in
documentation, then you can't trust the meaning of any words they choose to
use in identifiers, either - but if you don't trust the words they use for
identifiers, then the code is not self-documenting in any meaningful way. The
observation that documentation can be bad does not justify the claim that good
code never needs documenting.

------
reidjs
I see comments as sort of a fallback when I don’t have time or can’t think of
a more readable solution to a problem. I believe this is the rational
presented in the “clean code” book

~~~
mannykannot
I think you you have identified the source for this dubious concept's
widespread acceptance.

Putting aside the question of whether this is only about comments -- the
article is about documentation and the myth of self-documenting code --
suppose you have written a function. There are many things another programmer
might want to know about it, such as its time complexity, whether it is
thread-safe, what exception guarantees it provides (or simply what exceptions
it might throw, and what they signify), whether it modifies state, and if so,
when and what, whether its design is predicated on the system being in one of
a subset of possible states... how much does a developer have to read to
answer one of these questions? The answer is that, in general, it is not
bounded.

Now, the amount you would have to write to answer all possible questions is
also not bounded, but -- and this is the real point -- you can choose what to
document in order to maximize the usefulness of the function. And it is rare
that the optimal solution is no additional documentation beyond the source
code, at least for non-trivial components of non-trivial software.

------
piinbinary
I see code comments as useful for two categories of things:

1) Information that is available by reading the code. In this case, the
comments serve as a short-cut to understanding the code. They might be
explaining what an obscure flag does, noting the name of the algorithm being
implemented, or giving an overview of the structure of the code. You could
learn that by reading the code, but reading the comment is faster.

2) Information that is _not_ available by reading the code (or is unlikely to
be corrected derived by reading the code). For example, the reasoning behind
decisions can only be guessed at by reading the code alone.

------
Tarean
I really like ghc's comment style: all toplevel functions have a comment that
describes usage and interface. Comments about implementation details and
gotchas are floated out and referenced.
[https://ghc.haskell.org/trac/ghc/wiki/Commentary/CodingStyle](https://ghc.haskell.org/trac/ghc/wiki/Commentary/CodingStyle)

    
    
        prepareRhs :: SimplEnv -> OutExpr -> SimplM (SimplEnv, OutExpr)
        -- Adds new floats to the env iff that allows us to return a good RHS
        prepareRhs env (Cast rhs co)    -- Note [Float coercions]
            | (ty1, _ty2) <- coercionKind co    -- Do *not* do this if rhs is unlifted
            , not (isUnLiftedType ty1)     -- see Note [Float coercions (unlifted)]
            = do { (env', rhs') <- makeTrivial env rhs 
                 ; return (env', Cast rhs' co)  }
         ...more equations for prepareRhs....
    
        {- Note [Float coercions] 
        ~~~~~~~~~~~~~~~~~~~~~~
         When we find the binding
             x = e `cast` co
         we'd like to transform it to 
             x' = e
             x = x' `cast` co     -- A trivial binding 
        There's a chance that e will be a constructor application or function, or something
        like that, so moving the coerion to the usage site may well cancel the coersions
        and lead to further optimisation.
         ...more stuff about coercion floating... 
        -} ``

------
laythea
<rant> Why do i have to scroll down a full page to see any text and then when
I do, why do I have to zoom out to read it properly? </rant>

------
dyarosla
Comments in code often only describe the task at hand, and rarely ever the big
picture of how code fits together or why. Documentation, test cases(and
comments) and internal FAQs cover these to some extent, but are disassociated
from the code itself.

IMO to think inline code comments are as important as they are misses the
forest for the trees; I want to see the solution to these bigger problems.

Moreover (and this is a separate problem altogether) most code comments are
text based-Are there examples of non text commenting that have taken off?
Often an algo or structure is so much better described with an image or video-
yet most comments are text based.

There’s much to come in the way of comments- there must be.

~~~
bunderbunder
If I need to document something in a way that doesn't fit into a comment, I'll
add a separate document to the source repository and then add a comment that
references it in the code. If you're using something like GitHub that gives
you a Web interface that renders Markdown files, the ergonomics of doing it
this way are really pretty good.

I feel like this is the best way to document "big picture" stuff in general.
You don't want to just have the comments, because, if you carve it up into a
bunch of little vignettes and scatter them around the code, it's no longer a
big picture. But external documentation alone is also insufficient. If you
don't mention when it's relevant, at the spots where it's relevant, then you
can't rely on people to know when and where to look for it.

------
scarmig
I mean, sure, if you have what looks like a simple getter function for
temperature that doesn't support negative numbers, represents it as tenths of
a degree in ints, and can only be set by a recurring background process, you
probably should be commenting that.

Good code doesn't document itself, but bad code with comments also don't
document itself, and good code with comments has a surprisingly short half-
life of self documenting efficacy.

Nontrivial public classes should include solid comments, along with
interesting methods, but you don't need to be commenting a simple getter or a
parameterless constructor.

------
k__
Code doesn't live in isolation. Often we are forced to solve problems that
were created a layer below our code. In a way this can lead to unintuitive
code as well.

If I do this, I throw in some comments about my reasons to do so.

------
MaulingMonkey
I tend to flip between two extremes:

Code where I write few/no comments, because the API is intuitive,
straightforward, and free of weird edge cases or unexpected differences, with
any constraints well encoded by the type system, with everything relatively
obvious from naming conventions, etc.

Code where I write more comments than code. It might still be a good API, but
I can't fully encode the edge cases into the type system, or maybe there's
some subtle internal edge cases, or it's unobvious why you would need some
code that happens to be a bugfix, or [...]

------
simonblack
The most important habit I have carried since my COBOL days is the need to
always use self-descriptive variable names. Herewith, some recent variable
mouthfuls:

    
    
         char machine_prom_name_string[TERM_WIDTH_WIDE];
         int memory_mapping_register[4];
         int timer_interrupt_active=0;
         WORD floppy_controller_clock=0;
         BYTE four_key_reset_enable_flag;
         XColor yellow, green;
    

Oh, and just to reinforce other people: Comments are there to explain WHY.

------
winrid
Good unit tests work too. :) \- But are not a replacement.

Saying _why_ a constant's value is 4 gives business context, or why you pass
null as the last param of this function, or why we don't wait for this
function's promise, etc.

------
Communitivity
I try to live by a few simple rules regarding code vs comments. Here are ten
of them. Some of these are already in other comments, in a different form.

1\. Code should show not tell. That means the comments I write are typically
at the beginning of a class or function rather than scattered throughout on
separate lines.

2\. Code shows how, comments instruct why. A good comment includes the
reasoning behind the algorithms and tradeoff choices chosen by the coder.

3\. Good comments include an example of usage

4\. Good comments are compatible with an automated documentation framework,
such as Javadoc, Doxygen, Rustdoc, and Pydoc

5\. Good comments do not include a modification history. Version control and
changelogs can handle that.

6\. Kill your darlings - Good code follows the KISS principle, and is easily
understood, as well as easily maintained

7\. Good code is SOLID - This is part of Kill Your Darlings, in a way. To be
easily maintained, in many cases, you need to follow SOLID. Here's a good
article on SOLID: [https://scotch.io/bar-talk/s-o-l-i-d-the-first-five-
principl...](https://scotch.io/bar-talk/s-o-l-i-d-the-first-five-principles-
of-object-oriented-design)

8\. Good code is short - I don't have a firm line count, because it's
different based on domain, language, etc. I do try to keep each
method/function to no more than a quarter of a screen of code at a reasonable
resolution, so that's maybe around 15 lines. With modern optimizing compilers
and VMs this will not be a large performance hit, if it's a hit at all,
assuming you are following suggested practices. Martinn Fowler follows the
same approach, as he explains here:
[https://martinfowler.com/bliki/FunctionLength.html](https://martinfowler.com/bliki/FunctionLength.html)

9\. Good code has simple, but thought out, names. For the love of Bunnies and
Bears everywhere, please do not make a function named similarly to
GetFoobarEffectBarIndexFromFoobarSourceBarIndex ( a real function name changed
to protect the ~innocent ). Btw, Bunnies and Bears reference is from a
Microsoft practice, see
[https://blogs.msdn.microsoft.com/oldnewthing/20030818-00/?p=...](https://blogs.msdn.microsoft.com/oldnewthing/20030818-00/?p=42873).

10\. Good code breaks the rules it needs to in order to get the job done, so
apply the above rules in context. In other words - make it work, make it fast,
then make it elegant. You are the only one who can choose where to stand on
any given trade-off line, and that is fine (as long as you know why you are
standing there and can explain your reasoning). The surely wrong person is the
person who says their way is the only right way in all situations.

------
scarpino
I really wish Literate Programming had taken off. I loved that style.

