To have no documentation at all and to think that IntelliSense is all you need to understand the finest and subtlest details of what each class/method does, is illusory.
There are of course some very simple cases — for example, if a List
class has a Count
property, what could that property possibly return except the obvious. But a very significant amount of methods have corner-cases or behavioural properties that need to be documented for the benefit of the API user.
Let’s take an example:
public static TabPage ContainingTabPage(this Control control);
Do you think it’s obvious what the method does? Well, its intention is certainly clear, but... what if the control is not contained in any TabPage
? Does it return null
or does it throw? What if it’s in multiple nested TabPages? — Fortunately, the documentation answers these questions: If this control is located within a TabPage, returns the first TabPage found by iterating recursively through its parents. Otherwise returns null. What would the method need to be called to make this documentation redundant? InnermostContainingTabPageOrNull()
? That does not really contribute to code readability.
Or take something like this:
/// <summary>
/// Returns the smaller of the three IComparable values. If two values are
/// equal, returns the earlier one.
/// </summary>
public static T Min<T>(T val1, T val2, T val3) where T : IComparable<T>;
In the majority of cases the second sentence in the documentation is irrelevant but does no harm. In the few cases where it does matter, it can save you a lot of time — if you don’t have the source code, you’d have to find the answer by experiment. In this case the experiment is easy, but imagine the method is about concurrency and you’re wondering about its thread safety or race conditions...
Another example: take an XML serializer. That’s simple, you might think, just have a XElement Serialize<T>(T)
and a T Deserialize<T>(XElement)
method and it’s totally clear what they do! Uhm, well, except... how does it serialize dictionaries? How does it handle interfaces? Does it preserve object identity? Does it cope with cyclic references without going into infinite loops? How does it behave when faced with the challenge of serializing delegates, native resources, remoting proxies? What exception types does it throw in which situations?
Only having two methods does not mean the process of serializing data is simple. Consequently, our custom XML serializer has a big thumping documentation block on the class which describes, in detail, all its features and all its limitations; what kinds of classes it can serialize, what assumptions it makes and what exceptions it throws; the custom attributes you can use to modify its behaviour; and, perhaps most importantly, what the fundamental design ideas behind it are and what use-cases it intends to cover (so that if your intended use-case is sufficiently different, you know you may be better off choosing a different serializer).
Now, with all that said, I think there is something to be said about quality vs. quantity. A lot of hobby-made libraries come with extra HTML files or other documents containing heaps of low-quality documentation when they could be more useful with less but better documentation. Good documentation needs to fulfill two important functions:
What does this class/method do? — This one is easy, just document each class/method.
How do I do X? — This one is hard. It may not be obvious to the API user what the method or class they need is called. To cover such cases, it often helps if the documentation for one method links to another (e.g. “if you are trying to do X, prefer to use M”) or the documentation for a class mentions all of the other classes with which it interacts (e.g. our above-mentioned XML serializer lists all the custom attributes that influence it). Some small code examples for common scenarios can be helpful, but only if they’re not trivially obvious.
There must be a small set of places to look for the answer. If the API user feels that they have to read pages after pages of irrelevant stuff only to ascertain that the answer they’re looking for isn’t in it, then the documentation is too badly structured and the API user may as well not bother reading it if it’s easier and faster to just ask on StackOverflow.
So, in summary: No, extensive documentation is not a code smell at all. Certainly you can’t improve the code simply by removing the documentation. But it may be a documentation smell. There is good documentation and there is bad documentation, and in some cases bad documentation may be improved by trimming it. Adding more documentation can make the documentation worse. Quality of documentation is not measured by number of words any more than code quality is measured by lines of code.
"Documentation is like sex. When its good, its very very good, when its bad, its better than nothing."