On documentation, names, and the like

Just a brief note on the question of clarity in documentation, and in other places, like the selection of names in APIs, whether code requires comments, and that sort of thing:

If someone says “I find this documentation confusing” or “I find this function name confusing”, you cannot relevantly reply “I don’t find it confusing”. Sure, maybe you don’t, but that doesn’t change the fact that the other person does find it confusing.

There are two relevant sorts of replies.

One is “I don’t care.” Now, that’s a fairly rude thing to say most of the time, but it is certainly relevant — if it’s fine to you that the other person (and perhaps even many other people) would find what you wrote or picked confusing, then you can perhaps say “I don’t care” and move on.

Another sort of relevant reply would be “I’m sorry to hear that, what is confusing to you?” and then you try to figure out how to change things so that they don’t find the thing confusing any more.

But, unfortunately, as I hinted, often I see people reply “I don’t find this confusing,” and again, that’s not relevant, any more than it would be relevant to respond to “I’m hungry, I need food” with “I don’t feel hungry”, or to answer “I feel ill, I need medical attention” with “I don’t feel ill”. You can respond “well, so you’re hungry, not my problem whether you’re hungry” or “well, I don’t care that you’re ill, you don’t matter to me”, but it clearly isn’t relevant to the fact that the other person is ill or hungry to note that you are not ill or that you’re not hungry.

Someone not understanding documentation or the choice of a name and the like isn’t something you can fix by telling the other person you don’t share their confusion. You can choose to ignore them, or you can choose to acknowledge them, but you can’t make the problem vanish by saying that you don’t have the same problem. You also can’t reasonably say “no, you do understand this documentation, you’re lying!” though luckily I haven’t seen that response terribly often.

So when someone says they find documentation confusing, you can decide to ignore them, or decide to try to fix things, but you can’t dispute their report of their internal mental state by reporting your mental state is different. Their internal mental state isn’t something that can be altered with a report about your own. You have to accept their report of their own confusion.

9 Likes

This post left me all confused.

2 Likes

I don’t find it confusing.

2 Likes

That’s quite a limited view of the interactions that can occur. You can also try to help them clear their confusion through teaching. That’s especially true for newcomers and w.r.t. documentation conventions (having good tutorials about these to point them early on would of course be much better).

But that of course needs a certain mindset from the person complaining. That is you need someone who is willing to learn something new rather than be stubborn in asking for what he/she is used to. Sadly this mindset is becoming more and more rare, especially in this age of hype driven PL adoption.

I would be curious to know where exactly you think that actually happened.

4 Likes

The purpose of documentation is to teach someone how to use the system. If it does not teach, it is not useful. Good documentation removes the need for someone to be personally tutored through the use of a system.

It is a poor teacher who blames his students, especially when those students learn perfectly well when they have different teachers.

What is missing from this reasoning is the fact that it is difficult to have documentation that satisfies every kind of learner.

Otherwise said any form of documentation needs prerequisites so that further documentation can be communicated clearly and efficiently. You can’t reexplain the world on each documentation bit (this is the reason why I try to hyperlink the documentation of my libraries into the domain they deal with, so that a person without the prerequisites can try to get them through these).

In the API documentation I write I always favor the working OCaml programmer as my target learner and never the OCaml newcomer. Because I think that this is the demographics that will need it the most and in the most efficient way.

Newcomers to OCaml should learn through other teaching material — which in the best world would include the prerequisites that allows them to quickly become the working OCaml programmer I’m targeting.

I’m not blaming the student. I’m blaming the person who does not want to learn but only get what he/she already knows. That is by definition not a student ;–)

4 Likes

It isn’t very difficult at all, especially in software systems. One tries to make sure that it is easy to skip introductory material when looking at reference material and one is largely done.

I’ve seen the excuse that “well, an experienced user of the system would be slowed down by seeing that explanation”, but usually this is a false economy, as experienced people can skip to more or less just what they want. (We live in the modern world, and people typically use search and hyperlinks to read things, they don’t read them every time on paper.) See also below my comments about Unix man pages.

I think as evidence for this we can see that the documentation for a number of modern systems meets these criteria, and is clean, clear, and easy to read. The fact that others succeed at it means it is not impossible to do.

A happy medium exists between this and certain “documentation” I’ve seen for functions in certain libraries that is barely more than the type signature and a single sentence that explains neither the use nor the motivation for the existence of a function.

