DEV Community

Discussion on: 3 Essential Components of Great Documentation

Collapse
 
eli profile image
Eli Bierman

I know a lot of people agree with you on the comments too. :) I think comments in the code that repeat the code can be a burden to maintain, but I like to basically have a comment for each public function or type/object that briefly explains what you would use it for. Or to describe any non-standard code or design.

Collapse
 
jeyj0 profile image
Jannis Jorre

In my experience I have never come across a case where a comment was necessary. Feel free to give me an example. I like to challenge this thought. There's one exception that I can imagine, that is "unclean" code, that is necessary for performance purposes. But other than that...? Open for a challenge! ;)

Thread Thread
 
mohr023 profile image
Matheus Mohr

I've had the same opinion for a very long time, until I started paying attention to some places where a simple javadoc saves a good amount of unecessary research. Taking 2 quick examples that come to my mind:

  1. Wildfly Swarm, an application server meant for micro-services, in it's prior implementation where you had to create a class to configure your server, had a "swarm.createDefaultDeployment()" method. It is a method that makes absolute sense if you consider that it does exactly that, but... what is a default deployment? What would be this method's name if I explained it's details using it's name?

  2. Jsoup, a library to parse HTML in java, has a method that returns you an element's index considering the element list it's part of. Considering the domain it belongs, the method "elementSiblingIndex()" makes sense on it's own, especially if you're familiar with the terminology used in html handling, but again, how self-explanatory could/should be without getting a paragraph?

I'm always against any kind of extreme measures, which goes for both "no docs in methods" or "document every public method you have". Documentation is meant to make everything clearer and help other developers, and I think that the "Clean code doesn't need docs" idea, although great on it's own, ends up leading to confusing code that, even though made sense when it was created, now leads to "what is a default deployment after all?" kind of question.

And yes, I always love debating this, so let's go haha

Thread Thread
 
jeyj0 profile image
Jannis Jorre

I just want to clarify upfront: I didn't say no docs are necessary. I just said that method-by-method docs are unnecessary, if the naming and code is done well.

Here's my attempt to "fix" the above issues:

  1. I think, while a method like this is very nice to have, it actually does not state it's intent very well. I don't know what it actually does, but a naming like: createDeploymentWithXAndY() would describe it well. If you absolutely need a method as the above, it can simply "proxy" a method named like mine. When looking at the code of createDefaultDeployment(), you then know that it creates a deployment with X and Y. Another perk: you have another way to call it, which will enhance the usability of the interface.
  2. This one is a bit more complicated, as I am not sure what it's supposed to do. The first improvement that came to mind was: getElementIndexAsSibling(). This still doesn't make me happy. So I'd suggest: getElementIndexInContainingElementList(). This name is relatively long, but since it describes very well what it's doing, it fulfills it's main task very well. Some people might add an "s", making it "...ElementsIndex...", But that is fine tuning based on preference, I'd say.

If you have any issues with these solutions I'd be happy to be challenged with those. :)

Thread Thread
 
mohr023 profile image
Matheus Mohr

Indeed, and I agree that method-by-method documentation is makes as much sense as no documentation (I know that searchUserByName searches a user by its name ffs..)

Considering the examples, your solution to the second case is great, can't argue there, but when it comes to the deployment scenario, things get ugly.

Your ideas there lead to a spaghetti code structure that I've seen multiple times and is mainly what led me to question the statement "Clean code makes method-docs unecessary".

Think about what's involved in a deployment and the amount of tweaks you can do. Now let's consider the defaultDeployment option. I'm not saying you CAN'T do exactly what you said, but how many proxy methods with 1-2 lines would you need to create in order to "keep it clean"? And how much better would your code actually be after that? Would that amount of code and methods do a better job for your project than, say, a comment that explains what a single method does? Also, is your increased interface usability actually going to be of any use? Maybe your 3 new methods, all with a very clear signature, are never going to be used again (just like tons of generic code out there). And I say that based on multiple projects I've seen and worked, with exactly that kind of structure, where a proxy method was created for clarification, but 2 weeks later a new method was created, proxying the former, and eventually you end up with a 10 method chain, with 8 of them having less than 3 lines on them, and that's where I ask myself "is this really better than a 1-2 lines doc on a single method with, say, 3 parameters?". So far, my answer is no.

Considering my last 3 months of work (brand new project, from scratch), I've written very few method docs, but when I consider the amount of proxy methods I'd have to create in order to clarify what my 20-30 words doc does (including some parameter options), I can't see how that would be better.

Summing it up, I think that renaming your methods should always be considered ("are the methods name clear on their intentions" was actually one of our PR checklist items), but shouldn't be used as an argument to completely avoid method-specific docs, especially considering complex domain-specific scenarios.

Also wanna mention that indeed, you never actually said "Nobody should document their methods, ever", but your statement on "In my experience I have never come across a case where a comment was necessary." tends to lead less experienced developers to go full no code-docs, and that shouldn't be a thing (trust me, it has happened before with "Clean Code" book).

Thread Thread
 
eli profile image
Eli Bierman • Edited

I think it's really important with documentation (just like with any writing) that you are really clear with who your audience is.

