Several tricks and heuristics that I apply to write easy to understand functions keep coming up when I look at other people their code. This post outlines the second key principle. The first principle is Minimize State. Following posts will contain specific tips and tricks, often building on these two principles.
Do One Thing
Often functions become less readable because they are doing multiple things. If your function Foo needs to do tasks A, B and C, then create a function for each of the tasks and call those from Foo.
Having small functions is OK. Having just 3 calls to other functions in your function is OK. Don’t be afraid of “too simple” code or of this style making things harder to follow (it does not (unless you are splitting things up stupidly)). And don’t be afraid of performance. In most programs the amount of function calls have effectively 0 impact on performance. There are exceptions, though unless you know you are dealing with one of these, don’t mash things together for performance reasons.
One Level of Abstraction
Doing one thing includes dealing with a single level of abstraction. For instance, suppose you have a function in which in some cases a message needs to be logged to the file system.
1 2 3 4 5 |
function doThing() { if (condition) { low_level_write_api_call('write-mode', $this->somePath, 'Some error message'); } } |
Here the details of how the error message is logged are on a lower level of abstraction than the rest of the function. This makes it harder to tell what the function is actually doing, because details that don’t matter on the higher level of abstraction clutter the high level logic. These details should be in their own function.
1 2 3 4 5 6 7 8 9 10 |
function doThing() { if (condition) { $this->log('Some error message'); } } private function log(string $message) { low_level_write_api_call('write-mode', $this->somePath, $message); } |
3 thoughts on “Readable Functions: Do One Thing”