Clean Code: Writing Code for Humans

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

Cory’s course is the third course in the Getting to Great with C# Learning Path, but developers familiar with any C-like language (VB.NET, Java, JavaScript, Objective C etc.) should be able to follow along without any problem.

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.

Introduction

Introduction

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!

The Foundation

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.

Resources

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.

Principles

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.

Abbreviations

Booleans

Boolean names should sound like they are asking a true/false question, and we some examples of those that do and don’t here.

Symmetry

Names for opposites should be opposites. Cory discusses some of the almost opposites, and contrasts them with the clarity of good symmetrical naming.

Conditionals

Boolean Comparisons

“Which would you say in real life? If logged in equals true? Or if logged in?”

Boolean Assignments

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.

Positive Conditionals

Don’t be anti-negative! Just the name “anti-negative” sounds strange – why not just say “positive”? Why not write conditionals positive?

Ternary Elegance

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.

Stringly Typed

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.

Magic Numbers

Avoid magic numbers because they make the intent of your code much harder to understand.

Complex Conditionals

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.

Table Driven Methods

Here we see an example of dirty code that would be much more suited to existing in a database table.

Functions

When to Create A Function

Cory gives several reasons for creating a new function. The first one is to…

Avoid Duplication

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.

Extract Method

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.

Return Early

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

Fail Fast

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.

Convey Intent

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

Mayfly Variables

The lifetime of a mayfly is extremely short: only a few hours, and many live for less than an hour!

Not covered here is the thorny issue of JavaScript variables. Because of hoisting many people recommend declaring all of your variables at the top of your functions.

It is important to understand hoisting in JavaScript. As long as you and your team understand it, you should be free to code in the style that you like best.

Parameters

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

Scrolling

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.

Exceptions

There are three kinds of exceptions:

Unrecoverable

Recoverable

Ignorable

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.

Classes

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

Cohesion

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:

Vehicle

VehicleMaintenance

VehicleFinance

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

Primitive obsession is using primitive types such as strings and integers instead of encapsulating model classes.

Apologies and Warnings

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.

Bloated Header

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.

Defect Log

Avoid comments that only describe source control metadata because that’s exactly what source control is for.

Clean Comments

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.

Demo

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.

Stay clean

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.