35 comments

[ 4.5 ms ] story [ 92.8 ms ] thread
Writing something is like writing something. what an insight.
I agree that one should strive to make good code human-readable and I often also try to use names in a grammatically correct way (to make reading easier).

However, this article leaves me wishing he'd show examples of what he's talking about.

I'd like to see his code to determine whether it reads more prose-like.

Also, sometimes the meaning of the word "prose" is very subjective.
I'll give my personal pet peeve as an example: abbreviations.

When I want the constant for the user's language, everyone knows they're looking for LANGUAGE, in principle. And long identifiers aren't quite the problem any more with autocomplete. But some library- and language authors insist on saving 4 bytes by naming it LANG, or even just L. Or they somehow end up with this abomination:

    > locale
    LANG=en_US.UTF-8
    LANGUAGE=
There are better examples where more variations can be found in the wild. And there are some abbreviations that somehow just feel terribly ugly to me, but I've apparently succeeded in erasing them from memory. They sometimes remind me of people who use a plus sign instead of the word "and"–it betrays a certain lack of respect for the language,
Whether you use it or not the Illumos code base[1] is one of the most well written I've seen in this respect.

[1]https://github.com/illumos/illumos-gate

I can see some merit in this, a story will often reveal the problem better than cold analytics, but I have to say I still think the common approach of defining the objects and then the actors is going to get a better outcome.
Those objects and actors come initially from a story, and how you tell that story may affect how well you define them.

Defining the objects, the actors, and their interactions is part of writing prose, but there is more: you have to present them in a logically consistent manner, and furthermore in such an order that the reader is not confronted with an idea she has not yet been prepared for. The way that the components of a program are assembled has analogous consistency and ordering requirements.

Writing a program is a bit like writing a specific form of prose: an argument for a proposition. In the case of programming, the proposition is that the program will do whatever it is that you require of it.

A code comment is not like an intro paragraph. Comments are second class compared to code; see any code base. Of course they don't actually do anything except confuse humans, partially because they have no defined syntax or grammar, and partially because most programmers fail to maintain them as they change code.
Even incorrect comments are enlightening rather than confusing if you read them with the right mindset.

From the code you can tell what the program actually does. From a comment you can get some idea about what the authors intended, at least at one time in the code's history.

Nice post! I would add that some prose reads like poetry. Some poetry is abstract and unreadable :)
Or, in other words,

(ROOT (SINV (VP (VBG Writing) (NP (JJ Good) (NNP Code))) (VP (VBZ Is)) (NP (NP (DT a) (NN Lot)) (PP (IN Like) (S (VP (VBG Writing) (NP (NN Prose))))))))

I hate when I read other people's code that has scores of characters on the same line. My code is less prose and more poetry. I treat each line as its own idea.
I much prefer the poem analogy. My favourite code almost appears to dance around in my mind.
My attempt at parediting original example into poetry:

  (ROOT
   (SINV (VP (VBG Writing)
             (NP (JJ Good) (NNP Code)))
         (VP (VBZ Is))
         (NP (NP (DT a) (NN Lot)) (PP (IN Like)
                                      (S (VP (VBG Writing) (NP (NN Prose))))))))
I think the more useful side to this is that the path to understanding a codebase or library is in some ways like understanding a literary work.

It takes some time, rereading a bit. discussing it with other people who are reading it, making the right amount of notes in the margin, consulting the dictionary when you don't understand a term. If it's in a language you don't know, you can translate it slowly, but knowing the basics goes a long way.

I like this way of looking at it because it has more to do with gaining understanding than with promoting some semantic style in regards to documenting

And good code will contain a lot of prose.
By "prose" here I guess you mean comments? Strongly disagree. Most code should be self-documenting through variables, well organized functions, etc. Public APIs should contain lots of documentation, but the actual implementation code should be sparsely commented. Otherwise you now have two "code bases" to maintain.
> By "prose" here I guess you mean comments?

That's a big assumption. I assume the OP meant not quite literally 'prose' but 'good, clear writing' which can certainly be achieved using the built-in keywords of a language combined with well-chosen identifiers.

Public API documentation is very definitely a part of what I was meaning; but most code can also benefit from liberal explanation of how and why certain things are as they are.

Many comments that are written could be better handled by restructuring the code they reside in the midst of, but many code comments can’t be done otherwise, and to attempt to do otherwise would be convoluted.

To take an example of some code I wrote today:

  // Object.values is from ES2017 and Overture uses it; anything that has it will
  // have the other things from ES6 that we need, so we don’t need to add the
  // weight and load time of core-js for them. Browsers that thus need core-js
  // are approximately: IE, Safari≤10.0, iOS≤10.2, Chrome≤53, Firefox≤46,
  // Edge≤13?. No up-to-date browser needs it (for better or for worse).
  if ( !Object.values ) {
      dependencies.O = [ 'core-js' ];
  }
This comment is about explaining why a thing is as it is. Self-documentation by naming tends to only take you as far as what; for a case like this, it would have led to something like this:

  var needCoreJs = !Object.values;
  if ( needCoreJs ) {
      dependencies.O = [ 'core-js' ];
  }
This wouldn’t have explained why core-js is needed—or why I considered Object.values a suitable test.

I tend to draw a distinction between single-line comments which are only sentence fragments, and prose. Prose is beautiful in code.

