Clean Architecture Example & Breakdown

Clean Architecture is pretty popular and I’ve been asked a lot about it directly and indirectly. I decided to take a Clean Architecture Example (Template) and give my thoughts about where I see value in using it, in which context, and what I don’t like about Clean Architecture and/or how it’s organized, in practice.

YouTube

Check out my YouTube channel where I post all kinds of content that accompanies my posts including this video showing everything that is in this post.

Clean Architecture

Many people have asked me for my opinion on Clean Architecture. They have also pointed me to Jason Taylors C# Clean Architecture Template. So here’s my breakdown of what I think about Clean Architecture, Templates, where I see the value, and where I don’t.

First let me cover what Clean Architecture is, for those unfamiliar. At the very middle is Entities that represent the core of your domain. This is where your business rules (and/or domain model) should live. A layer outside of that is Use cases, this is your application layer that is invoking your domain. Often times you will also define interfaces here that your application logic will use. The next layer outside of that is generally for defining implementation for those interfaces defined in the uses cases layer. These can be things like implementation for data access, file system, etc. Lastly, the outermost layer is for things like your UI/web framework which is the input into the system.

The key to all of this no matter how you break apart the responsibility of layers is about the direction of dependencies.

It’s about coupling and managing it. The very inner core of your domain will have no dependencies. While the outer layer will depend on one or many of the inner layers. If you’re familiar with afferent and efferent coupling, the core has an efferent coupling of 0 and an afferent coupling of 1. As you go out the reverse starts to occur where the outermost layer has an efferent coupling of 1 or more and an afferent coupling of 0.

Templates

This post (and video) are not a criticism of the Clean Architecture Template. I have a love/hate relationship with templates because it’s really difficult to provide context for when something should or shouldn’t be used. The problem with templates and sample applications is they are simple. Most applications may start simple but often grow over time along with complexity. Because applications evolve and grow, what was being done in a template may no longer fit what you’re currently building.

I also don’t think that a template even fits as a starting point for a new application because unless you are sure it fits the context of what you’re going to build. Speaking directly about this template, if you’re creating a simple application, I don’t think it even makes sense to use this template. Here’s why…

Project Breakdown

The template is broken down into 4 projects to represent the various layers and enforcing the direction of dependencies. The 4 projects in the template are Domain, Application, Infrastructure, WebUI.

Domain

The domain project is the core of the application. It does not have any other project references. Inside of it as Entities which are ultimately used by Entity Framework. As mentioned, templates are simple. Because of this, this simple template is using a Todo list as an example. There’s zero logic related to a to-do list sample. This means that the domain entities are really just data buckets that are representing our data model. They have no behavior. I would suspect in a complex domain that you would likely Aggregate with Entities and actual domain logic. But because this template is simple, as expected, you wouldn’t be aware that’s where the actual domain logic would live. It’s not a place to store data models.

Application

The Application project references the domain Project. This project is using MediatR to define commands, queries, and their respective handlers. These handlers are what are using the Entities from the Domain Project. This project also defines interfaces (abstractions) that are used for things like Data Access inside the handlers. However, the implementation for the interfaces lives in the Infrastructure Project.

Here’s the IApplicationDbContext defined.

Infrastructure

This project contains the implementation for the interfaces defined in the Application Project. This template it’s using Entity Framework for data access. There is an ApplicationDbContext that implements the IApplicationDbContext as well as extends the Entity Framework DbContext.

This means that your Application project code doesn’t use an Entity Framework DbContext directly, but uses the IApplicationDbContext.

However, if you look at the IApplicationDbContext snippet above, you will see that you have a leaky abstraction because we’re exposing the DbSet<T> from Entity Framework. This also means that the Application project also has a reference to Entity Framework. To me, this defeats the purpose of the separation of projects/layers.

WebUI

The last outermost project is what is hosting ASP.NET Core. Mainly there are Controllers that use MediatR to convert an HTTP Request into a Command or Query and then are dispatched via MediatR in the Application Project. I do like this approach because it makes a clear distinction between a web request and an application request. Let ASP.NET Core handle web-specific concerns and our Application project won’t have any of those concerns.

