NDepend

Improve your .NET code quality with NDepend

An Introduction to Clean Architecture

An Introduction To Clean Architecture

It seems to me that the topic of software architecture has attracted a lot of interest in the last few years. And among many different flavors and styles of software architecture, there’s one that attracts even more interest than the others. I’m talking about the clean architecture, proposed and evangelized by Robert C. Martin, a.k.a. Uncle Bob. (And for the rest of this post, it’s simply referred to as “clean architecture.”)

By employing clean architecture, you can design applications with very low coupling and independent of technical implementation details, such as databases and frameworks. That way, the application becomes easy to maintain and flexible to change. It also becomes intrinsically testable.

We’ll start today’s post not by explaining what clean architecture is right away. We’ll first dive into the problems that high coupling can cause in software projects. Then we’ll proceed to see the more mainstream solution to these problems.

Finally, we’ll explain the flaws with this solution, showing why and how clean architecture can be the piece of the puzzle that was missing for your application to achieve its full potential.

“Desperation” of Concerns

If you have at least a couple years of software development experience under your belt, then I can almost guarantee you’ve heard the term “separation of concerns.” It’s a principle that shows up quite often when talking about software architecture.

One of its incarnations is in the form of advice: “Separate presentation from business logic.” It’s very sound advice and I agree with it wholeheartedly, but the problem is that it’s not so easy or clear how to put it into practice, especially for beginners.

In practice, what ends up happening is that logic business frequently leaks to the application’s UI. And the same can go the other way around: it’s not so rare to find business logic code concerning itself with UI concepts, such as colors, markup languages, font sizes, and what have you.

And things can get even worse when you add data access to the mix. How does one free oneself from this mess?

Enter the Layered Architecture

The solution people often found for the mixing of concerns is to break up the application into layers. There are generally three:

  • One layer concerns itself with everything database related. A common name for this layer is “data access layer” (DAL) or something similar.
  • The next layer is responsible for the business logic of the application. It’s here that your entities and your value objects would generally reside, for instance. This is usually called, not surprisingly, “business logic layer” (BLL). Names such as “domain layer” or “core” are also common.
  • Finally, we have the UI or presentation layer, which, ideally, should contain all the code related to presentation concerns and no business logic code at all.

Nothing groundbreaking here, right? This stuff is pretty standard. You can bet there are no shortages of applications running around the world right now that follow an architecture like the one I’ve just described. Maybe the names aren’t exactly the same or there are more (or maybe just two) layers, but the general principles still apply.

The Problems With the…Not So Clean Architecture

In order to see clean architecture’s benefits, we really need to understand the flaws in the current alternative. And for that, we need to talk about dependencies.

Quick question about the architecture described in the previous section: which layer depends on which? Well, it’s trivial to answer this if we organize the layers by using a diagram:

UL to BLL to DAL flow chart

We can see that the presentation layer depends on (or references) the business logic layer, which is entirely reasonable. We wouldn’t want aesthetic tweaks to cause changes to our underlying business logic, right?

On the other hand, it’s perfectly acceptable that changes to the business rules cause changes in the UI.

The Traditional Layered Architecture Is Very Database-Centric

By looking at the diagram, we see that the business logic layer references the data access layer. If you rearranged the layers as concentric circles—like the common depiction of clean architecture, as we’ll see soon—then the data access layer would be at the center.

At first sight, it doesn’t look like a problem. After all, you often have to persist changes in the database after some interaction with the user. It seems like the natural workflow:

  • User performs some request through the UI.
  • The request generates some kind of action for the business objects to perform.
  • Finally, changes are persisted to the database as needed.

Well, of course that’s pretty much what happens at execution time. What doesn’t follow is that the dependencies should flow in the same direction at compile time also. They shouldn’t. This will harm you. Let’s understand why.

The first problem is that you couple yourself to a specific database vendor. I already hear you saying how rare it is for this to happen in practice. It happened to me on my first job after college. I had to adapt an application that up until then only ran on SQL Server and make it support Oracle Database also. ORMs were out of the question, for…reasons. It was a tough job, but it could’ve been easier if the application wasn’t so heavily coupled to SQL Server.

Dirty Architecture Hurts Testability

The next point is about testability. It’s not uncommon to have data access code mixed up with code that performs calculations or other tasks that don’t rely on the database at all. You really wish you could test the logic of the code. But that would mean hitting the database, which would make the test not only slow but also harder to set up and less predictable.

Coupling to the database does not only harm automated testing. Even manual exploratory testing can suffer. As put by Alistair Cockburn:

“When the database server goes down or undergoes significant rework or replacement, the programmers can’t work because their work is tied to the presence of the database. This causes delay costs and often bad feelings between the people.”

Here he says “programmers,” but replace that with “testers” or “QA engineers” and the effect is pretty much the same.

This issue also applies to the UI layer. Sometimes you really wish you could test user interface, just for the sake of testing the presentation logic itself (e.g., when user clicks on radioButton, then the field x should be enabled) but without actually exercising the application logic. This would allow, for instance, that two completely separate teams handle the UI and business logic development.

Clean Architecture to the Rescue

Now we know that the problem with the traditional approach, in short, is that it creates unnecessary coupling. It couples the UI to the other layers; worse, it couples the domain (or business logic) layer to implementation details such as storage, which can have dire consequences for the testability of the application.

So, what’s the solution? Well, I’ve almost spelled it out in the previous paragraph: restore the domain to its rightful location, at the center of the architectural diagram.

Clean Architecture: A Bit of History

To the best of my knowledge, the first mention of clean architecture is from a blog post by Robert C. Martin, published back in 2011. He then proceeded to write another, more famous post on the subject in the next year. In this newer post, Robert provides a more formal definition of clean architecture, complete with diagrams.

Right at the beginning, Robert explains that the architecture he’s proposing isn’t necessarily new. Actually, it’s an attempt to integrate and create a shared vocabulary about several architectural ideas that had appeared in the years prior, such as onion architecture and hexagonal architecture.

Since then, he’s written more posts and given talks on the subjects, and it started gaining momentum. Other developers were inspired enough to create their own sample projects and examples based on clean architecture.

Characteristics of Clean Architecture

So, a quick recap. Up until now we’ve seen

  • the dangers of a highly-coupled codebase;
  • the traditional layered architecture commonly used to try to prevent those dangers;
  • why the aforementioned architecture isn’t always a good solution; and
  • a bit of history and background on clean architecture.

Finally, now it’s time to actually see what this whole clean architecture thing is about.

Layers and Organization

The common depiction of clean architecture is a diagram consisting of concentric circular layers, very reminiscent of the onion architecture, which is not a surprise. The idea here is that the inner layers are high-level, abstract policies; the outer layers are technical implementation details.

The proposed layers are

  • Entities. Here should live the business objects of your application, generally called “entities,” in DDD lingo.
  • Use cases. In this layer reside the use cases; in short, we could say that these are objects that represent an action a user can perform in the application.
  • Interface adapters. This layer contains code whose goal is basically to provide a bridge between the outside world and the immaculate world inhabited by the use cases and entities. Models, views, presenters, and repository implementations all should go here.
  • Frameworks and drivers. Finally, we have the layer that basically represents external agents: the web, the database, etc.

The Dependency Rule

The aforementioned layer organization isn’t set in stone, though. There’s nothing really stopping you from using more than that if you need to. What you really have to remember is to follow the dependency rule: all dependencies should point inwards.

The entities layer shouldn’t be aware of any other layer in the application. There should be no change in the outer layers that causes a change to it. The opposite holds, though: a change in the entities layer can and probably will cause changes in next layers.

Your Journey to a Clean and Safer Architecture Is Just Beginning

Today we’ve just touched the tip of the iceberg in regards to clean architecture. There’s a lot more to know about it, of course. My intention with this post was to present what might be a novel idea, to excite your curiosity and leave you wanting more.

In the next posts, we’ll continue to explore the subject here on the NDepend blog. We’ll build a sample application in order to put these guidelines into practice. And we’ll test these ideas against the most realistic scenarios we can create in a blog post.

We’ll also show you how you can use NDepend to help you achieve clean architecture even faster. Stay tuned!

Carlos Schults

Carlos Schults is a .NET software developer with experience in both desktop and web development, and he’s now trying his hand at mobile. He has a passion for writing clean and concise code, and he’s interested in practices that help you improve app health, such as code review, automated testing, and continuous build. You can read more from Carlos at carlosschults.net.

Comments:

  1. At the risk of sounding nerdy, I’m excited about this. There might be a good “reference” example of Clean Architecture out there, but perhaps I didn’t Google hard enough to find it. So far I’ve just been able to try to apply some of the principles. I’m looking forward to seeing what this looks like built by someone who gets it.

  2. Sounds nice, but is often totally impractical. Examples:

    1. Suppose you only want certain options in the UI to appear depending on the setting of other elements in the UI which have a business purpose. This often requires coding business logic in the UI without implementing an inefficient process of communicating through layers, a process that usually affects the UI in a user-unfriendly way.

    2. I work in a Microsoft shop, something I haven’t always been happy with, since I could have often done my work much more quickly with fewer bugs using open source technologies. I tried to make our code more database agnostic by using OLE DB adaptors, rather than SQL Server DB adaptors. The OLE DB adaptors, developed in an open environment of adhering to the least common denominator, dealt with stored procedure parameters numerically, ignoring the names. This contributed to hard to troubleshoot bugs until I discovered that the SQL Server adaptors actually took the parameter names into account and switched to them. The OLE DB was a waste of time and resources, especially since the use of open source databases was better implemented in non-Microsoft languages to begin with.

  3. Very nice article.
    Some aspects i’m missing are:

    – (G)UI is twofold: 1) Data to be handled by users (she/he needs to read it and take action on it and has to enter it from a sources he must have at hand) and needs syntactical and semantical checks, and 2) presentation and input of data to/from the user which depends e.g. on view ports, navigation necessities and alike to optimize the perception of users. These two aspects may not be defined in one layer.

    – Interfaces to other systems are quite similar to UIs. They need their one layer.

    All in all, I doubt that architectural layers can be “independent”. They must be commonly defined oriented on the class of tasks the apps produced with them.

Leave a Reply

Your email address will not be published. Required fields are marked *