Usually the only people that will see code comments are maintainers of the code, so I think anything that you would want to tell another maintainer that you would work with should be communicated in comments. This is a personal preference that I think is based on not always knowing who would work on my code after me. But if code is successful, hopefully somebody you don't know will try to extend it and not have to ask you questions about it directly.

Comments on public functions or methods are usually for users of the library, who probably don't want to look into the source code to find out what a function does. The function name might be descriptive, but what about the parameters it takes, or the side effects it might have? Strongly typed languages can help somewhat with this, but I think these important details should always be communicated somehow to the user in the documentation.

Users often don't ask questions about things they are confused about, they just move on to something easier to understand.

An example of a code commenting style I strive for can be found in Fossil SCM's implementation of its internal scripting language TH1. It starts with a brief overview of what the file contains. Each function has a comment that answers the question "why does this function exist?" Check out the comment on an internal Buffer type. Here's an example of a comment that you might see as redundant, but another maintainer might see it as saving one precious minute of their time trying to figure out the purpose of that code.

Thread Thread
 
jeyj0 profile image
Jannis Jorre

First of all, sorry for such a long silence, I've been meaning to answer for quite a long time now... But I wanted to do it right and properly.

@mohr023
My solution to the second problem was not ideal, I admit that. Your Answer still makes a wrong assumption. Let me explain what I mean, and my attempt at a better solution.
Your answer relies on the assumption that by proxying some method, you end up creating a culture of proxying. But if everyone actually writes clean code (which, since this is a thought experiment, we can assume) somebody will notice the chain of method proxying and refactor the necessary code to be clean again. Which would probably end up in my next proposed solution. You also mention that increased usability, or at least increased size of the interface is not helpful, or necessary. If this is the case, which it surely can be, I would still use proxying and simple call a private method in such a case. This still makes it instantly clear what the default method does (since the next method call explains it and is the only in the default method's body).
You make a very good point about the many options though. My previously suggested solution does not scale very well, that's true. For such a high-configurable Entity, I like to use the builder-pattern. Using the builder pattern you always start off using a default state, but can customize whatever necessary or desired. I would assume that in the case that event the builder pattern does not scale enough, I'd probably check whether I can somehow split the code further. Otherwise I'm out of ideas as well.

@eli Bierman
Audience is key. That is totally true. I was mostly talking about in-project code, not code that would be used as a library. But if a library is very well written, I usually don't have to look at any documentation but can simply use autocompletion of my IDE to do what I want. Anything else will be faster via Google and StackOverflow or similar anyways, than reading the docs. At least for me. But specific project should have a full documentation either way. While programming languages should also be very intuitive in their naming, they do require docs with a full walk-through. Just to mention one relatively obvious example. There's always edge cases, and in German we have a saying: "Keine Regel ohne Ausnahme", which translates to "No rule without an exception" - which I find is really fitting for situations like this, and everywhere for that matter.

Partly in response to your (@eli Bierman) answer, but also generally as well, I just want to mention that it is highly language dependent, whether and how much documentation is necessary. Some languages work on a higher level, which generally make them more readable for us humans to understand, while others work on a lower level. These languages generally need more docs, as even experienced developers might spend a few seconds figuring out what exactly a method does, even if the naming is ideal.

I actually write a lot of comments. But I also delete most of them. Very rarely does one stay in the code after I have worked on it and somebody has reviewed it. By explaining what a method does in a comment, which feels less restricted than a name, I can optimize the comment to derive a very good name for the method or whatever it is I am trying to name/commented on.

In the end it does come down to preference though. I myself like to rather look at the code and understand what it does than read docs, while for others it might be the other way around. Which is both valid. And if your target audience is bigger, I'd opt for documentation on public methods. Just so that everyone can be happy.

:)

Thread Thread
 
mohr023 profile image
Matheus Mohr

Exactly, I don't think we'll ever come to a single option that fits every case, but I guess that in the end, it's still valid to use comments only as a final resource, you know, not using them as an excuse to leave an ugly code behind.

As you mentioned about preference, I actually prefer when a library I'm using has in-built docs, so that I can quickly ctrl+space and confirm that the input, process and output are what I expected, but that doesn't mean I'm filled with joy when I see a "createDefaultDeployment" method and have to read it's docs piece by piece just to start going.

You make some very good points though, helped me consolidate a few thoughts on comment using and refactoring, thanks for taking your time going through them.

Thread Thread
 
eli profile image
Eli Bierman

This is such an interesting conversation. When I was working primarily with Objective-C in Xcode, I was very comfortable using other code that didn't have any documentation, just a descriptive name like pushVideoFrameToBuffer, and I felt prepared to use it.

Now I usually work in dynamically-typed languages without an IDE, so that definitely biases me towards a small number of concisely named public methods, because it is easier to remember what to type (and for me, easier to read too). Usually those methods are configurable by passing in arguments, like the builder pattern you mentioned @jeyj0 . It's interesting that design patterns are more constant across languages than naming patterns...

My current primary language Elixir lets you read each public method's comment from the interpreter, so it feels comfortable to refer to documentation to answer my questions about a method's usage. If I come across a library in Elixir with minimal documentation and long descriptive method names, it feels uncomfortable to use and I will probably look for a different one. The total opposite of what I expected in Objective-C.

Our code has to be a chameleon and blend into the surroundings. :)