Co-workers often tell me my code is "nice" even though their linters hate it. The problem is that a linter enforces blind habit, not the motivation behind it.

If you write code and you want people to enjoy working on it, here& #39;s what I do.

(A thread on taste vs practice).
I try to make sure you can understand the first picture by only reading the second one. It& #39;s completely opposite from how some devs think, which is that the code should be "obvious" enough that it doesn& #39;t need comments.
No. The comments should be obvious enough that you don& #39;t need to read code. Because X months later, even you won& #39;t care anymore how clever you were.

The general principle is simple: you should be able to safely turn your attention off large parts of your code.
Those concerned with clarity of code would consider e.g. two partial for loops too "weird" or "unreadable". But it& #39;s irrelevant. Even if you change the implementation to e.g. map/filter/reduce/..., the comments would describe the same things being accomplished.
I deliberately chose this example because it& #39;s a case where two partial for-loops is actually the solution. If you were to e.g. make a functional lazily evaluated data flow to do the same thing, you can, but it would end up doing the same thing, minus abstraction overhead.
In a way, this is self-justifying code: it pre-empts taste arguments by never losing sight of what is being accomplished.

If someone wants to nitpick style, I invite them to write a version that does the exact same thing differently. They rarely do.
(As an aside: I suspect that most feelings of "beauty" in scientific and mathematical pursuits are really just our brain confusing our perimeter of ignorance with the edge of what is knowable, so I don& #39;t consider it a useful signal).
This is not at all the same as full-on "literate programming", nor am I a fan of it.

Code is the "what" but it& #39;s missing the "why". It also describes the "how" in too much detail. So that& #39;s what comments are for.

I& #39;m still using the code& #39;s own structure to hang my text off of.
I do try to explicitly order the functions in a file to produce a natural pedagogy. The first N functions should form a cohesive whole at a certain level of abstraction. Reading more functions should teach me more details.

This is not always possible, but always worth trying.
This is often backwards from how you write it: you start at the deep end, wrangling the details, and work your way out.

But the same way it often makes sense to paste your conclusion to the front of a post or letter after writing it, it makes sense to reorder your code.
It is also eminently useful, even in the midst of abstraction, to remind others what that abstraction is going to be used for 90% of the time.

Like pointing out that I use this function to relabel data by day. I can imagine a dozen uses, but maybe the reader doesn& #39;t even know 1.
Most codebases document examples in an entirely separate place, like a tutorial or a gallery. Certainly not in the middle of a "beautiful" abstraction.

Yet that& #39;s exactly where it& #39;s needed most.
If you don& #39;t remind yourself how what you& #39;re doing ties into what people down the line actually need, you& #39;re going to measure the quality of your work purely by taste instead of useful outcomes.
You can also do this with unit tests. In many cases, it is entirely possible to have a test suite tell you everything you need to know about the sorts of problems a library is designed to solve and capable of solving. You can write the tests with this in mind.
Code is an artifact for consumption by both humans and computers with different understandings. The technology to do this has existed thousands of years: a Rosetta stone.

Without it, we wouldn& #39;t be able to read hieroglyphics. So let a thousand Champollions flourish.
If you& #39;re wondering where Doxygen fits into all this. It kinda doesn& #39;t. It mainly exists to allow people to work with code that they can& #39;t look at or aren& #39;t allowed to touch. That& #39;s a different use case entirely.

(unsurprisingly, it& #39;s the main use of commenting in enterprise)
Docs produced from e.g. Doxygen or Swagger are also often terrible because they try to automate the pedagogy. e.g. It can auto-generate valid example inputs for any function or type... but none of it will make any logical sense.

Because an example is a _cohesive_ set of inputs.
The crucial skill you need to develop is to be able to predict how someone who isn& #39;t you, right now, will react to and absorb the information down the line.

Not just "will it make sense" but "will it be interesting", "will it be productive" and "will it be convenient".
Nobody enjoys reading procedurally-generated docs because we can all clearly tell that& #39;s exactly what they did. At that point it& #39;s just easier to read the typedefs.

See every "Reference Doc" that just tautologically restates a class hierarchy in HTML.
By the way, people often build microservice architectures with the same goal of ignoring everything except what they& #39;re currently working on.

But often the net result is that debugging a simple action now requires stepping through N separate processes on M machines.
If there& #39;s no clear recipe that tells you what is going to happen in what order and why, readable from top to bottom, debugging is a miserable experience. Everyone knows this, but somehow a lot of people don& #39;t recognize it in their own code.

/thread
You can follow @unconed.
Tip: mention @twtextapp on a Twitter thread with the keyword “unroll” to get a link to it.

Latest Threads Unrolled: