loading...

Self Documenting code isn't

grahamcox82 profile image Graham Cox ・1 min read

I know this is going to be a very controversial article, but I'm going to write it anyway.

Self Documenting code is not a good goal to aim for. Quite the opposite in my opinion.

Comments in code exist for a number of reasons. One of those is to tell what code does, and this is the kind that Self Documenting code seeks to remove. This is not a bad goal, because if the code needs comments to tell you what it does then it's too complicated.

Another form of comment, though, is the one that tells you why code does what it does. This is much more important that what because this is not self evident from the code itself. This can come down to code design decisions, product design decisions, large scale architecture decisions, or a myriad of other reasons.

Yet another form of comment is links to external sources. This can be issue tracker numbers, design documents, or many other things.

Finally, sometimes you really do need to document the big picture of how something works, because the entire algorithm is complex and it's not feasible for everyone to read all of the code to get the big picture overview.

So, whilst striving to make your code clean, obvious and easy to follow, don't go to far in removing all code comments because they have other uses too.

Discussion

markdown guide
 

Developers often equate clean code to self documenting code to no comments. It's neither a zero-sum game, nor are all these things necessary conditions of one another.

As the author of many clean code articles as well as removing comments I think this is an important distinction. Otherwise these topics can become similar to the tabs vs spaces holy war.

I am obviously on the other side of the spectrum. I challenge myself to rework the code so what comments are no longer required. That doesn't mean my code doesn't have comments. There may be an occasional why comment. I just use them sparingly to keep the code my primary medium of communication.

 

And that, in my mind, is absolutely great. My problem is the case where people decide that they've reworked the code so that what style comments are unnecessary, and so they remove all comments - including the why style ones.

 

I stand by this too. How often did we see old comments that lead you off the understanding of the code because it wasn't updated? To me if you have to write a comment saying what it does it's a code smell that needs refactoring. Too much comments is a noise that we all end up ignoring and then collects dust. I only write down a comment saying why some code is written in some way to explain it's unusual design and that it was (hopefully) the best idea at the moment. Only 2 rules of exception here for noisy comments : you write assembly or the comments are used by testing tools for test cases. Rare comments catch the eye.

 

So the big argument for making code "self-documenting" is that comments and documentation can get out of date (and lie) and code cannot. But obviously there is no silver bullet and everything you are saying is also very valid.

Are there any languages or environments that enforce commenting and documentation accuracy in some way? Like a compiler that demanded comments be structured a certain way and enforced that they be manually timestamped for correctness if the code they referenced changed? Obviously no system is perfect, but we rely on other pseudo-accurate measures of correctness like testing itself.

 

Elixir does this, you can check it out at hexdocs.pm/elixir/writing-document...

If you add

iex> MyApp.Hello.world(:john)
      :ok

in your function doc, and add the DocTest to your test suite, then this examples will run as tests. And yes, this comes built in in the language.

I have to say, it's really awesome checking out the docs for any given library and being confident that the code examples will just work.

 

Really slick. Definitely seems like Elixir and Elm are two new languages going the extra mile to solve a lot of problems with functional programming while also making developers happy and sane.

 

Anything with doctests. Unai Esteibar listed Elixir's exunit, and this is also a feature of Rust's rustdoc, and there are less-official ways to add it to other languages.

Like all automated testing systems, though, it's only a partial solution. The best comments I've ever seen tend to be things like this:

From a user's point of view, realm_view_pills_button looks exactly the same as realm_view_pills, and should never have any user-visible differences.

The reason we have both is that realm_view_pills_button is actually a bunch of buttons under the hood, and will completely rebuild the view and hit the network when you switch tab. You should use it if you expect more than five tabs. realm_view_pills, on the other hand, is actually a Bootstrap pills-tabs view under the hood, and allows the user to switch between them more quickly.

You try writing that kind of stuff in a way that gets automatically checked.

 

Clojure does not enforce, but you can comment what the function does like:

(defn give-me-motivation
  "Prints Rocky Balboa motivational phrase"
  []
  (println "Life's not about how hard of a hit you can give... it's about how many you can take, and still keep moving forward."))
 

In the Javascript realm, I think jsDoc is a must !
It's easy to write, help with auto-completion and "bad parameter" check. If your editor knows how to read it (and it should), it catch a lot of spelling mistakes.

 

