Back

A Clean Guide to Uncle Bob’s Work

Introducing our guide through Uncle Bob's legacy. Dive into Agile, Clean Code, and Software Craftsmanship.
Szymon Biduła

Szymon Biduła

Mar 27, 2024 | 18 min read

A Clean Guide to Uncle Bob’s Work

Robert Martin, or "Uncle Bob" is a highly influential author who covers the realities of the IT world today. As one of the co-authors of The Agile Manifesto, Martin shaped the landscape of a software project manager as much as the coding environment of a software engineer with his work on the software architecture and coding style.

I will present his ideas about how to practice test-driven development, how to implement best agile practices and write good code. I’ll also go into how organizations can implement these values. Of course, Agile values don’t just apply to software project management, they also fit other complex collaborative projects in various fields.

Clean Craftsmanship: Disciplines, Standards and Ethics

Clean Craftsmanship Disciplines, Standards and Ethics

In a widely-cited 2018 publication “Accelerate: The Science of Lean Software and DevOps” authors Nicole Forsgren, Jez Humble, and Gene Kim found that a company's culture is one of the main factors that contributes to the pace at which an organization can deliver software. This metric, in turn, is related to revenue, employee turnover and the general health of the company. Interestingly, using Ron Westrum's classification system he laid out in his 2004 paper, A Typology of Organisational Cultures they also provided evidence that a generative culture is optimal in IT-driven organizations.

What is a generative culture?

Westrum based his studies on the assumption that the flow of information is the pinnacle of a company's culture. Leaders either enable or stop it through their actions. In a generative culture, leaders are concerned with performance (not power) and are interested in implementing novelty, and cooperation strategies. Moreover, they’re interested in learning from failure and dare to share the risks.

How to implement a generative culture

Unfortunately, Westrum as well as Forsgren, Kim and Humble have rather murky advice on how to implement it. In "Clean Craftsmanship: Disciplines, Standards, and Ethics" Uncle Bob provides some advice on how to organize teamwork, on the individual level, as this book was published before the seminal 2019 work “Team Topologies” by Manuel Pais and Matthew Skelton.

Ideas Uncle Bob presents

Professional values that could save you significant resources revolve around the foundation of writing clean code. Some highlights include:

  • Professionals know when to say no. Instead of saying, “I’ll try” it is better to say “no” and work together as a team to find a solution for both management and developers.

  • Professionals also know what it means when you say yes. Here the book uses the "say, mean, do" framework created by Roy Osherove. If you say “yes,” you’re specifying what you are going to do (say), you have the intention of doing this stuff (mean), you do the work (do).

  • Professionals test their code using the TDD method and acceptance tests.

  • iProfessionals work as a team. You use pair programming, you ask for help when you get stuck, and you use "say, mean, do" so other people can depend on you.

Clean Agile: Back to Basics

Clean Agile Back to Basics

Agile software craftsmanship

Processes are hard to grasp. They’re those abstract and nimble things created from hundreds of interactions that are heavily context-dependent. Software development is also a process. This conclusion has opened a whole new area of studies that are trying to answer questions like:

  • How can we measure the effectiveness of the development process?

  • How should we organize teamwork?

  • How to react to change?

Clean coders have their answer to these questions—you have to practice agile software craftsmanship.

Revolutionary paradigm

To truly understand why this take on the software development process leads to accomplishing tasks at higher peace than other methodologies you need to understand where the agile alliance came from. "Clean Agile: Back to Basics" starts there. It tells a captivating story of how the Agile framework came to life at Snowbird Ski Resort. You’ll understand how the life of a project manager, software engineer, or systems analyst looked in the Waterfall world and how significant resources were wasted because of a lack of feedback from the business, and why agile is a revolutionary paradigm.

Agile development organization

After giving you the why, Uncle Bob proceeds to give you the how, so you could become a team lead/project manager or better understand why your team is doing things in this way if you are a software engineer. It will clear several cognitive distortions common in task estimates, and give you good advice on how to adopt the clearly defined practices from the book. For software engineers, these practices include writing unit tests, cleaning code by refactoring and pair programming. Project managers will find in ideas Uncle Bob presents all the timeless advice of what to measure, how velocity is an important part of agile practice, and why continuous integration is such an important concept.

Master craftsman: the beginning

After reading “Clean Agile” you likely won't be able to claim final authority on best agile practice, but you’ll be able to start your work with greenfield projects or legacy systems reasonably. Highly recommended.

"The Clean Coder: A Code Of Conduct For Professional Programmers" A Tale of Writing Clean Code

