Welcome to 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.
When I produced my list of the Top 10 Pluralsight courses in 2015, this is one of the courses that very narrowly missed the top 10. Learning how to write clean code is one of the most important things that you can do as a developer, and that is what this course is all about.
In addition to watching this course, I can highly recommend Robert Martin’s book Clean Code and also Code Complete by Steve McConnell
As I write this review I am re-watching it for the first time in nearly 3 years. This course was developed after Cory began giving talks on Clean Code, as you can find out more about both the course and his talks on his own site Bit Native.
Cory explains that this course is all about writing code that is easy for our fellow developers to read, maintain and understand. A couple of quotes that inspired Cory and can also inspire you are this one from Donald Knuth:
“Programming is the art of telling another human what one want a computer to do”
and this one from Martin Fowler:
“Any fool can write code that computers understand. Good programmers write code than humans can understand.”
Cory discusses the meanings and takeaways of these quotes.
Why should I care?
Cory explains that writing code is easy but reading code is hard, discusses the negative effects of technical debt, and reminds you that you never want to become a verb!
Cory explains the Clean Code is a foundation for the SOLID principles. There is a course from Steve Smith on the SOLID principles later on in the Getting to Great with C# Learning Path.
The SOLID principles not only help your code to be more, maintainable, they also help your code to be more unit testable. So these principles can be viewed as a foundation for unit testing. I have written a guide Learning Unit Testing and Test Driven Development to help you decide which course(s) to watch to learn those practices.
Cory mentions that Steve Smith’s course on refactoring is yet to be published. This course has been published and it features on my list of Top 10 Pluralsight courses.
There are at least a couple of good Domain Driven Design courses available as well, which is something that builds on your refactoring skills. But first you must learn clean code.
We are Authors
Cory runs through some definitions of authors. As developers, we meet all of these definitions.
We learn that the techniques traditional writers use to make their writing easier to understand translates to what we do as developers. The only difference is the jargon.
Cory House recommends three books. The first two are the ones I recommended above. The 3rd is the Pragmatic Programmer, a book that I still haven’t bought or read, despite it being recommended many, many times.
Three Core Principles
Cory describes the three core principles of clean code. The first one is…
The Right Tool for The Job
All developers have their favorite tools, but a common mistake is for developers to get carried away and use their new toy in situations that aren’t appropriate.
Here Cory illustrates this with a time that he “creatively” used the wrong tool for the job.
Boundaries Matter: Stay Native
Cory discusses the boundaries between HTML, CSS, JS, server side languages (Ruby/C#/Python) and SQL. It explains the need to stay within them, and the price that you pay if you don’t.
I know that Cory has since slightly revised his opinion on the boundary between JS and HTML, a hell of a lot has happened on the client in the past 3 years.
But the key points here remain. Stay within your boundaries, understand where they are and respect them.
Cory gives 7 advantages for staying native.
Here Cory gives three examples of useful technologies that turn evil when they are used beyond the area where they were originally designed to be used for.
There are many more examples that you should be able to think of. Be aware of the area where any particular technology is strong and stay within it. I think that this is an extremely important point.
Signal to Noise Ratio
Cory explains TED as an acronym for signal (good) and tells us that there are many bad practices that contribute to noise.
Don’t Repeat Yourself. The point that I most strongly agree with here is that copy and paste is often a design problem.
Cory discusses some issues that duplication creates.
A study that was done way back in 1979 but remains true today found:
“Understanding the original programmers intent is the most difficult problem” Fjelstad & Hamlen
Cory describes four core things that self-documenting code strives for.
This is an example of dirty code due to bad naming, and then see the clean version.
The only change is an improvement to the naming, but the difference in readability is striking.
This shows a number of examples of bad class names.
I almost laugh out loud, because I have seen almost every one is these bad class names over the years, and you will likely have seen them as well.
Cory provides several guidelines for good class names. We see the first specific reference to one of the SOLID principles here.
Method names should be specific and give the reader a good understanding of what the method does without needing to read all of the program logic within it.
Cory lists many examples of bad names, and some much better ones.
You might wonder whether Cory has completely lost his mind as he recommends putting a rubber duck on your desk so that your explain your code to it.
There are however real benefits in doing this! In my office, there is no rubber duck, but there is a toy frog.
His name is Reginald. Reginald the frog. As well as being interested in all of our coding problems, he serves as a reminder to us to do our stand ups.
Words like And, Or, If in your method names suggest that your method is attempting to do more than one thing.
Some examples of method names and what they should not do as well.
Boolean names should sound like they are asking a true/false question, and we some examples of those that do and don’t here.
Names for opposites should be opposites. Cory discusses some of the almost opposites, and contrasts them with the clarity of good symmetrical naming.
“Which would you say in real life? If logged in equals true? Or if logged in?”
I don’t know about you, but this clip is making me hungry.
It’s also a reminder on how you can simplify your boolean assignments and increase your signal to noise ratio.
This is another good example of the power of reading out code in English. The redundancy jumps out at you, prompting you to eliminate it.
Don’t be anti-negative! Just the name “anti-negative” sounds strange – why not just say “positive”? Why not write conditionals positive?
The ternary operator is another opportunity to increase our signal to noise ratio.
Cory discusses the balance you should strike with the use of the ternary operator: not too much and not too little.
I love this name “Stringly” Typed. Sounds like Strongly Typed, but then wait, it’s NOT Strongly Typed.
Strongly Typed beats Stringly Typed, Cory gives four very good reasons why it is better to use an Enum.
Avoid magic numbers because they make the intent of your code much harder to understand.
Another code smell here. Cory describes some techniques for refactoring the smell away:
- Intermediate Variables
- Encapsulate complex conditionals in a well named method
Although it is usually better to write less rather than more code, the example that Cory gives for encapsulating complex conditionals shows that there are times when it is necessary to write some additional code to clarify intent.
Polymorphism vs Enums
Here we see a dirty switch statement and a cleaner solution using the Template Method pattern.
We see some of the benefits of learning LINQ here.
Something I either completely missed or forgot the first time I watched this course is Cory lists LINQ like implementations available languages other than C#:
- Java: LambdaJ (Java 8+ has it’s own implementation of Lamdas so I guess LambdaJ is obsolete now)
- Python: Pynq
Table Driven Methods
Here we see an example of dirty code that would be much more suited to existing in a database table.
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.
When to Create
Cory discusses many situations where it is appropriate to create a new class:
- New concept
- Low cohesion
- Promote reuse
- Reduce complexity
- Clarify parameters
He explains the benefits of creating a new class in each of these situations
This clip explains the concept of high cohesion, which was first introduced by Tom De Marco in 1979.
Cory contrasts this with some of the magnet classes that were discussed in the Naming module.
As an example we see that a magnet Vehicle class is much better split out into three classes:
Cory stresses that you should start with a good, specific class name, and that usually leads to higher cohesion.
When is a Class too Small?
Signs that a class is too small are:
- Inappropriate intimacy
- Feature Envy
- Too many pieces
Steve Smith’s Refactoring Fundamentals course goes into a lot more detail in these areas.
Cory adds that it is very rare for classes to be too small, so be more concerned about classes that are too big.
Primitive obsession is using primitive types such as strings and integers instead of encapsulating model classes.
Cory explains 4 advantages of creating a new class here.
Also see Mark Seemann’s From Primitive Obsession to Domain Modelling
Principle of Proximity
This is all about making code easy to read from the top of the file downwards, and Cory discusses keeping related actions together.
Collapsed code should read like an outline. This is a tricky concept to grasp initially, so there is a demonstration later in this course.
Cory asks the question “Are comments great, or a code smell?” and gives the answer “Yes there are!”
Necessity and Crutch
Comments are both a necessity and a crutch, and here Cory gives general rules on when and when not to use comments.
Next we look at some types of comments to AVOID.
Redundant comments break the DRY principle because they are a form of repetition
These explain what the code intends to express. Much better if the code itself expresses this.
Apologies and Warnings
Cory describes this as malpractice and he is right. Instead of apologising, fix the issue.
Yay! Kill Your Zombie Code!
Cory discusses the common causes of zombie code: risk aversion, and hoarding mentality.
Next he explains how zombie code damages your signal to noise ratio, creates ambiguity, hinders debugging and refactoring, and adds noise to searches.
KILL YOUR ZOMBIE CODE
Dividers and Brace Trackers
Back in my old VB.NET days when text editors were very primitive and I before LINQ was invented, I used to use brace trackers (end if trackers?) nearly all the time.
Modern text editors and IDEs will now highlight matching opening and closing braces for you, and brace trackers should never be required these days. If you see them, remove them.
Another hideous “best practice” from an earlier era in programming. Ghastly! Thankfully source control is pretty ubiquitous today, and bloated headers are becoming a much rarer sight.
Avoid comments that only describe source control metadata because that’s exactly what source control is for.
I have seen TODO comments plenty of times before, but never seen HACK comments before.
I recommend avoiding TODO comments unless you have specific processes in place around them, e.g. we cannot go live with TODO comments in place. They are only useful if they are very temporary. As Cory says, you should standardize as a team.
In a previous job, there were around 250 TODO comments in the codebase from many years ago. Nobody could remember or tell which if any were still relevant, but nobody wanted to delete them either just in case they were important. I expect that most of them still live on in the codebase today.
Other examples of clean comments that Cory describes are summary comments and documentation that can’t be expressed in code.
In this module, Cory takes a dirty application and refactors it into a clean one using the principles covered earlier in this course.
It is an application for registering conference speakers and Cory registers his cleaning fish for humans course.
We see that the initial dirty code is a fairly realistic and not too exagerrated example.
Some problems with it are:
- Much too much indentation
- High cyclomatic complexity, low maintainability index and high class coupling
- Numerous types of useless comments
- Poorly named variables
- Variable declared to far away from their use
Cory fixes all of these problems and turns the application into something much cleaner.
This final module wraps up the course by examining the key takeaways.
First he discusses when, and when not to refactor. Most importantly you need adequate test coverage to protect yourself against regressions.
Next he relates the Broken Windows article to coding and the lessons that teaches us.
He recommend Code Reviews and/or Pair Programming (two best practices that I strongly agree with)
He points out Robert C. Martin’s “Boy Scout Rule”:
“Always leave the code you’re editing a little better than when you found it.”
And he ends with a summary of all these important points.