Document Your Code

Michael McCartney
3 min readNov 11, 2021

Comments shouldn’t really be optional*

I’m a firm believer in:

Only a fool deals in absolutes

But when it comes to commenting, documenting, and otherwise statically relaying information to future maintainers — I have a very strong belief that they are almost always a good thing.

We have all been at the Crossroads of Discovery when looking over someone else’s code or, worse yet, our own from a previous adventure. We’ve been there without any comments or documentation to help us along.

Comments Take CPU Time

We’re on the verge of the Exascale Age, computers are quite good at parsing text, and the biggest challenge with software at scale is maintenance and onboarding.

So while we need to be cautious of the Software Disenchantment, that shouldn’t keep us from adding comments to our code for fear that we cannot eek out the extra few cycles on a python app.

What is a Good Comment

The classic paraphrase of “Describe your intent, not your logic.” is always helpful.

def unpack(results: dict) -> pollkit.QueryResult:
"""
Unpack provided results, typically coming from the
web API or data cache. There are a number of checks
done in this function, each of them documented below
with a "# Check: ..."
.. tip:: This will always force file-path fields into unix
style slashes. ``file://`` will also be stripped if
found.
:raise: :ref:`pollkit.QueryResult.Invalid`` if the
data isn't aligned. Best to use try/except for
anything that doesn't need to succeed.
:param results: ``dict``
:return: :ref:`pollkit.QueryResult`
"""
for key, val in results.items():
# ...

That’s a lot of documentation for just one function but now we can always come back and we’ll never hit the “gotcha” of the path handling.

As a side note, I really enjoy the sphinx style of documentation. I even use it for some of my C++ projects.

Action at a Distance

It’s typically helpful to relay connection information for events that are not obvious while reading.

# Note: This will trigger an update on the UI
# via the pollkit.add_connection(...)
pollkit.fetch_data()

Be Verbose (to a degree)

Describing, in detail, what something does, is rarely a bad thing.

We live in a world where IDEs are plenty and well developed code management solutions exist. If you can’t stand long docstrings, there’s usually a plugin to hide them.

I can’t remember a time I’ve come back to extremely documented code and was upset by it. It may take a moment to find the information I’m looking for but at least the information exists.

Be Exact

  • Work on your terminology and stick to it while documenting.
  • Build a glossary for anything that’s specific to your code

Be Persistent

The biggest challenge is getting used to documenting nearly everything. It’s a constant battle between your desire to keep going on the project when you have a great idea and remembering that you may one day need to share the lines of code with others (or your future self).

Practice

That’s the best tool you have. Write simple APIs or applications and document the heck out of them. See if your peers can unpack that information and use it without your intervention.

Finally, Add Examples!

Examples are the single most useful tool for understanding code. Odds are, when looking at documentation, you scroll passed text blocks and look for MVP examples of some kind.

When you see multiple elements of the same project working together in a reasonable way, you can digest what makes your code tick.

def unpack(results: dict) -> pollkit.QueryResult:
"""
...
.. code-block:: python raw = pollkit.fetch_data()
try:
results = unpack(raw)
except pollkit.QueryResult.Invalid as err:
interface.push_error(err)
else:
interface.merge_result(results)

Now, be it in the generated documentation, or as other maintainers are looking around, they can see a concise example of where this class, function, variable, or otherwise fits into the architecture.

--

--