Emergent Design with Clean Code

Jacob on Software
CodeX
Published in
5 min readAug 20, 2021

One of the great things about Clean Code is that as you progress through the book, the concepts you cover become more abstract. To my mind, this practice mirrors how one gets better at the art of programming itself. When you begin reading Clean Code, you cover concepts like good names for variables or functions and the optimal number of lines for a class. As you read on, however, Uncle Bob & Co. elaborate on how you can step back from your code and ensure that it is well-designed, that one of your colleagues could drop into your program on any given day and easily understand what you intend it to do.

In the same way, once you grok the syntax and basic features of a language or framework, you’re able to go up a layer of abstraction with your code, focusing on the overall design and maintainability of your programs. I’m referring here to emergent design, a concept in Agile software development that urges developers to focus on building the functionality of an application and letting the overall design of that system emerge with time. In this blog, I’ll review Clean Code’s general rules (in order of importance) for facilitating emergent design, and how you can build robust programs that are more readable and maintainable.

Rule 1: Run All the Tests

While we’ve talked about testing before, it bears repeating. To keep this lesson simple, I’ll repeat the most oft-quoted phrase my mentors in the software development space say to me: Untested code is broken code. As Clean Code puts it, an untested program is an unverifiable program; that is, you cannot check to see if your code consistently does what you intended it to do. And if you cannot check what a system does, you may as well not deploy it.

While I may sound a broken record, prioritizing tests essentially forces us to write cleaner code. For instance, if all of your logic for a program exists in a single file, it will be immensely difficult to test. To write tests for that logic, you’ll need to break your functions into separate files, adhering more closely to SRP by default and ultimately making your programs smaller. In addition, this practice lends itself well to loose coupling and high cohesion. So if you glean nothing else from this blog post, glean this: WRITE YOUR TESTS.

Rule 2: Refactoring

We’ve touched on refactoring before as well, but like testing, it’s such an important subject that we should discuss it in more depth. Simply put, refactoring our code is essential to good design. In point of fact, the rule about refactoring comes after the rule about tests for a very good reason: if we have good tests, we can be confident our program does what we intend it to do, even if we change it. As Jeff Langr writes in Clean Code:

The fact that we have these tests eliminates the fear that cleaning up the code will break it!

Although it can be a daunting proposition, it’s incredibly important to incrementally refactor our code. In giving our logic another look, we give ourselves a chance to employ programming best practices, choosing better names, modularizing our logic, etc. With testing and refactoring at the forefront of emergent design, we can fine-tune our code with the final three rules.

Rule 3: No Duplication

At this point you can probably see that I’m summarizing a lot of my earlier blog posts with this article. But while there are more chapters to read and forthcoming blog posts from me on Clean Code, this chapter serves as a good encapsulation of the book, summarizing many of the most important points as you look to write a cohesive piece of software.

Duplicative code introduces unnecessary complexity to your system, and along with that complexity, more opportunity for your programs to fail. By eliminating that duplication, your code becomes more reusable. While there are many methods for keeping your code D.R.Y., Clean Code specifically mentions the Template Method from the incredibly influential Design Patterns as a way to reduce that complexity.

Rule 4: Expressiveness

We’ve all been there, trying to decipher unclear code, painstakingly poring over every line looking for a pattern to emerge. Oftentimes we’re the programmer that wrote that unintelligible code in the first place, which makes the sting of confusion that much worse. As Clean Code tells us, the “the majority of costs of a software project is in the long-term maintenance.” As such, it’s critical that we write software everyone on our team will be able to understand.

There are many ways to express ourselves well in the medium of code. Good names help us write expressive code, as do small functions and separating concerns. In addition, unit tests act as another way to make our code expressive. When we run our tests we get a better sense of what our code intends to do.

Rule 5: Minimize Classes and Methods

While Rules 3 && 4 are important to follow, we wouldn’t want to take it too far and create thousands of classes and/or files to accomplish our task. In keeping classes and methods small, we may make too many of them, which will ultimately increase our code’s complexity and slow us down. In truth, writing clean code is a balancing act; in trying to achieve your goal, you’ll constantly be asking yourself is this method too large? Do I have too many classes? Are these tests brittle?

Frankly, this uncertainty is the nature of programming. There is no hard and fast “right answer” to most coding problems. Programming is a creative exercise, one that is never perfected, but in attempting to be perfect we get a little bit better everyday. As your skills improve, the idea that there is no “perfect code” goes from utterly terrifying to ultimately freeing. In attempting to write clean code, you will improve as a programmer, you will push your colleagues to improve, and you will create amazing things. What work could be better than that?

At the end of this chapter, Langr mentions that while these rules are important to follow, no guidelines can trump the expertise gained with experience. Still, by looking to these principles, programmers of all levels increase their likelihood of writing clean code, and in doing so, creating elegant software.

Happy coding!

--

--