The Clean Coder...

All the timeless advice: how to write a better code?

"The Clean Coder: A Code Of Conduct For Professional Programmers" outlines several of the key questions for any software developer. How to start cleaning code? How to begin writing good functions? How to distinguish between good and bad code?

It is important to put advice from this book into a modern perspective. Here are some points that could help:

  • In its introduction, Uncle Bob asked other significant software development figures like Bjarne Stroustrup, Ward Cunningham, or Michael Feathers to define clean code in their own words. Then, Uncle Bob suggested that his teachings are more like martial arts disciplines—different methods focus on different aspects.

  • Some parts of this book are dated. Seems that linters and code formatters have a greater impact on the daily work of software developers than we are willing to admit. Otherwise, why are we smiling when reading chapters about Comments or how to format code?

  • The book is JAVA-skewed. Some could argue that this language is not offering maximum readability, to say the least, thus it does not help in writing clean code. We are not opening this Pandora's box, just give a heads up that you will find in this book a whole chapter about JUnit.

  • Finally, clean code is written for a better developer experience. According to the assumption that one reads more code than one writes, so it’s better to optimize the reading time.

Clean code equals bad performance: debate

Clean code prioritizes the developer experience, so it raises the question if that focus causes other software qualities to suffer. Casey Muratori took this as a starting point on his substack and examined how performance differs between clean code and poorly written code.

Next, Muratori took the classical shape listing used as a guiding example of clean code and then measured the performance. In the next steps, he stripped away the clean code rules and added a few bad ideas, at least according to the advocates of this approach, instead, he replaced polymorphism with "switch" statements. The results were astounding. The clean code slowed the program performance by a factor of 25.

Although a heated debate went through social media one finding is important. Nobody believed in a free lunch, i.e., that we could exchange developer experience for free when it comes to performance. Nevertheless, the scale sent a shock wave through the Agile community.

"Agile Software Development, Principles, Patterns, and Practices": Uncle Bob’s Guide to SOLID Principles

Agile Software Development, Principles, Patterns, and Practices...

SOLID isn’t for functional programming?

It’s not a trivial task to trace back the SOLID principle. Some claim Uncle Bob coined the term in a 2000 article from Object Mentor, however, archived sites trace the term to 1995. We are using the book "Agile Software Development, Principles, Patterns, and Practices" as the starting point of the discussion. Although the SOLID principles are regarded as a core of object-oriented programming in the blog post OO vs FP Uncle Bob argues that they are general programming principles that could be used regardless of the paradigm that you work with.

Single responsibility principle (SRP)

The only constant is change: cliche is a good starting point

Uncle Bob presented SRP on numerous occasions, but I think the best explanation of this rule was in his blog post The Single Responsibility Principle from 2014. It represents the basic tenet of Uncle Bob's software philosophy, namely, that our processes, code and work ethic should be able to effectively deal with change. Why is this aspect of the infinitely complex process of creating software so important? Here noted software expert Robert Martin cites a classical paper from David Parnas (1972). In this article, Parnas provided evidence, albeit limited, that the most effective strategy of decomposition, which is the basis of software development, isn’t based on workflow but on the encapsulation of decisions that may change.

How to separate modules?

To have an efficient strategy of adapting to change we need to identify the source. SRP gives you the answer to where the changes are likely to come. Namely, they will come from people. Despite its surface simplicity many senior developers who we’ve been fortunate to work with believe that this is the most important principle of all SOLID. First, it tells you how you have to group similar elements, so your code will become more cohesive. Secondly, and more importantly, it could transform the way you think about designing your code. If you start thinking in terms of SRP you will no longer see classes or modules but people/personas that will need to interact with them to accomplish some action. This change of way of thinking will pay off considerably.

Open/closed principle (OCP)

As you have separated your code into classes and modules that take users into account, another question emerges. How to build a resilient system that can accommodate a change within an existing part?

One of the answers is to design according to the OCP: your code should be open for extension but closed to modifications. How to achieve this? According to Uncle Bob if you base your code on stable abstractions you would get a clear definition of behaviors that will be open for extension because you could add behavior to child classes thanks to inheritance.

Importantly, the chapter about OCP ends with advice to use this principle only in parts of the system that will change a lot. To paraphrase another popular rule: premature use of abstraction may be the root of all evil in your system.

Stay updated

Get informed about the most interesting MasterBorn news.

Check our Policy to know how we process your personal data.

Liskov substitution principle (LSP)

