Reading Clean Code: Week 2

Jacob on Software
CodeX
Published in
8 min readJun 29, 2021

As followers of this blog know, I’m currently reading through Clean Code, a classic in how to write readable, professional code. Written primarily by “Uncle Bob” Martin, with appearances from a number of leading thinkers in the field of AGILE software development, Clean Code isn’t exactly a step-by-step coding manual. While I covet another animal-adorned O’Reilly book as much as the next code junkie, Clean Code won’t teach you a particular language or framework. Rather, Clean Code’s subtitle — “A Handbook of Software Craftsmanship” — explains the broader purpose of this book.

Uncle Bob wants you to write clean code

For Bob Martin and his co-authors, Clean Code provides a way to take care with your code. Just like a carpenter guides her or his lathe across a slab of wood with laser precision (nowadays literally with laser precision), so too should software engineers write their code with the utmost attention to detail. To illustrate more specifically what this fantastic book has to offer, I’m going to continue where I left off last week, providing more detail as to what elements of a computer program might require cleaning.

For this post, I’m going to look at code for a different project than last week, refactoring my own work using entirely different lessons from Clean Code. Fans of the book (and similar texts) might notice that I’m not writing sequentially by chapter. From my experience, Clean Code is one of those books that is best digested by flipping around to a chapter that immediately grabs you. Let’s start restructuring our project to make it a bit cleaner.

The project I’ll be refactoring for this post is in fact my capstone project for Flatiron School’s software engineering bootcamp, Putrid Potatoes (please excuse the corny name, I truly can’t help it). A clone of the movie review website Letterboxd, Putrid Potatoes allows you to log the films you’ve watched, write reviews of those films, and follow other reviewers on the site. As a fan of Letterboxd and cinema generally, I had so much fun building this website, and once it was complete I truly felt like a full-fledged software engineer.

Putrid Potatoes homepage

That said, as anyone who’s attended a coding bootcamp can tell you, learning to make a full stack web application in just three weeks can be immensely stressful. I’m not proud of it, but I’m sure that in that time I wrote some not so clean code, and I’m excited take lessons from Uncle Bob and co. to tidy some of my work up. As a reminder, the reason it’s so important to write clean code is that the time spent reading code as opposed to writing code is 10:1. This is especially important because I’m still building out features for Putrid Potatoes, and anyone with a GitHub account can contribute to my code just like any piece of open-source software. If my code was unclear it would slow down their development process and possibly the evolution of the site. Worse yet, if Putrid Potatoes gained a significant amount of users and something broke it’d be infinitely harder to fix than if I had just written clean code! With that, let’s look at what we can clean up in this codebase.

Functions

Even if you don’t follow the functional programming paradigm, functions are, as Clean Code says, “the first line of organization in any program.” Functions allow us to pass data through our program, manipulating it to our heart’s desire and unlocking the real power of software. As we rely on functions so often in our code, it’s important to make sure we follow some best practices. Let’s look at the following function from Putrid Potatoes, which follows another user on the app when the correct button is clicked and sends that user an email notifying them of their new follower (utilizing the fantastic EmailJS library):

While the naming conventions used here are relatively straightforward, there’s one major problem with this piece of code. As Clean Code says, functions should be Small! To be more specific, Martin tells us these are the first two rules of functions:

  1. Functions should be small.
  2. Functions should be smaller than that.

Although handleFollowOtherUser could be a lot longer — I’ve seen functions in the 1,000-line range (gulp!) — functions should be bite-size chunks we can easily grok. If writing code is like any other kind of writing, then we want our functions to serve as sentences, incrementally giving details on what a program is supposed to do as though it were a novel. Rather than have this 30-line behemoth like the one above, our code would be significantly more readable if it was broken up into multiple smaller functions:

In my opinion, even just halving this function into two chunks makes it much more readable. If another programmer were to come along, they would have a much easier time following the chain of functions here.