However, I do not like the idea of having a Controller with many different actions. Controllers have very low cohesion. You will also notice if you use a command/query dispatcher like MediatR that you likely will have in most cases a 1 to 1 mapping between a Controller action and the actual Handler. In other words, you are only going to create the request object in a single controller action. Because of this, I’d much rather have the controller action live alongside the command and handler.

Vertical Slices

That last statement is what drives me to the use of vertical slices. The flow starts to seem natural of a web request being invoked by ASP.NET Core in a Controller Action, which is then creating an Application Request (Command or Query) and then dispatched to a Handler. Some slices will share Infrastructure, for example, a DbContext, and share the same domain model.

Clean Architecture Example & Breakdown

What this looks like is cutting out a vertical strip from all the layers. Taking all the concerns for each layer and organizing your code that way.

Clean Architecture Example & Breakdown

When moving to vertical slices, you begin to stop thinking about layers and abstractions. The reason being is that a narrow vertical slice doesn’t necessarily need an abstraction. If you want to use your Entity Framework DbContext instead of an interface (abstraction) you can do so that dependency is in a limited number of other slices. If you want to change the implementation to something other than Entity Framework, for example, move to Dapper, you can re-write the data access in the limited number of places as required. You don’t have to swap out the entire layer, you swap out the features/slices you want.

Abstractions become less of a concern and you can start leveraging concrete implementations. It’s worth noting that anytime you create your own abstraction you’re likely going to lose functionality.

Clean Architecture

I don’t have any issues with clean architecture. It’s about coupling and managing it. However, you can also manage coupling by creating specific vertical slices of functionality. Each vertical slice defining its own dependencies (coupling).

Related Posts

Follow @CodeOpinion on Twitter

Software Architecture & Design

Get all my latest YouTube Vidoes and Blog Posts on Software Architecture & Design

Problem Details for Better REST HTTP API Errors