Given the last piece of advice, we should strive to base our system on stable abstractions, e.g., abstract classes or interfaces in concrete implementations. This naturally leads to a concept of hierarchy. Barbara Liskov in LSP gives us a strict rule on how to create the mentioned chains of inheritance that could enrich our systems.

In her memoir, Liskov distinguished two kinds of inheritance, namely an implementation hierarchy and a type hierarchy. Implementation was a way to omit code duplication by sharing methods or properties among classes. As such, it was rather uninteresting to her as data abstraction, i.e., restricting which methods are allowed to manipulate objects, could achieve a similar goal. However, type hierarchy could reveal interesting properties of the system that we work with.

Liskov believed that to construct a type hierarchy object within it should abide by a more restricted set of rules. Her favorite example is the difference between a stack and a queue. Both of the mentioned data structures could have a method that removes elements. Their signature could be the same. Yet, the behavior varies drastically.

Therefore, Liskov was interested in defining a way of creating a hierarchy that could preserve the behavior of supertype across the whole inheritance chain, so the user could use it safely. She provided the answer in the seminal 1994 paper by using the notions of pre-conditions, invariants, and post-conditions.

Together with her coworker, she has formally proven that to preserve the behavior of the supertype the subtype must maintain the pre-conditions and invariants that are necessary to run a method in question, and post-conditions have to equal to or even be stronger than that from the base type. This has become a powerful idea of how to create APIs or even protocols (check robustness principle/Postel's law).

In his book, Uncle Bob gives us a perfect example of how to spot that we are breaking the LSP. If we start to depend on our control flow to check which instance a class is, then the smell tells us that we have broken the LSP.

Interface segregation principle (ISP)

We have learned so far how to distinguish modules in our system by using the SRP, then we maintained these modules open for extension by using stable abstractions. After we started to create a hierarchy among classes, LSP provided us with a guide on how to maintain their behavior stable and predictable. Now, with ISP Uncle Bob is helping us with another problem that usually emerges during the work. How to maintain an interface with reasonable size within the created hierarchy? The answer seems to be simple: the client should not be forced to implement a method that he doesn’t use.

As usual, Uncle Bob provides us with two heuristics that help us implement the ISP. He distinguishes two methods of separating/using interfaces. The first one tells us that if we do not need to use the whole interface, but some methods from it, then we should consider using an intermediary. For instance, you could use an adapter pattern. The latter heuristic advice for using multiple inheritance.

Dependency inversion principle (DIP)

Finally, we get another piece of advice on how to structure our code with the use of abstractions. Uncle Bob proposed that we should structure our code, so the low-level code should depend on the abstractions. This is an inversion of the typical control flow where the UI depends on the abstract domain logic, and the domain logic depends on the database. DIP states that both UI and database should depend on the domain logic.

How to achieve this goal? Domain logic could take control by defining ports that lower modules need to implement in an adapter. Thus, consequently used DIP will result in a variation of the ports and adapters architecture.

SOLID Alternatives

Given its widespread influence SOLID principles have been intensively discussed among developers during the conferences and examined during the job interviews. Interestingly, we were able to find only limited evidence that they lead to a better code/save cost. As a result, the mentioned rules have been challenged.

CUPID

Probably the most recent alternative has been proposed by Dan North, the guy who invented Behavioral Driven Design, with a cute backronym CUPID. The most important change that he suggested is to stop thinking in terms of principles and start to think in terms of code properties.

As a result, CUPID represents qualities that software should have, so the work with it would be "joyful." These properties are composability, Unix philosophy, predictability, idiomatic and domain-driven.

"Clean Architecture: A Craftsman's Guide to Software Structure and Design": Principles to Distinguish Good and Bad Code

Clean Architecture

Ports and Adapters versus Onion Architecture versus Clean Architecture

Given that there are three architecture patterns, namely port and adapter, onion architecture and clean architecture that are closely related it is valuable to point out their differences to better understand them.

Alistair Cockburn defined the ports and adapters pattern in 2005. He wanted to prevent business logic from leaking into the infrastructure code and enable testing without the concern of low-level code. How to do this? He used the metaphor of a port by which the driver could use the business logic and adapter which modulates the signal from the driver, so it can go through the port to the business logic.

This idea was the starting point for Jeffrey Palermo who in 2008 used it to invert the flow control in the classical layered architecture. As this version was centered around the layers Palermo called it an onion architecture.

In the next iteration, Uncle Bob (2018) added that for an onion architecture to be clean it has to be independent of frameworks, databases, transport layers and other details. This is the most radical presentation of the initial port and adapter pattern. In the case of NodeJS, this idea imposes, for instance, that your application should be independent of ExpressJS or other libraries (check this repo for an example implementation).

Clean architecture critique

This architecture has been critiqued, for example by Dudycz (2022), who pointed out that:

  • Focus on technical layers swings your attention from the business flow.

  • Layers tend to proliferate during the life of the application, as a result, the cognitive burden of understanding the app flow becomes unbearable.

  • If everybody feels lost in the code, then everybody is even more scared to change it.

"Screaming Architecture:" Uncle Bob’s Clean Code in Folders

Screaming architecture

Before you start writing code

Every software developer sooner or later will face a mundane problem of how to organize and name folders in their projects. Surprisingly, even such a simple decision could result in obscuring code logic as pointed out in the well-known post "Screaming architecture."

Software developers should center their code around the use case

In his article, Uncle Bob argues that a code base should be centered around the project use case. A folder structure should also be focused on the business theme of the project. You should not base your folder names on concepts like: "controllers," "services," or "database" but follow a better path and use domain names like: "employee," "salary," or "taxes" if, for example, you’re building a payroll system. After applying this suggestion your project will be screaming about the problem that it is trying to solve.

To reinforce the point, in the post, Uncle Bob draws a comparison between the folder structure of the application and the blueprints of a building. For instance, in a blueprint of a shopping mall, we would probably see corridors, places for stores and parking spots. The architecture would scream that you are looking at the future shopping center. Uncle Bob believes that this principle should be also applied to the folder structure of the application. Specifically, it should be based on the domain part of the code.

Software engineers should not base their folder structure on the framework or layers

This idea was developed in sharp contrast to framework-centric development organization that we could observe, for instance in Ruby on Rails, and could be seen as a starting point to the vertical slice architecture advocated by Jimmy Bogard.

Deeply misguided metaphor of the project

Interestingly, the essay is a perfect example of using the metaphor of a project as a building. The code base is a stack of bricks that create a room that in turn creates a building. This idea has been challenged, as it does not include software entropy and is hard to reconcile with continuous delivery (for a more in-depth discussion of this topic check Mark Seemann’s book “Code That Fits in Your Head: Heuristics for Software Engineering.”

Summary

In Mary Shaw's seminal 1990 paper: Prospects for an Engineering Discipline of Software defined three stages of maturity for engineering discipline, namely:

  • The “Craft" phase is defined by using brute force and intuitive methods implemented by "talented amateurs."

  • The "Commercial" stage is characterized by using strategies that effectively handle the scaling problems. These strategies are created by "skilled craftsmen."

  • The "Professional engineering" period is represented by individuals who use daily theories and analyses that guide them to use effective data structures. They call themselves "educated professionals.”

If we follow these terms, then Uncle Bob's work may be considered one of the best examples of the craft phase. One of his books, described in the present post, has a title: "Clean Craftsmanship." There’s still a lot to do in the software design field to move above from the craft stage to a professional engineering phase, so the projects that we work on will for sure not get off track. Nevertheless, Uncle Bob took one of the first and most significant stabs at defining the field, so we could move forward. As a result, every software developer who wants to grow has to digest his thoughts and timeless advice.

Related articles:
/blog/how-much-will-spaghetti-code-really-cost-you/

How Much Will Spaghetti Code Really Cost You?

Spaghetti code can lead to the failure of your IT infrastructure. Learn how to fix messy code and avoid it in the first place.

/blog/interview-with-matthew-combs-founder-and-ceo-at-tentacle/

Interview with Matthew Combs, Founder & CEO at Tentacle

Read about Matt’s experience working with MasterBorn to build Tentacle - leading him to tear down all notions of what working with an outsourced partner really means.

/blog/how-to-effectively-scale-your-web-app/

How to Effectively Scale Your Web Application - 7 Tips from a CTO

Web App Scaling ensures consistent performance and increases the efficiency of your app as it expands. Learn how to put it to good use in your business.

We build valuable, JavaScript products for U.S.-based companies

  • Nashville, U.S.

    2713 Wortham Ave.
    Nashville, TN 37215, USA

  • Wrocław, PL

    ul. Krupnicza 13, 50-075 Wrocław

  • Szczecin, PL

    ul. Wielka Odrzańska 26, 70-535 Szczecin

  • Kielce, PL

    ul. Gabrieli Zapolskiej 45B, 25-435 Kielce


Copyright © MasterBorn® 2016-2024

The Administrator of your data is MasterBorn, with its registered office in Wroclaw, Krupnicza 13, Wroclaw. If you want to withdraw, get an insight or update information about you, then contact us: contact@masterborn.com