Should you always document functions, even if redundant (specifically python)? [closed]
Asked Answered
D

4

9

I try to use function names that are active and descriptive, which I then document with active and descriptive text (!). This generates redundant-looking code.

Simplified (but not so unrealistic) example in python, following numpy docstring style:

def calculate_inverse(matrix):
    """Calculate the inverse of a matrix.

    Parameters
    ----------
    matrix : ndarray
        The matrix to be inverted.

    Returns
    -------
    matrix_inv : ndarray
        The inverse of the matrix.

    """
    matrix_inv = scipy.linalg.inv(matrix)
    return matrix_inv

Specifically for python, I have read PEP-257 and the sphinx/napoleon example numpy and Google style docstrings. I like that I can automatically generate documentation for my functions, but what is the "best practice" for redundant examples like above? Should one simply not document "obvious" classes, functions, etc? The degree of "obviousness" then of course becomes subjective ...

I have in mind open-source, distributed code. Multiple authors suggests that the code itself should be readable (calculate_inverse(A) better than dgetri(A)), but multiple end-users would benefit from sphinx-style documentation.

Devindevina answered 8/10, 2015 at 15:24 Comment(7)
Where you're just delegating to another function, you could use e.g. calculate_inverse.__doc__ = scipy.linalg.inv.__doc__ to give it the same documentation. Who are you writing this documentation for, though?Napper
Note that copying the __doc__ works for tools like sphinx which imports the code. It probably doesn't work for tools like epydoc which just parses the docstrings out of the text.Cantoris
@Napper - Perhaps the example was overly simplified; I don't mean only functions which call other functions. I simply mean any code that does exactly what its name says.Devindevina
@Devindevina note that one person's Ronseal is another's confusion. The name also doesn't necessarily tell you what the function accepts, what it returns and/or might raise, etc., and if you're providing end-user documentation (as the format suggests you are) the code being self-documenting isn't necessarily beneficial.Napper
I think this question is a bit too subjective to be a good fit for SO - ProgrammersSE is a better place to ask questions about programming style.Turnpike
@Turnpike - It's been thoroughly addressed before. See here, here, here, and here. Worth noting that two of those are closed as duplicates and it's worth pursuing the question chain to see the other answers.Howlend
@GlenH7 - thanks for the links, but unfortunately none of them mentions Python specifically. I think it would be interesting to know the answer for the Python ecosystem.Snore
M
6

I've always followed the guideline that the code tells you what it does, the comments are added to explain why it does something.

If you can't read the code, you have no business looking at it, so having (in the extreme):

index += 1   # move to next item

is a total waste of time. So is a comment on a function called calculate_inverse(matrix) which states that it calculates the inverse of the matrix.

Whereas something like:

# Use Pythagoras theorem to find hypotenuse length.
hypo = sqrt (side1 * side1 + side2 * side2)

might be more suitable since it adds the information on where the equation came from, in case you need to investigate it further.

Comments should really be reserved for added information, such as the algorithm you use for calculating the inverse. In this case, since your algorithm is simply handing off the work to scipy, it's totally unnecessary.

If you must have a docstring here for auto-generated documentation, I certainly wouldn't be going beyond the one-liner variant for this very simple case:

"""Return the inverse of a matrix"""
Mab answered 8/10, 2015 at 15:32 Comment(3)
While I agree with this for comments (and so does PEP-8), the situation for docstrings is less clear.Devindevina
@Devindevina -- I think that the point is why? Do you need the docstring for auto-generated documentation (e.g. via sphinx?). Or is it simply for your future self reading the code? If the latter, and the docstring tells you nothing more than a quick glance at the code would tell you, then it's probably not worthwhile. If the former, then you need to start balancing the fact that the user perusing the docs won't see the code with the increased maintenance cost.Cantoris
What @Cantoris said, this is all about who you're writing them for. If you're using an IDE that can use them (e.g. PyCharm) that might be relevant, too.Napper
S
4

"Always"? Definitively not. Comment as little as possible. Comments lie. They always lie, and if they don't, then they will be lying tomorrow. The same applies to many docs.

The only times (imo) that you should be writing comments/documentation for your code is when you are shipping a library to clients/customers or if you're in an open source project. In these cases you should also have a rigorous standard so there is never any ambiguity what should and should not be documented, and how.

In these cases you also need to have an established workflow regarding who is responsible for updating the docs, since they will get out of sync with the code all the time.

