Function Arguments – Clean Code
As an extension to the last post on functions, below are some points about function arguments.
- Function arguments take a lot of conceptual power while reading and understanding code.
- They should be at the same level of abstraction as the function name. For e.g. String createTestableHtml(PageData pageData). Reading this function signature forces you to know the detail which isn’t particular important at that point in time.
- The ideal number of arguments for a function is zero (niladic). Next comes one (monadic), followed closely by two (dyadic). Three arguments (triadic) should be avoided where possible. More than three (polyadic) requires very special justification—and then shouldn’t be used anyway.
- Arguments are most naturally interpreted as inputs to a function.
- Output arguments should be avoided. If your function must change the state of something, have it change the state of its owning object
Single Argument Functions
Commons reasons to have such functions
- Asking a question about that argument, as in boolean fileExists(“MyFile”).
- Operating on that argument, transforming it into something else and returning it. For e.g. InputStream fileOpen(“MyFile”) transforms a file name String into an InputStream return value.
- Event for e.g. void passwordAttemptFailedNtimes(int attempts).
In such single argument functions, you should choose good function names such that the function and the argument form a verb/noun pair. e.g. writeField(name) which tells us that the “name” thing is a “field”.
Passing a boolean into a function is a truly terrible practice. It clearly proclaims that the function does more then one thing. A solution would be to create two separate functions.
When groups of variables are passed together, they are likely to be part of a concept that deserves a name of its own. It’s not bad to create new objects.
Ward Cunningham, inventor of Wiki, inventor of Fit, coinventor of eXtreme Programming. Motive force behind Design Patterns. Smalltalk and OO thought leader. The godfather of all those who care about code once said :
“You know you are working on clean code when each routine you read turns out to be pretty much what you expected.”
Half the battle to achieving that principle is choosing good names for small functions that do one thing.
Don’t be afraid to spend time choosing a name. It is not at all uncommon that hunting for a good name results in a favorable restructuring of the code.
Error Handling is one thing
If the keyword try exists in a function, it should be the very first word in the function and that there should be nothing after the catch/finally blocks.
One cannot write functions which follow all the clean code rules from the start. You need to refactor and refine it until it reads the way you want it to read.
Master programmers think of systems as stories to be told rather than programs to be written. If you follow the rules herein, your functions will be short, well named, and nicely organized. But never forget that your real goal is to tell the story of the system, and that the functions you write need to fit cleanly together into a clear and precise language to help you with that telling.