22 Comments

Uncle Bob’s Clean Code: Irrelevant in the Age of Full-Stack JavaScript?

I recently picked up Clean Code by Robert C. Martin (a.k.a. Uncle Bob). I’ve found it to be particularly helpful in the practice of day-to-day software development. It contains some wisdom that has since become so engrained in the culture of the software development community that it almost sounds trite when you read it for the first time. But how relevant is it to the concerns of web development eight years after it was published?

Clean Code Book Cover

Some Context

If there’s one place where the book struggles, it’s in the fact that it was written one year prior to the birth of Node.js and the full-stack JavaScript application. The code examples–all written in Java–have aged reasonably well, except for the fact that they’re written in Java.

If this book were to be written today, the code examples ought to be written in JavaScript. Not only is JavaScript the most appropriate language for this book because of its widespread use and promising future, but JavaScript is also a much more difficult language in which to write clean code.

Let me be clear: You can write terrible code in any language, but if you were to try to write terrible code that works, JavaScript would be your language of choice. And that’s why I’m evaluating Clean Code in this 21st year of JavaScript (JavaScript can drink now!).

Clean Code is Functional

The most important of Martin’s claims is that clean code is functional. Mind you, this was written when Java 6 was the latest and greatest and Java had not fully embraced the functional style with the introduction of lambda expressions and java.util.function.

Probably my favorite bit of wisdom in Martin’s chapter on functions is that functions should not mix levels of abstraction. On some level, I knew this, but I did not quite have the vocabulary to express it. From Martin:

Mixing levels of abstraction within a function is always confusing. Readers may not be able to tell whether a particular expression is an essential concept or a detail. Worse, like broken windows, once details are mixed with essential concepts, more and more details tend to accrete within the function.

This is especially relevant to JavaScript developers because unless your tests break, it’s very easy to screw up code that you’re working in without knowing that you broke it. Abiding by this principle is also perhaps the best way to discern the boundaries of a function’s responsibility (and keeping your functions short, another of Martin’s values). Keeping your JavaScript code functional is probably the only path to sanity in a large JavaScript codebase. Martin’s chapter on functional code is maybe the most valuable 22 pages you could read on the subject of staying sane.

Clean Code is Clean

I found the foreword written by James O. Coplien to be really insightful. He discusses the Japanese workplace organization methodology called 5S, and one of the principles of this methodology is Seiso (Shine).

Clean your workplace on daily basis completely or set cleaning frequency.
Use cleaning as inspection.
Prevent machinery and equipment deterioration.
Keep workplace safe and easy to work.
Keep workplace clean and pleasing to work in.

As I was reading this, I realized that there were formatting inconsistencies in my codebase that had been really irritating me. I immediately took a few minutes to do a find and replace (and run tests) on stuff like spaces between closing parens and opening curly braces in anonymous function expressions. I was really quite surprised to find how much better I felt after doing this.

I also can’t express how important this is for catching typos in a language that fails as silently as JavaScript does. Anything you can do to make your codebase more regular and easy to scan for correctness must be done. Unit tests are the answer to many problems, but there are certainly edge cases that will frustrate you when you fat finger a variable name.

‘The Only Truly Good Comment is the Comment You Found a Way Not To Write’

Comments are the subject of the next most enjoyable chapter. I’m not a big code commenter, but boy, did I love reading Martin’s takedown of code comments:

Why am I so down on comments? Because they lie. Not always, and not intentionally, but too often. The older a comment is, and the farther away it is from the code it describes, the more likely it is to be just plain wrong. The reason is simple. Programmers can’t realistically maintain them.

The distilled wisdom from this chapter is relevant to people like me who already avoid writing comments: If you feel an urge to comment or explain yourself, encapsulate the code you would comment in a function that is basically the comment you would write.

I encountered this problem recently when writing a function that programmatically creates the name of the image file it needs based on a combination of variables that describe some state of the app.


keyboardLayoutImage: function () {
    let keyboardLayout = this.get('keyboardLayout');
    let itemDisplay = this.get('itemDisplayMode');
    return 'assets/images/' + _.kebab([keyboardLayout, itemDisplay]) + '.png';
}

My solution for constructing filenames using constants describing the various states of the app was simple, easy to read, easy to test, and very short. There was only one problem: Since we used the same image file for several different states, we could reduce load time by using the same image file for several of the states. If you were just reading the code, my addition to support this functionality looked bizarre:


keyboardLayoutImage: function () {
    let keyboardLayout = this.get('keyboardLayout');
    let itemDisplay = this.get('itemDisplayMode');

    if (keyboardLayout === LetterLayouts.custom) {
      keyboardLayout = LetterLayouts.alphabetical;
    }

    return 'assets/images/' + _.kebabCase([keyboardLayout, itemDisplay]) + '.png';
}

I almost felt the need to put a comment there describing the shortcut I was taking to reduce the number of images we used. Instead, I took Martin’s advice, and got the resulting code that is much cleaner (and doesn’t mix levels of abstraction!).


keyboardLayoutImage: function () {
    let keyboardLayout = this.get('keyboardLayout');
    let itemDisplay = this.get('itemDisplayMode');
    keyboardLayout = this.useAlphabeticalImagesForCustomLayout(keyboardLayout);

    return 'assets/images/' + _.kebabCase([keyboardLayout, itemDisplay]) + '.png';
},
useAlphabeticalImagesForCustomLayout: function (keyboardLayout) {
    if (keyboardLayout === LetterLayouts.custom) {
      return LetterLayouts.alphabetical;
    } else {
      return keyboardLayout;
    }
}

Some Quibbles

I will go ahead and address Betteridge’s Law Of Headlines: Clean Code is still relevant–in fact, reading it with the present in mind makes it feel at times prescient with its embrace of functional programming, which is all the rage in front-end development these days.

While it is still relevant, an update certainly wouldn’t hurt it. For instance:

  • The chapter on error handling is still very relevant to Java, but a fundamental premise doesn’t apply to JavaScript error handling: try-catch-finally blocks define their own scope in Java. JavaScript has block scope syntax and functional scope. Although the introduction of let has improved the language in this respect, JavaScript’s weird scope rules requires extra consideration.
  • There’s almost nothing in the book about managing asynchronous code. This is a weird subject to tackle, especially since some JavaScript frameworks are built around solving this problem, but it would still be nice to have it directly addressed by Martin.
  • It sometimes feels like Martin is creating a catalog of interesting code smells, and while there’s value in creating a vocabulary with which to talk about such things, it doesn’t always feel particularly helpful. Time might be better spent on strategies for absolving your code base of such nonsense (or helping team members lose such habits).

Martin’s Clean Code has a lot to say that is applicable to JavaScript development, but if Clean Code: JavaScript Edition came out tomorrow, I’d be first in line to buy it.