A part of the illumos codebase was linked to elsewhere in these comments, and I think it satisfies my point also: https://github.com/illumos/illumos-gate/blob/master/usr/src/.... 600 lines of documentation up front is more than I’d typically expect, but it’s well done in this case. After that, there’s liberal application of explanatory comments where they can help.

The rustc borrow checker is another example that I like: https://github.com/rust-lang/rust/tree/master/src/librustc_b.... What is now README.md used to be somewhat shorter (though still long and involved!) and in mod.rs. Look at both files. The documentation here is all about implementation detail; without this extensive prose, I’d say: good luck understanding borrowck. With it, it’s involved, but quite attainable, and you can approach the code without needing excessively deep and intricate understanding of everything about rustc.

Comments can be done badly, but they can also be done really well.

Sure, of course it's needed sometimes. But I was disagreeing with this statement:

> And good code will contain a lot of prose.

I disagree. Good code can also contain no comments. It's not an either/or thing.

I will adjust my position to this: non-trivial good code will contain a lot of prose.
Editors really need to improve their support or comments. Currently, they're even deemphasised in some color schemes (looking at you VSCode).

I built a prototype for an Atom extension a while back that rendered Comment blocks with a markdown parser, inline, right in the editor.

I'm hoping that the VSCode team gets around to implementing the extension hooks necessary to implement this at some point, since I've switched away from Atom.

I was really hoping we would have some common syntax for comments accross all languages. Something like doxygen + markdown, standardized that works for everyone, with a tool in all stdlibs to handle it.
It's bizarre that we're still marking up code with comments like it's 1960. We need some sort of standard to include comments in code like footnotes, margin notes, and so on, that allow us to better explain what is going on without changing the actual readability of the code.

It would require us to move away from strict file-and-text-editing as the end all of programming, which makes many uncomfortable of course. And you get into lock-in issues.

> It's bizarre that we're still marking up code with comments like it's 1960. We need some sort of standard to include comments in code like footnotes, margin notes, and so on, that allow us to better explain what is going on without changing the actual readability of the code.

Actual comments already do that if the editor hides them by default; you don't need different syntax or abandoning pure-text representation, just the right editor features to do what you want.

Don't really understand this article. It just takes the writing process and inserts bits about writing good code into it. If anything, good code should read like Hemmingway and nothing else. And as such, not all good prose will be as dry and concise.
I studied both English and CS in a hybrid program in college. One of the things that appealed to me about writing great code is that it did parallel good writing. The process of writing, especially a paper or a longer thesis relies on logic. There have to be clear bridges, or segues between sometimes disparate thoughts, connecting them.

I find when I am writing code, I try to use the same principles. I don't want anyone to look at two isolated pieces of code and think "what the hell, these don't even belong in the same universe, let alone the in same repo." Whether through comments or just good self-documenting code, I want things to connect in some way.

Jeremy Ashkenas made the connection in a piece of his writing about coffeescript as well. Kind of an ah-ha moment for me.

Really any creative task is the same: writing music, writing software, writing prose.

You have your primitive ideas for some chosen rules, chosen such that the desired product is a valid idea in those rules. Then you combine your ideas through concatenation and composition to get more complex ideas. Sometimes you realize your rules aren't quite right so you change them some. You keep doing this until you have a big idea that fits your definition of a "solution" (whatever that means) and then you're done.

This is an interesting read. The structured approach to writing (code or prose) with intent is surprisingly rare among developers of various skill levels in my experience.

One of the key pieces of advice I give to new recruits is "write a paragraph about your intent, what do you want this code to do?". This, it turns out, is non-intuitive for folks as it requires first understanding what is there (OP notes this well) before jumping into coding. I think the root of this is that you're paid to write code and you want to impress right from the start.

Thus I found it very interesting when a few Q4's ago I was tasked with creating a new recruiting site for engineers ( https://engineering.twitch.tv ) to better understand our culture. The central focus of this site was to be a series of blog posts which highlighted core work that had recently taken place. My job quickly became editor in chief; working with engineers of various levels to understand what they've been doing, what was cool about it, and get them writing about it. Seven blog posts were identified and I made calendar events to check in seven days from then to read drafts... seven days later no drafts existed. As I dug into this it was apparent that they'd all assumed they could jump into the writing prose much like they do code, they all remarked that writing prose is actually really hard. I provided a template of my own pieces over the years and by the following quarter we had three pieces written!

I credit TPW for giving me words to describe this to engineers ( http://tom.preston-werner.com/2010/08/23/readme-driven-devel... ) and my high school English teachers for giving me the love of words!

Paragraph advice is great. I got into the habits of writing a few conversational comment lines at the top of modules and each function as a message from designer-self to implementer-self.

It functions a lot like BDD, or at least my version of it, of keeping me on track for the problem I'm trying to solve at the moment and felt like it led to generally better code quality once I started doing it.

>I credit TPW for giving me words to describe this to engineers ( http://tom.preston-werner.com/2010/08/23/readme-driven-devel.... ) and my high school English teachers for giving me the love of words!

This so much. I find that my strong liberal arts education in high school has made me a much better developer. Things like meter and pacing are quite applicable to writing code, and like you I have only my high school English teachers to thank for that.

So many of the processes around writing (good) code are similar to those around writing (good) prose, it amazes me that non-technical writing and literary analysis aren't more strongly preferred.