So in summary, never ever comment/document if you can help it. If you have to (because of shipping libs/doing open source), do it Properly(tm).

Sandarac answered 8/10, 2015 at 15:32 Comment(0)
O
3

Clear, concise, well written, and properly placed comments are often useful. In your example, however, I think the code stands alone without the comments. It can go both ways. Comments range from needed and excellent to completely useless.

This is an important topic. You should read the chapter on comments in “Clean Code: A Handbook of Agile Software Craftsmanship,” by Robert Martin and others (2008). Chapter 4, “Comments,” starts with this assertion, “Clear and expressive code with few comments is far superior to cluttered and complex code with lots of comments. Rather than spend your time writing the comments that explain the mess you’ve made, spend it cleaning the mess.” The chapter continues with an excellent discussion on comments.

Otocyst answered 8/10, 2015 at 17:47 Comment(1)
Upvoting for a link to the excellent book.Snore
S
3

Yes, you should always document functions.

Many answers write about commenting your code, this is very different. I say about docstrings, which document your interface.

Docstrings are useful, because you can get interactive help in python interpreter. For example,

import math
help(math)

shows you the following help:

    ...
    cos(...)
        cos(x)

        Return the cosine of x (measured in radians).

    cosh(...)
        cosh(x)

        Return the hyperbolic cosine of x.
    ...

Note that even though cos and cosh are very familiar (and exactly repeat functions from C math.h), they are documented. For cos it is stated explicitly that its argument should be in radians. For your example it would be useful to know what a matrix could be. Is it an array of arrays? A tuple of tuples, or an ndarray, as you correctly wrote in its proper documentation? Will a rectangular or zero matrix suit?

Another 'familiar' function is chdir from os, which is documented like this:

    chdir(...)
        chdir(path)

        Change the current working directory to the specified path.

Frankly speaking, not all functions in standard library modules are documented. I found a non-documented method of a class statvfs_result in os:

     |  __reduce__(...)

Maybe it is still a good example of why you should document. I admit that I forgot what reduce does, so I've no idea about this method. More familiar __eq__, __ne__ are still documented in that class (like x.__eq__(y) <==> x==y).

If you don't document your function, the help for your module will look like this:

    calculate_inverse(matrix)

Functions will clump together more, because a docstring takes additional vertical space.

Write a docstring for a person who doesn't see your code. If the function is really simple, the docstring should be simple as well. It will give confidence that the function really is simple, and nothing unexpected will raise from that undocumented function (if they didn't bother to write documentation, are they competent and responsible to produce good code, indeed?)

The spirit of PEPs and other guidelines is that code should be good for all. I'm pretty sure that somebody will once have difficulty with which is obvious for you. I (currently) write from my laptop with not a very large screen, and have only one window in vim, but I write in conformance with PEP 8, which says: "Limiting the required editor window width makes it possible to have several files open side-by-side, and works well when using code review tools that present the two versions in adjacent columns". PEP 257 recommends docstrings which will work well with Emacs' fill-paragraph.

So, I don't know any good example when not to write a docstring is worthy. But, as PEPs and guidelines are only recommendations, you can omit a docstring if your function will not be used by many people, if you won't use it in the future, and if you don't care to write good code (at least there).

Snore answered 18/8, 2019 at 10:42 Comment(4)
P.S. For your particular example I would make a docstring a one-liner, not as you wrote. """"Calculate the inverse of a matrix (ndarray).""" - if you don't add about non-degenerate matrices, "parameters" bloatstrings seem to be too excessive.Snore
If the why and how are obvious for a short function, there's not a need to add a docstring just for the ritual of doing so. Comments generally should be reserved for non-obvious aspects of the code. As well, while I agree it's nice that there's interactive help for Python standard libs, surely not all code must live up to that lofty standard, particularly living code where comments might become stale.Distal
@Distal - a small docstring would be easier than reading the code. I don't use docstrings often (when the name is enough). I agree that I use Python help very rarely. Outdated comments are just wrong, we don't discuss wrong code here. And for "small functions" it's often enough to use library functions / lambdas.Snore
@Distal the author wrote "I have in mind open-source, distributed code. " - so if your code will be used by other people, you must always document that. For me it's hard to imagine a "small function" that will be clear and useful (there will be need for it). It will be more useful with docs.Snore

© 2022 - 2024 — McMap. All rights reserved.