Sweet Smelling Code

I found this list buried in my notes from long ago. I cleaned it up and updated it, but yeah, I still found wisdom in this advice from my former self.

Moreover, this advice is also to myself. I need to be reminded of these guidelines, as I sometimes disregard them and then need to go back and clean up things afterward.

Name functions after what they return.

Name subroutines after what they do.

Name variables after what they hold.

…not after what they’re used for. Put that in a comment, if needed.

Delete old code. Don’t comment it out or leave comments explaining why it isn’t called anymore. The next person who reads the code will not care why the old code isn’t there, only that the new code is there. (Or if he does care, that’s what source-code control is for.)

Don’t use three different names for the same concept or referent. Especially, don’t do this in the same block of code.

Don’t use mixed code conventions. If you have MyFunc and my_func, one of them should be renamed. This is a safe refactoring. (The only exception is where the names are part of a well-used, public API that follows an obsolete convention, such that you can’t fix it without breaking other people’s code. In that case, hold your nose, and I will, too.)

Keep API documentation out of the code comments. Put them in docstrings or POD or JavaDoc or whatever format is appropriate for your programming ecosystem.

That said, keep private documentation out of sight of the public. In some ecosystems, this means putting them in ordinary comments, not in documentation blocks. But still keep these comments out of the code. Put them where the normal documentation would go, usually right above the symbol being documented.

Keep bug reports out of comments. Put them in a bug-tracking database or TODO list. (However, it’s fine to refer to a published bug report to explain why some code was included.)

Comment why the code is there, not what it does. (The exception is when the code implements a specific, esoteric algorithm that is needed in this case, and the reader needs an overview of how it works.)

If it takes you more than a few minutes to figure out that you needed to add a line of code to address a particular issue, consider leaving a comment for the next reader as to why you added it.

Remember that comments must be maintained. If your comment is not actually needed to understand the code, or if it’s too vague to understand, then you’ve made things worse, not better.

Please put capital letters at the beginning of each sentence, and a period at each’s end.

If you change the parameters or values that a function will accept, update its documentation.

Don’t pack multiple behaviors into a single function by specifying different argument values, then unpack them by switching off of the argument value. Instead, use multiple, distinct functions. If you have a formal parameter called action, you probably want multiple functions. If you’re passing in an argument that changes the behavior of the function, then you want two functions. If you have code of the following form, you probably want two functions:

def my_func(value):
    if value == SOMETHING:
        return x()
        return y()

If you have code that reads if type(thing) == 'Spam' or if isinstance(thing, 'Spam'), then consider whether you actually want two different classes and ought to be using polymorphism.

Prefer imports over mixins.

Prefer mixins over inheritance. (Although in some languages, the difference is just in a naming convention.)

Use as few layers of inheritance as you can, but no fewer.

A method that doesn’t use any of an instance’s data probably doesn’t belong in that class. Put the method into the class of the object that it accesses most prominently.

These notes reflect some other long-ago thoughts on the topic.

This entry was posted in Uncategorized and tagged , . Bookmark the permalink.

Leave a reply