Often having just three sentences, or even two, solves such a problem, but I’m aware some people insist that they’re “attempting to cultivate a certain mindset in the reader” and other such rot and outright refuse to have their documentation explain things like motivation or purpose. They fight pitched battles to avoid having a function documented with two or three sentences instead of one! This is not “re-explaining the world”, this is just simple courtesy to your users. Often even an extra phrase here and there will save people time when trying to figure out how something works.

At one time, I was a newcomer, and I found the OCaml documentation opaque. I am now someone who has been using the language quite steadily for a year, and I still sometimes find the documentation opaque, which is why I often try to help fix it.

Of course, perhaps I’m a moron. People have called me that many times, and they are probably right a lot of the time. I’m not as young as I once was, my memory has become poor, I often miss obvious things, and I’m clearly not in the league of many people I know. Regardless, though, I’m more representative of what working OCaml programmers will be like if the language gets a lot more users than the best of the best programmers in the world are. (Perhaps you might see that as a reason to prevent entry of more people into the ecosystem?)

Documentation is not usually viewed as a contest to see how compact you can make a description that is still technically accurate, or as an adversarial game in which one attempts to avoid giving too much away. It is a way to assist people who are trying to get their work done. If you are cruel to the users of your system, if you spend your time trying to remove all redundancy and ignore the interests of the people trying to read the documents, if you make it too hard for someone who is reading to figure out what something does, they will respond in kind by walking away. Now, perhaps you want them to walk away, maybe you feel your library would be contaminated by having too many people like me using it, but you should be aware that is a potential consequence.

I’ve given examples from other programming languages in previous threads on documentation. I’ll pick another domain today. I’m a long time user of Unix — 35 years or so — and one of the nice things about most Unix variants is that the man pages for every single system call and library call describe those calls in substantial detail. They explain the motivation for the call, they explain what happens when the parameters are edge cases, they give hints and examples.

Even the most compact such man page, with only a few sentences, tries hard to cover all the bases and explain both motivation and use. See, for example, the following man pages from NetBSD:

The NetBSD memcpy documentation
The NetBSD read system call documentation
The NetBSD uvm kernel subsystem documentation

Note that the one there, for UVM, is the documentation of an internal kernel interface. Those get manual pages too. The creators of NetBSD take care to carefully and fully explain all such interfaces, even though only very skilled programmers typically work on the kernel. This makes life easier for everyone — new kernel programmers don’t need to constantly ask old timers (who may not even be around any more) how things work, old timers have good reference material to work from, and people even avoid problems like forgetting what invariants are supposed to be maintained and the like because they’re documented instead of being part of an unwritten lore.

Note this is in documentation that is intended for working users of the system, and was written by quite expert people for use by others. It is not introductory material. In spite of having worked with many great kernel programmers and systems programmers, I’ve never seen a single one complain that the documentation was too verbose, even though it is substantially longer than the documentation some people believe is sufficient, say when documenting OCaml libraries.

BTW, I’ve been using menhir a lot in recent months, and in spite of the fact that it has a long and very complete manual, I have never thought to myself “if only this manual was shorter! It’s too hard to find things!” — instead, I’ve been glad every time I’ve been puzzled that the manual almost always explains things if I re-check it. Perhaps you are upset that the manual is too complete, of course.

Your comment speaks for itself.

This is getting kind of heated, so let me add to the fire a little with my own insight.

The reason you can’t dismiss a question about naming or documentation is that if you get one such question, you’re really getting a sample representing hundreds/thousands of people with the same question. Asking for that person to educate him/herself is fine, but you can’t do that for all the other people who will come and read the docs with that same background. The key is to understand that the one sample is precious because you’re getting useful information from it, and this information will allow you to reduce friction and allow more people to work more easily with your code.

To dismiss the attitude of the feedback-giver, you’d have to ascertain that you’re somehow sampling someone who really isn’t representative of the distribution of people you may want to inform. For example, if someone criticizes a comment and you learn that they don’t even know OCaml and are instead purely python programmers, it’s fair to say that they’re not representative and should probably go learn OCaml basics first. But that’s going to be extremely unlikely – normally people who are motivated enough to give feedback are people who want to understand something relevant to them.

2 Likes

@perry While it’s fine to express your reasoning on a subject, the constant passive (and sometimes not so passive) aggressive tone undercuts the weight of what you’re expressing. It also hurts the community as a whole by setting an uninviting tone. Please keep things on topic and civil.

@dbuenzli’s documentation is some of the best I’ve read, in OCaml or otherwise. Yes, it reads like a technical manual quite often. I tend to think that’s a good thing for technical reference documentation. His work also has some amazing introductory material to help set expectations around the intent of the associated API documentation.