How do you tell your API Consumers explicitly if there are errors or problems with their request? Everyone creating HTTP APIs seems to implement error responses differently. Wouldn’t it be great if HTTP API Errors had a standard? Well, there is! It’s called Problem Details (https://tools.ietf.org/html/rfc7807)

YouTube

Check out my YouTube channel where I post all kinds of content that accompanies my posts including this video showing everything that is in this post.

If you’re creating a RESTful HTTP API, Status Codes can be a good way to indicate to the client if a request was successful or not. The most common usage is 200 range status codes indicate a successful response and using 400 range indicate a client errors.

However, in most client error situations, how do you tell the client specifically what was wrong? Sure an HTTP 400 status code tells the client that there’s an issue, but what exactly is the issue?

Different Responses

Here are two made-up examples that were inspired by 2 different APIs that I’ve recently consumed. Both indicate there a client error, however, they both do this in very different ways.

This first example is using a Status Code of 400 Bad Request, which is good. They provide a response body that has a Message member which is human readable. There is also a documentation member which is a URI, I assume to give the developer more info on why it occurred.

Here’s another example but very different response.

This response has an HTTP 200 OK. Which is interesting, to say the least. Instead, to indicate success or failure, they include in the response body a success member was a Boolean. There is an error object which is useful because it contains an info member, which is human readable. But what’s really nice is the code and type members which appear to be machine-readable. Meaning we can read their documentation, and write the appropriate code to handle when we receive an error with code=101, then we might want to show our end-user some specific message or possibly perform some other type of action.

Commonality

So what do these 2 different HTTP APIs have in common when it comes to providing the client with error information?

Nothing.

They are both providing widely different response body’s and using HTTP status codes completely differently.

This means that every time you’re consuming an HTTP API, you have to write 100% custom code to handle the various ways that errors are returned.

At the bare minimum, it would be nice if there was a consistent and standard way to define the human-readable error message. In one of the responses, this was called “message”, in the other, it was “error.info“.

Problem Details

Wouldn’t it be great if there was a standard for providing error info to your clients? There is! It’s called Problem Details (RFC7807)

   HTTP [RFC7230] status codes are sometimes not sufficient to convey
   enough information about an error to be helpful.  While humans behind
   Web browsers can be informed about the nature of the problem with an
   HTML [W3C.REC-html5-20141028] response body, non-human consumers of
   so-called "HTTP APIs" are usually not.

   This specification defines simple JSON [RFC7159] and XML
   [W3C.REC-xml-20081126] document formats to suit this purpose.  They
   are designed to be reused by HTTP APIs, which can identify distinct
   "problem types" specific to their needs.

   Thus, API clients can be informed of both the high-level error class
   (using the status code) and the finer-grained details of the problem
   (using one of these formats).

Here’s an example using Problem Details for the first example defined above.

Problem Details

type“: URI or relative path that defines what the problem is. In a similar way, as the first example had a “documentation” member, this is the intent of this member as well. It’s to allow the developer to understand the exact meaning of this error. However, this is meant to also be machine-readable. Meaning this URI should be stable and always represent the same error. This way we can write our client code to handle this specific type of error how we see fit. It’s acting in a similar way as an error code or error key.

title“: A short human-readable message of the problem type. It should NOT change from occurrence to occurrence.

status“: The status member represents the same HTTP status code.

detail“: Human-readable explanation of the exact issue that occurred. This can differ from occurrence to occurrence.

instance“: A URI that represents the specific occurrence of the problem.

Here’s another example using Problem Details from the second example above.

Problem Details

Type & Extensions

In the example above, traceId is an extension. You can add any members you want to extend the response object. This allows you to provide more details to your clients when errors occur.

This is important because if you use the type member, which is the primary way you identify what the problem is, then you can provide more extension members based on the type you return.

In other words, in your HTTP API documentation, you can specify a problem type by its URI, and let the developer know there will be certain other extension members available to them for that specific problem.

Multiple Problems

As with everything, nothing is perfect. Problem Details has no explicit way of defining multiple problems in a single response. You can achieve this by defining a specific type, which indicates there will be a problems member which will be an array of the normal problem details members. Just as I described above to leverage bot the type and extensions together.

ASP.NET Core

If you’re using ASP.NET Core, you can use Problem Details today in your Controllers. Simply call the Problem() which returns an IActionResult.

If you don’t have thin controllers and have business logic outside of your controllers, then you can use Hellang.Middleware.ProblemDetails by Kristian Hellang which is a middleware that maps exceptions to problem details.

Source Code

Developer-level members of my CodeOpinion YouTube channel get access to the full source for any working demo application that I post on my blog or YouTube. Check out the membership for more info.

Follow @CodeOpinion on Twitter

Software Architecture & Design

Get all my latest YouTube Vidoes and Blog Posts on Software Architecture & Design

Talking C# Performance with Steve Gordon

We’re talking C# Performance! I sat down and chatted with Steve Gordon to talk about writing performant C# code. When should you be concerned about performance? Does your application code need to be performant? At what cost to readability? How do you measure and test that you’re changes are useful? Steve and I cover all of this in this video.

YouTube

Check out my YouTube channel where I post all kinds of content that accompanies my posts including this video showing everything that is in this post.

When to think about optimizing?

As Steve mentions, it’s easy to get really deep into writing performant code. It’s fun! However, it’s probably a good idea to have a discussion with stakeholders to figure out how much performance matters.

This answer can vary wildly.

If you’re writing framework or library code, I think performance matters. As an application developer, I want framework or library code to get out of my way. Meaning it has as little overhead as possible.

When writing application code, this goes back to figuring where performance matters.

Once you do want to get deep into performance, here are some resources and blog posts that I think would be useful.

BenchmarkDotNet

BenchmarkDotNet helps you to transform methods into benchmarks, track their performance, and share reproducible measurement experiments.

dotMemory

dotMemory allows you to analyze memory usage in a variety of .NET and .NET Core applications: desktop applications, Windows services, ASP.NET web applications, IIS, IIS Express, arbitrary .NET processes, and more.

Follow @CodeOpinion on Twitter

Software Architecture & Design

Get all my latest YouTube Vidoes and Blog Posts on Software Architecture & Design

Links