Refactoring my code in this way allows us to discuss another of Bob Martin’s recommendations for our functions: functions should Do One Thing. Before, handleFollowOtherUser was performing quite a few operations for us, taking in the event, collecting the proper information to create a new follower-followee relationship, and then posting that data to our database.This function is a no-brainer to edit. While we could abstract postNewFollowerRelationshipToBackend out into smaller and smaller chunks, I think it’s preferable in this case to keep all of our fetch logic in one place.

While I won’t go into them in full detail here, Clean Code’s recommendations on Function Arguments, Using Descriptive Names, and keeping your code D.R.Y. (Don’t Repeat Yourself) are well worth a Google, and will likely be a subject of future blog posts here. No doubt they will make your functions smaller and more easily digestible for your development team.

Formatting

One of the great joys of writing code today is the flexibility we can give to the layout of the words we write. Just imagine if we had to write code that looked anything like this minified JavaScript file:

The nightmare fuel of code

Thankfully, our IDEs give us the ability to format our code in virtually anyway we want. So long as it’s still valid in the language we’re writing in, the compiler should be able to bundle our code and do what we tell it to. But just because we can write our code in an extremely loose format doesn’t mean we shouldn’t take care with how we present our code on the page. To be sure, Clean Code’s chapter on formatting has one of best sentences I’ve ever read on writing code, and I think it sums up the point of the entire book well:

“Code formatting is about communication, and communication is the professional developer’s first order of business.”

We have to remember as software engineers, code is just words. As convoluted as fetches and try-catches and switch statements get, we’re still just writing words, linking them together to make a cohesive whole of a program. For this reason, we want to pay close attention to detail. Let’s look at the following code to get a sense of formatting:

As you can see, GenreFilter() takes up only 25 lines of code (it also clearly does one thing and has descriptive names, in case you were keeping score). But why is Vertical Formatting important for our programs? Let’s take a look at the following diagram from Clean Code, which shows the average file length of a number of large-scale production applications:

As Clean Code tells us, “small files are easier to understand than large files.” Rather than scrolling up and down our screen to understand what our code should do, we can write small files and break our logic out into other files if it gets too long. What’s more, it’s clearly possible to create useful applications writing ~100 lines of code/file. To help drive this point home, Martin tells us to use The Newspaper Metaphor. We read the newspaper vertically, looking first to an informative headline, then to the synopsis of the story in the first paragraph, and gleaning more details as we read further below. In the same way, our source files should have simple, explanatory names, with more details about the file revealing themselves as we read downwards. Let’s look at another aspect of formatting we should pay close attention to:

While the functionality of allReviews is clear enough, there’s obviously a big problem here: the width of the line starting with canLeaveReview exceeds the length of the screen! Just like with vertical formatting, as programmers we also need to pay attention to Horizontal Formatting. To get a better sense of what I mean here, let’s look at another diagram from Clean Code showing the average line width:

As the diagram shows us, programmers clearly prefer short lines. Even if we’re working with large monitors, we should be cognizant that other programmers will likely not want to scan the entire length of their screen to see what the relevant code is supposed to do. Refactoring this code makes it much more readable:

While the edited code is still fairly wide, the longest line is now only 160 characters long, roughly half of what it was before. There are many more lessons to be learned about formatting that I won’t delve into here, including Indentation, Horizontal Alignment, and Conceptual Affinity. Although it might seem like with formatting you’re merely making your code look presentable, there is serious power in writing code that others can easily read.

As I mentioned in the beginning of this blog post, Clean Code is one of those books that you can flip around until something piques your interest. As an aside, the book has a number of funny cartoons at the start of every chapter, and you might do well to start reading wherever your interest takes you.

Over the next few weeks I’ll continue reading and writing my way through Clean Code, veering off into different blog topics when I need to learn more about writing good tests or general code design. My hope in this blog series is that you’re inspired to write good, clean code, so we can all collectively build software that does something important. So go ahead, flip around, find something that looks interesting to you, and go write some clean code.

--

--