Functions should have as few arguments as possible. At most they should have 3.
Output arguments are harder to understand than input arguments - instead
functions should generally just return your desired output
- Flag arguments are bad (e.g. booleans into function). Instead, make two functions
(e.g. - render(bool isSuite) vs. renderForSuite() and renderForSingleTest())
- For functions with two arguments, be wary when there is no 'natural' ordering of the two
inputs - e.g. x,y vs. row,col - its not immediately obvious which form you're using
Try instead to use argument objects:
Circle makeCircle(double x, double y, radius) - Circle makeCircle(Point center, double radius)
- For "monads" (single argument functions), they should have a verb/noun relationship
(do "verb" on argument "noun")
- for dyads (2 argument functions), "keyword encoding" is good, e.g. the arguments
fill in the "keywords" of the function name -
assertExpectedEqualsActual(expected, actual)
- functions should either do something or answer something - not both. e.g.
change the state of an object or return information about the object
- prefer exceptions over error codes - they lead to many nested if statements. However,
try catch blocks are ugly, so extract the body of try/catch blocks to functions of their own.
Error handling is its own thing, hence it should have its own function
- we can negate dijkstra's rule ("every function should have only one entry and exit")
and have break/continue/return/gotos in a function as long as the function is short
and their effects are immediately obvious
Don't repeat yourself!
These rules probably won't be followed when you initially write the function - its like
a rough draft that will need revisions
bj
2019-09-22