Beginners to the language, ecosystem and individual libraries need help to get to the point where these things are digestible. That doesn’t require disparaging existing material or authors.

1 Like

We were not discussing him, and I would never discuss particular individuals in such circumstances as it is both rude and unnecessary. I don’t think I mentioned his name anywhere. But as long as we’re mentioning things he has written, we can use one of his creations as an example. Lets look at some documentation taken from his recent pull request for a Bool stdlib module. This is from the .mli file:

val negate : ('a -> bool) -> ('a -> bool)
(** [negate p v] is [not (p v)]. *)

So the proposed documentation for negate is apparently, in its entirety:

negate p v is not (p v).

Now, perhaps this is some of the best documentation you’ve ever read, but when I first encountered it, I couldn’t make heads or tails of it for almost two minutes. I then read the source, thought for a little while, and realized this was a function intended for people mapping a boolean function over something who wanted to invert the direction of the function. BTW, if I have figured this out wrong, it’s yet more evidence of a problem, but never mind that, I don’t claim to be smart.

Anyway, to me, the purpose of documentation is not to create a mental puzzle for the reader, and that is also not the purpose of the name chosen for a function in an API. Documentation, and names, are there to make it clear and easy to a reader what they are looking at, so they should help the reader along by making intent clear. Simply changing the above to:

negate takes a boolean-valued function and returns a negated version of the function. Thus, negate pred val returns not (pred val). For example, this could be used to reverse the sense of a function passed to List.find or List.filter.

would have made the situation much better, at the minor expense of turning one sentence to three somewhat longer ones. Picking another name for the function negate would also help.

It might be argued by some that this set of three sentences renders the documentation unreadably long to an expert, but I don’t think that’s the case.

Note again, I’m not a beginner, and yet, the intent here was not obvious to me from [negate p v] is [not (p v)]. Perhaps it is obvious to you, but as I’ve noted, my subjective experience is not subject to debate, though feel free to note that a smarter person would not have my trouble. That said most users will not be smarter than me.

So, to me, that extraordinarily terse explanation was indigestible after a year of working with OCaml. I don’t think I’m a beginner any more.

I have not mentioned the person of anyone during this discussion, and would never do so, for precisely the reason that discussing the person of particular individuals is not necessary in a discussion like this and is impolite.

1 Like

BTW, I should emphasize once again that, in many cases, simply adding a sentence or two, or changing a couple of words, can dramatically improve the readability of the documentation for a function.

Furthermore, picking a slightly better name for a function often makes the difference between a reader immediately understanding the intent while going through a piece of code and being stopped cold until they think things through, even if they have encountered the function before. Human psychology is weird that way. (This is one reason why taking great care with the names of functions in widely used libraries can be of so much help to people reading code later on.) I’m happy to show examples of this phenomenon, btw.

I am not suggesting that people write dissertations about simple functions intended to do things like returning inverses of boolean functions. I’m merely suggesting that if someone comes to you and says “I find this documentation confusing”, your response should not be “well, I don’t, so there’s something wrong with you, a reasonable person would put in the effort to figure it out”, it should probably be “what small change can I make so that the understanding of the hundreds or thousands of people who will read this will be a bit better.” A word or two, or sometimes a sentence or two, can work wonders.

Similarly, I’m not suggesting that people spend weeks debating the name of single API calls, but if something isn’t very obvious from its name, there is something to be said for taking a bit of time and considering alternatives.

I don’t think this is anything to do with intelligence.

There are good reasons to prefer @dbuenzli’s proposed documentation style for negate (which I do, too), and it’s worth understanding what they are before trying to change things.

1 Like

According to that Wikipedia article, “Chesterton’s fence is the principle that reforms should not be made until the reasoning behind the existing state of affairs is understood.”

I think the reason for the existing state of affairs is quite obvious. It also will harm absolutely nothing to have three clear sentences in place of “[negate p v] is [not (p v)]”, and having that as the documentation is in itself a problem. This isn’t like changing the structure of a political system — better documentation clearly is at worst harmless.

Note that I didn’t want to discuss this particular function’s documentation but the problem in general. (I also don’t want to discuss personalities or particular people — that’s neither productive or polite.)

OCaml is a wonderful language with excellent performance, wonderful tools, an amazing type system, and a smart community. I believe, strongly, that one of the reasons other languages have gotten much more popular isn’t that people dislike quality or are incapable of recognizing it, but because it’s possible for very ordinary programmers to learn them because of the difference in the quality of the documentation.

