Welcome to Part 5 of this review of the Pluralsight course Clean Code: Writing Code for Humans by Cory House.
Cory is a Microsoft MVP in C#, founder of OutlierDeveloper.com, avid tech reader, and speaker. He believes in clean code, pragmatic development, and responsive native UIs.
Here are the links to each part in this series:
Part 1 – Writing Code For Humans
Part 2 – Clean Code Principles
Part 4 – Clean Code Conditionals
In this episode, we look at some techniques for keeping our functions clean.
When to Create A Function
Cory gives several reasons for creating a new function. The first one is to…
We return to the DRY principle, and Cory explains that less is often more.
Ironically this is one clip that could have been eliminated as we’ve already covered this earlier in the course, however it’s important to understand that this principle applies to functions as well as other forms of code.
Excessive Indentation Overview
Cory introduces us to arrow code, which makes me shudder as it reminds me of some hideous code I wrote many years ago.
Cory refers to a study by Chomsky and Weinberg:
“Comprehension decreases beyond three levels of nested ‘if’ blocks”
The next three clips discuss refactoring solutions to this problem. For a more in depth guide to refactoring, scroll down to number 6 in my list of Top 10 Pluralsight courses.
Also, if there is dirty code in your organization’s applications, consider starting a Refactoring Forum.
Cory likens this practice to an author using footnotes and shows an example from Wikipedia.
Extract Method is one of the most common and valuable refactorings.
This clip references a great piece of advice from the book Code Complete:
“Use a return when it enhances readability… In certain routines, once you know the answer…not returning immediately means that you have to write more code.”- Steve McConnell
Cory explains the concept of guard clauses here, and where they are useful.
I sometimes think of this as “offensive coding” as opposed “defensive coding”.
Aside from the readability issue, I have seen a lot of code that tries to prevent the program from crashing at all costs and in the process makes a set of database or other state changes before the true coding error comes into light via an exception in a part of the application far away from the actual coding error.
It is important to learn defensive coding, but it is also important to know when you should fail fast.
Make sure that you also watch the exceptions clip in the Functions module to understand this point.
We see the complex conditionals example again, so that we can appreciate that the clean version of it better conveys the intent of the code. This more than justifies the extra code required here.
Do One Thing
Cory explains that there are many advantages of functions only doing one thing:
- Aids the reader
- Promotes reuse
- Eases naming and testing
- Avoids side-effects
The lifetime of a mayfly is extremely short: only a few hours, and many live for less than an hour!
Cory explains that we should strive for only 0 to 2 parameters in each function.
Also covered here is some good advice on watching out for flag arguments.
What’s Too Long?
Here Cory describes 5 signs that a function has grown too long:
- Whitespace / Comments
- Naming issues
- Multiple conditionals
- Hard to digest
This clip also refers to the book Clean Code, and the specific advice that functions should be rarely be more than 20 lines of code and hardly ever more than 100 lines of code, and have no more than 3 parameters.
Cory also refers to the Linux style guide and simplifies it to an important maxim.
I think that this is very smart thinking because I have seen a few examples of long but very simple functions that are much more readable than they would be if there would be if they were broken out into multiple functions just to satisfy some arbitrary or inflexible coding standard on the maximum length of a function.
There are three kinds of exceptions:
Cory explains the you should process these kinds of exceptions in different ways, and gives the important advice not to catch exceptions that you cannot process intelligently.