As Michael noted and Unai exemplified with Elixir, there is this concept of doctests: code snippets with expected outputs to be inserted into documentation, executed and checked. I believe the first and most famous example is Python's doctest module, of which I'm a big fan :) and just got a nice post here in dev.to some days ago. I know there are third-party, somewhat experimental projects for other languages (such as many for JavaScript) but none very popular. Which is a shame, I have to say...

 

Too often a project / class / method becomes way too cluttered with comments when following this idea of "commenting for the sake of commenting". Any developer worth his / her / their salt can follow a trail of code and infer the logic. You don't need comments to tell you "what" the code does. The code will tell you. Code has to update as requirements change. There's nothing beyond the developer's discipline that compels the developer to update the comments, thus they can't be (solely) relied upon.

I view comments in code (other than the Xml Documentation Comments) as a form of an apology to my future self / other developers. This links nicely to your "why" reasoning. I would have very specific reasons why the code is here / like this. Reasons vary from specific sequence of events to hacks to dealing with very niche scenarios encountered and accounted for. Comments in those instances stand out from the almost boilerplate nature of comments.

Comments linking to issue trackers and the like are not proper code comments, and should rather be check-in comments in your source control repository.

I wouldn't say don't write self-documenting code. I would actually say one should strive to do so. But use a few comments in cases where things aren't as obvious to the observer however many days / weeks / months into the future. And you'll find that people would actually pay heed to those comments, because of their rarity :-)

 

I totally agree with what you said. From my point of the view (and it may not be the good one) semantic is the key to everything. We write code for others, if we did for machines it should more look like assembly. The problem I got with comments is that often they are missused (at least in France, thanks to schools which ask to write comments everywhere even for saying it's an int). Most of the time, the code can express itself.
This is what I avoid:

// this function makes coffee
fn something() {
...}

This is what I strive for:

fn make_coffee() {
  ...
}

Same goes for parameters. In few words, don't do with comment what you can do with code. Instead use comment for what code cannot provide. For exemple the why as you said, but also exemple of the use, to explicit the chain of mind comming to this point. For exemple, some tools like rust documentation generator propose even the test as doc, test embedded in comment.

In short, too much comments kill the purpose of it. Like everything, it's a tool that should be use with care.

That's only my opinion and I may be wrong here.

 

Sadly, best practices/patterns/anti-patterns are often applied without understanding the problem they address.

And the solution seems to be similar in most cases: Understand why the best practice/pattern/anti-pattern is one, what the tradeoffs are and what that means for the specific case. Easier said than done, I admit.

In this case, There are some comments that are inherently important (why-comments) and some that are incidentally important (what-comments).
What I would prefer to do:

  • Refactor code into chunks that can be understood by reading names and type signatures.
  • Remove redundant comments
  • Keep the ones that still add value.
 

Self documenting code should be developer's goal for many reasons. We have high level languages (high level because they are close to natural language): let's use them. Use comments where code is not enough (the why point is a good one).
I suggest:

  • write your code at your best
  • ask a colleague for proof reading
  • change your code accordingly
 

I think you’ve hit the nail on the head. I worked on a team that disliked docblock comments (and would fail my code reviews if I included them). Their rationale was that any amount of commenting would allow a developer to become lazy when naming methods and variables, or wouldn’t extract functionality out. While I agreed on some level, the wholesale refusal to merge code that contained any comments at all seemed overkill. All too often I stumble across code that appears to be doing something odd, or a “better” solution is very obvious to me in that moment. In the rare cases that I’m able to discuss those past choices with the original developer, the reasons why are usually illluminating. Being able to communicate why something needs to be done seems like the best middle ground available, and is something that I try to be mindful of when I’m authoring or refactoring code. Good article.

 

There is no silver bullet and it's matter of trade offs like everything else, but generally speaking I think we should strive to write self documenting code.
Besides the obvious advantage of keeping in sync code and docs, self documenting code usually means code which is more modular, testable and reusable.

There are exceptions, for example like you mentioned, comments which explains the why some code does what it does.

There might be cases in which you also need do write comments to explain what the code does, but I really see it as an edge case, as a last resort.

One of those cases is when you write code which deals with microseconds latency. If I realize that adding a new class or new functions would cause a regression, then as a last resort I would write a comment.

 

Agreed - comment why, not necessarily what. (Yes, the line blurs, but the point is for the comment to describe what you intended to happen, on a more human-thought level.) One way of approaching this is the Commenting Showing Intent standard.

 

ASCII art is a good use of comments, e.g. drawing a hidden-line diagram of a cube with the corner and mid-side node numbers since for FEA programs there are at least 3 different conventions. Typically this will be for processing by Doxygen.

 

Code is written for other developers to read. If they can't read and understand code, they should not have the job. Code should always be self documenting by use of variable names, anyway. That should be stressed. Your verbiage does not do that. Of course, a comment can be added when necessary for unusually complex code, but most of the time is not needed.

Most people do not document. Are you going to be a moralist or a computer programmer. To obtain at least some documentation, stress and require self documentation.

 

I have to tell you that when I read the title, I was on the defensive. That was short live when I got to saying comments should tell "Why" not what.

Telling why keeps the next guy from removing/changing code that looks unneeded or unclear to the reason it is there.

Good job!

 

Many often believe that writing comments is an absolute waste of time, and that our only concern should be to have as clean code as possible.

I am a great fan of comments that focus on why or how, instead of what, and here lies the big distinction:

On the one hand, what a piece of code does, should be apparent from the code itself. Too many lines, difficult to understand syntax or poorly named variables are all signs of poorly written code.

On the other hand, why or how this code does a specific thing is a matter of the business logic of the application, and should be documented.

One cannot expect from a developer that opens a file to have a full grasp of the app's business logic.

Keep in mind though, that clean code means clean comments too and also requires extra effort to refactor and keep these comments up-to-date as well. :)

 