And again, you can tell other people that you don’t care if they are capable of using your documentation, but you can’t tell them that their subjective experience of finding it confusing is invalid. It is no more up to you whether they find it confusing than it is up to you whether they’re hungry or have a pain in their abdomen. As @bluddy correctly observed, it is also valuable to pay attention to complaints about specific documentation problems, because only one person in hundreds will take the time to complain when confused.

Oh, and…

So if I wasn’t confused because I’m dumb, and I wasn’t confused because I’m a true newcomer to the language, why do you think I found that documentation confusing, and why do you think my subjective experience of finding it confusing should be ignored in favor of maintaining the status quo?

I will note that the position that documentation like that should be actively protected from being improved but is supposed to be informative to some group of people is equivalent to the position that I am not one of those people — it’s the claim that somehow, the documentation isn’t intended for me but for some other type of person. So, what distinguishes me from that other type of person? If the distinction isn’t that I’m too dumb to be using the language compared to the intended audience, and the distinction isn’t that I’m too unfamiliar with the language compared to the intended audience, what exactly is different about me such that such that I’m not the intended audience and this documentation is fine for those who are intended to read it?

I will repeat: there seems to be a somewhat strange but apparently widely held belief that one can judge documentation based solely on one’s own experience of it as the author and not on the experience of others. If one’s goal is to have documentation be informative to other people, then this belief is invalid. You can tell someone you don’t care about their opinion, but you can’t tell someone you actually intend to learn from your documentation that they’re somehow in the wrong if they find it difficult to read.

I’m not sure. I have the impression that you don’t understand why some people prefer the documentation for negate as it is, since you haven’t mentioned any of the reasons they prefer it that way. Trying to change people’s minds about something without showing that you understand their existing position isn’t likely to work.

Here’s a suggestion: write the strongest argument you can in favour of the existing documentation style and then, starting from that point, explain why your proposed change is an improvement.

1 Like

I’m a little bit confused by this thread. :wink:

If I can understand the position in the first post of @perry, I do not see the problem with the only example given : the negate function. The documentation is just the translation in english of the corresponding OCaml code.

When I read [negate p v] is [not (p v)], I literally translate this to let negate p v = not (p v). And to be honest, I’m confused that this is not obvious to an OCaml programmer. Where is the problem?

Here the verb to be is used to express the identity between two things, as is the sentence “Elisabeth II is the Queen of the United Kingdom”. And in the particular case of this OCaml documentation, there is identity by definition.

There is also another meaning of the verb to be, for instance in the sentence “Elizabeth II is a woman”, which in this case is translated by a type annotation “Elizabeth II : woman”.

Example : val l : int list is translated in english to "the value l is an int list`.

Concerning the name, I’m not an english native speaker (I’m french), but for such a function I’ll use the verb “nier”, and if I ask Google to translate I get: deny, negate or gainsay. In other words, Bool.negate thesis is the antithesis.

1 Like

I don’t think I ever dismissed the attitude of a feedback (except maybe if needlessly rude). My answer to this thread was precisely to note that there were other ways to deal with feedback than the false dichotomy – fix it or ignore it – the OP suggested.

Since it seems my answers give the impressions that I do not like to get feedback or that I’m a dismissive person, I would like to say it explicitely: I do enjoy getting the feedback of OCaml newcomers and my library users as they are always informative of certain defects or misunderstandings to be cleared up.

However I treat this feedback exactly the same way I treat my clients, I listen to them carefully to understand their problem, but I rarely end up doing what they tell me they want or need in order to solve their problem — nothing new here that’s basic UX design.

Taking the example at hand I understand that a newcomer like the OP finds declarative doc strings confusing, should I then rush to change all the doc strings of my libraries to satisfy the wishes of the newcomer ? I don’t think so but that doesn’t mean that there is no problem and nothing to do. My take away point is that it would be good to have a document explaining their meaning, purpose, value and relationship to equational reasoning.

Now I’m off this discussion, happy documentation reading !

2 Likes

There are two distinct problems with your statement.

First, at a higher level, it is obvious that merely because you do not see a problem doesn’t mean you can dismiss claims by others that they found something incomprehensible. It is sufficient that someone tells you they didn’t understand something for you to know that at least some subset of the readers do not find the documentation adequate. Saying “I do not see the problem with this documentation” is a claim that should immediately raise a red flag when one is engaging in writing documentation — abstract reasoning about why people should find the documentation perfectly adequate doesn’t count, only the subjective experience of the confused people counts. If people are confused, that’s enough to know a problem exists, and your belief that they should not be confused does not fix their confusion.

