Key Takeaways from “Clean Code” by Robert C. Martin

Mihael Y. Cholakov
Sep 6, 2018 · 7 min read

through the prism of an iOS developer.

Clean Code: A Handbook of Agile Software Craftsmanship is a remarkable book written by Robert Martin. It uses Java examples exclusively, but that should not stand in your way. The entire book consists of wonderful examples of how a good code should look and behave. As I’m an iOS developer, this article aims to tell the story using examples tailored for Swift.

Functions should be short, well-named, and straight to the point.

In my practice i’ve seen quite the gigantic blocks of code under the roof of a single function. To be honest, some of them were written by me. Thankfully, I’ve learned from my mistakes and so should you. It’s very easy to fall in the trap of just pouring all the logic into the editor not realizing you’re 100 lines deep into a single function.

Let’s look at the example:

This is a key function of a custom ProgressView that allows setting the progress. The first few lines however take care of something else - normalizing the fractionComplete. Just like UIViewPropertyAnimator, ProgressView's fraction complete value can only be between 0.0 and 1.0. But why should that happen in the setProgress(_:animated:)? It has nothing to do with actually displaying the progress.

Let’s extract this logic to an extension:

This solves the issue of having a piece of code whose responsibility does not match the one of the containing function. Sure, it shaves off only a single line of code, but in other examples it could easily exceed 5–6 or 30 lines.
There’s something else. Normalization can be required not only for Double. You could extend all other numeric types with basically the same function replacing the types. But that is a big no-no. First of all, it does not follow one of the most important guidelines for a clean code -- Do Not Repeat yourself. Second of all, since we're in the context of iOS Development, it is not very Swifty.

Let’s take a look at the declaration of the max function:

The generic type T conforms to Comparable. Let's use that protocol for our improved extension.

It’s beautiful, isn’t it? We can now use it with all `Comparable` types and pass the range it should take into account.

For the next example let’s focus on the naming.

At first sight everything seems okay, right? We’ve extended Date with the function add(_:). But.. what are we adding to the current date? Is it minutes, days, years?
A more readable approach would be:

or:

However, we’re still able to take things one step further. We could bring back the add name, but add the actual date component.

Now the function call reads like a sentence.

Don’t comment just because.

We are often told we should comment everywhere, all the time. That one is not a good programmer if they neglect it. And I stand by the comment praising, but let’s step back just for a little bit. Comments can be dangerous. If they are not maintained alongside the nearby code, they can be misleading, or straight up lies.

Other times they are just a noise. Take a look at the following example:

Do we gain anything by specifying that the value parameter in an add function represents the value that is to be added? Honestly, that's more of a noise. It can get even uglier:

Try to explain yourself with code first. For example, prioritize functions / variables. In my humble opinion, this:

is better than this:

Most importantly, you should not make up for bad code with comments. Before writing a short poem on what the following lines do, ask yourself is the code most simple and decluttered version if itself.

Structuring and formatting.

The book quotes a very interesting metaphor — a code should be like a well written newspapper article.

The first paragraph gives you a synopsis of the whole story, hiding all the details while giving you the broad-brush concepts. As you continue downward, the details increase until oyou have all the dates, names, quotes, claims, and other minutia.

Let’s take a look at a common example of a View Controller structure:

There’s a pretty good chance there’s a logic in setupObservers that is quite specific, possibly executed not that commonly. This should not be the first paragraph of our article. Instead, it is a detail that is to be buried further in the code.

Furthermore, a newspaper article often does not spread throught hundreds of symbols wide, as it makes thing harder to read. In Xcode there’s a handy option in the settings to guide you with this. ⌘ + , -> Text Editing -> Page Guide at Column. A good go-to value is 100. 120 at maximum.

For example, instead of this:

go for this:

It is much neater and easier to follow.

For a full guide on dos and donts for line-wrapping (and everything else), refer to Google’s Swift Style Guide.

Team Rules.