Most arguments against comments tend to implicitly assume that code can always also express why, despite the requirement to implement weird business rules being pretty much a/the staple of software development.

 

Although I'm still in university, they really drill us to comment our code in academia (obviously for good reason so we know what we're doing). Three years into this degree though, I find myself using comments only when I'm writing something that's too complex to speak for itself. For example, just recently in my Object Oriented design class, we're told that making variable and function names that are verbose (i.e in Java: IndexOutOfBoundsException; There's really no need to comment on what that exception is. Sure it might be a little longer than what's maybe seen as typical length, but it's to the point!) I find myself frequently looking at this example when I'm writing code.

That being said, I recently had an interview where a potential employer saw some of the code I've wrote in the past and specifically mentioned on my lack of comments, and I told him what I had just explained above. He responded by telling me that it's not about me, it's about the people after me.

I'm not sure, as a community, developers will ever create a universal standard for commenting, but one day we can only hope.

 

Code can replace most "what comments" but it certainly cannot replace the "why comments". In addition, there are some "what comments" that are needed because they explain what a complex stretch of code does.

 

Yes at the "why" question for the most part. So called self-documenting code also has a way of not being self-documenting to anyone except the original author, and even then, maybe only for a few hours. Engineers seems to think their code doesn't stink. Strive for, but accept code will not be perfectly self-documenting to all able bodied engineers that must one day read it. I'd rather risk a little redundancy in a place contextually near the implementation than guess, hunt down ex-employees, or hope the developer captured the essences of their three hour hallway conversation in manner that I'll immediately be able to discover it.

 

100% agree that documenting the "why" is something that you can't always do in code. Also, Ben Halpern makes an excellent point that avoiding documentation rot is an important reason not to document the "what" if you can avoid it. Also, I've used Elixir's commenting extensively and can say that it feels wonderful + natural to use doctests!

This makes me think of DHH's first writing software (well?) video. He spends 15 minutes discussing the rationale for removing a comment and replacing it with a better-named variable, which then becomes a well-named constant, which then gets placed into a more appropriate location in the code. It's an interesting thought experiment to say, for example, "could I simply replace this comment with a helpfully-named variable?".

 

Graham, Yes and no. I do incorporate self documenting code as the structure for the coders to use. There is always overhead stuff that needs to be in place. I encourage the coders to full document code.

 

In copied code snippets I often add a comment of the URL where they came from, such as GitHub or Stack Overflow.

 

Self Documenting code is not a good goal to aim for. Quite the opposite in my opinion.

Self Coding documentation?

Because that is a very interesting idea.

 

I like to document code blocks, for example big bold:
/*

  • here we calculate stuff */

and so on... it helps readibility and quick finding stuff

 

The right three line comment can tell me as much as reading 50 pages of code. The 'no comments' absolutists are a mystery to me.