I will repeat that I found the documentation confusing, so we know at least one person found it inadequate to the purpose.

Second, on a lower level (and almost less important level), the concrete mistake in your claim is obvious. If something that was just the translation into English of the code was adequate documentation, without any explanation of motivation for the code and without any explanation of the results of executing the code, then there would be no need for documentation, one could simply show the source code and be done with it. The fact that most people consider source to be inadequate as documentation should indicate that merely stating the content of the code is also probably not adequate as documentation.

However, even if we could not identify this obvious cause for the inadequacy, the mere existence of people who are confused would be sufficient to tell us some inadequacy existed even if we ourselves thought the document was comprehensible.

You have attempted, as I mentioned from the beginning of this thread, to explain why someone else should not be confused on the basis that you find the content sufficient, which is again like trying to explain that someone else’s leg isn’t broken because your own leg is intact, or trying to explain that someone else isn’t hungry because you feel full. The reasoning chain is misguided a priori.

You cannot dismiss someone else’s confusion on the basis that you are not confused, and I will state, once again, and unambiguously, that I found that particular piece of documentation confusing.

You can decide to explicitly ignore their confusion on the basis that you don’t care about it, or you can decide to change the documentation to eliminate their confusion, but you cannot claim they are not confused on the basis that they should somehow not be. Thus, if the goal of documentation is to repair confusion, no amount of explaining to someone that the documentation is already adequate because they “shouldn’t” be confused will fix it.

BTW, imagine the translation of this attitude into some different areas of human experience:

  1. The likely revenue of a restauranteur who explains to his customers that they logically should be enjoying their food, even though they dislike the taste, because he enjoys it.
  2. The future of the marriage of a person who explains to their spouse that they should enjoy an activity that the spouse loathes but that they like, and who therefore insists on imposing it upon them no matter how much the spouse protests.
  3. The career prospects of an author who insists that even though people dislike reading his books, logically they should enjoy them, and thus they should buy his works anyway even though they do not want to.

There is a central problem involved in the insistence that you can rationally convince others not to find a piece of writing confusing.

It is, sadly, based in a very common human failing. People have preferences and believe the world should share those preferences. “I like this thing, so everyone should want things to be this way!” is the underlying thinking. People naturally would prefer a world that catered to their own needs, and do not like altering their behavior to suit other people’s needs.

However, no matter how much I might want others to find my writing clear and easy to understand, no matter how much I might dislike having to cater to the needs of others rather than my own, it is not possible to persuade others that they already find the writing comprehensible simply because I prefer writing something in a particular manner. If they do not understand things that are written in that style, no matter how much I might prefer that style and have wondrous logical arguments for its beauty and superiority, my arguments will not be able to persuade them that they understand something written that way if they do not in fact understand it.

I am thus forced by the cruelty of the world to sacrifice my own preferred style if I wish to achieve the higher goal of having others understand what I wrote. If, of course, I don’t care if they understand, I am free to write any way I prefer.

I think you have misunderstood my comment. I have perfectly understood that you did not understand the documentation at first sight, and I do not claim that everybody should understand a thing only because I understand it. I just try to explain you (an so, you can’t say I don’t take care of your problem) why @dbuenzli wrote the doc this way.

BTW, I will now take your documentation proposal:

No, no, and triple no ! negate returns nothing. Please don’t use the verb return to document such a function. I mean, you can do what you want with your own libraries but I’m pretty sure you will never convince the core team to use it in the standard library documentation. negate pred val do not return not (ped val), but it is not (pred val), that’s what the documentation claims, and that’s also what I tried to explain in my comment.

  • Elizabet II is the Queen of United Kingdom
  • The Queen of United Kingdom has a son named Charles.

hence, I can rewrite the second sentence in “Elizabeth II has a son named Charles” without changing its meaning, because it is the same person (the same entity, if you prefer). Would you really take seriously someone who try to explain you that Elizabeth II returns the Queen of United Kingdom? :thinking:

In other words, I gave you the answer that @yallop asked you: “it’s worth understanding what they are before trying to change things”.

It may surely be useful to some users to add examples of use or the context where we may want to use this function (as you did with List.filter and List.find), but I repeat: please, do not substitute the verb to be by the verb return.

Daniel has right when he said:

This document would certainly be useful for newcomers and people too used to imperative programming, but these informations do not have their place in an API documentation.