Everybody has their own favourite programming formatting rules. Working in a team, no matter the size, leads to some clashes of preferences. It is a good practice for a team to agree on sets of rules and follow them unconditionally. When you look at a codebase it should look consistent, as it was created by a single entity — a team. Not just a bunch of individuals gathered around.

Replace magic numbers

The following example speaks for itself:

The logic takes care of anchoring the header view if the user scrolls past 60 pts. But what does that value of 60 means? And how a colleague of yours in future will be able to take care of additional logic that should take that value into account?

Giving that magic number a name makes all the difference in the world. Also, it makes thing drastically better in cases where that magic number is used in more complex calculations.

Classes should be cohesive.

In a perfect world all classes are small and have a limited number of variables. For a class to be maximally cohesive means that each of its methods use each of its variables. While that sounds and in practice is close to impossible, it is a good thing to keep in mind and try to follow. Maintaining cohesion results in many small classes. And this is always a good thing and means we’re most certainly sticking to the one responsibility per class rule.

Fight inconsistency.

Some actions can be called a couple of different ways. It is a good practice to pick one name for each of those actions and stick with it for the whole project. The first thing that comes to my mind is downloading a json struct from some backend. I’ve seen this action called retrieveObject, downloadObject, fetchObject, getObject. I prefer getObject, since it corresponds to the HTTP method. Whatever you decide on, use it everywhere.

Another thing is the result of service call.

Here you can call the closure argument result or response, etc.

Unit Test

I left this part for the end as it’s probably the one that affected me the most.

The book quotes the three laws of TDD

First Law You may not write production code until you have written a failing test.
Second Law You may not write more of a unit test than is sufficient to fail, and not compiling is failing.
Third Law You may not write more production code than is sufficient to pass the currently failing test.

This three laws lock you into a cycle that is perhaps thirty seconds long.

While test driven development is neat and greatly improves the code quality, we should take the time and care to give it the ‘clean’ treatment as well. The easy part is that we can treat unit tests a little more loosely compared to production code. For example, in the iOS world, you’re completely allowed to use force unwrapping, or give variables shorter names (ex: vc suffix for View Controllers instances).
However, you need to keep in mind that dirty tests is quite possibly worse than having no tests at all. Unit tests allow us to confirm that we are not breaking functionality by making changes to the codebase. But when it is necessary to make substantial changes, it should be followed by refactoring the tests as well. Maintaining badly written tests is as painful as maintaining badly written code.

A single test should take care of a single concept. There should be one point of a possible failure. If needed, feel free to split a function into smaller testable chunks.

The book quotes another five rules we need to abide, a.k.a the F.I.R.S.T.

Fast

Tests should be run frequently and not take much time to do so.

Independent

Tests should be able to be tested individually and not depend on each other. A bad example is a test setting up conditions for the following test(s).

Repeatable

Tests should be repeatable in any environment.

Self-Validating

Tests should have a boolean output. Either they fail or succeed. You should not have to read through logs or compare different files in order to tell if a test is failing.

Timely

Tests should be written just before the production code. If you start writing tests a week or month after the code they are testing, you are no longer in the state of mind where you have a problem and a resolution you know everything about. That leads to making things take longer time and you may even skip important details just because.. well, you forgot about them.

Conclusion

This article barely scratches the surface of what Clean Code: A Handbook of Agile Software Craftsmanship has to offer. It is certainly no surprise that it is that praised. The book allowed me to focus on the fundamental things. As an iOS developer, I really love focusing on the shiny animations, trying out the new things Apple anounces every WWDC, browsing github for awesome open source projects and then watching 4 conference talks about it in a single evening. Reading the book kind of made me step back a little bit, slow down and think about backbone of a codebase. I am certain it made me a better developer and highly recommend it.

You can grab your copy at Amazon.

Thank you for reading this post. ✌️
Mihael

Mihael Y. Cholakov

Written by

iOS Developer

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade