• Clean Architecture
  • Modular Monolith NEW

How To Approach Clean Architecture Folder Structure

How To Approach Clean Architecture Folder Structure

3 min read · September 24, 2022

Clean Architecture is a popular approach to structuring your application.

It's a layered architecture that splits the project into four layers:

  • Application
  • Infrastructure
  • Presentation

Each of the layers is typically one project in your solution.

Here's a visual representation of the Clean Architecture :

presentation layer clean architecture

How do we create this in our .NET solutions?

Domain Layer

The Domain layer sits at the core of the Clean Architecture . Here we define things like: entities, value objects, aggregates, domain events, exceptions, repository interfaces, etc.

Here is the folder structure I like to use:

You can introduce more things here if you think it's required.

One thing to note is that the Domain layer is not allowed to reference other projects in your solution.

Application Layer

The Application layer sits right above the Domain layer . It acts as an orchestrator for the Domain layer , containing the most important use cases in your application.

You can structure your use cases using services or using commands and queries.

I'm a big fan of the CQRS pattern, so I like to use the command and query approach.

In the Abstractions folder, I define the interfaces required for the Application layer . The implementations for these interfaces are in one of the upper layers.

For every entity in the Domain layer , I create one folder with the commands, queries, and events definitions.

Infrastructure Layer

The Infrastructure layer contains implementations for external-facing services.

What would fall into this category?

  • Databases - PostgreSQL, MongoDB
  • Identity providers - Auth0, Keycloak
  • Emails providers
  • Storage services - AWS S3, Azure Blob Storage
  • Message queues - Rabbit MQ

I place my DbContext implementation here if I'm using EF Core .

It's not uncommon to make the Persistence folder its project. I frequently do this to have all database facing-code inside of one project.

Presentation Layer

The Presentation layer is the entry point to our system. Typically, you would implement this as a Web API project.

The most important part of the Presentation layer is the Controllers , which define the API endpoints in our system.

Sometimes, I will move the Presentation layer away from the actual Web API project. I do this to isolate the Controllers and enforce stricter constraints. You don't have to do this if it is too complicated for you.

Is This The Only Way?

You don't have to follow the folder structure I proposed to the T. Clean Architecture is very flexible, and you can experiment with it and structure it the way you like.

Do you like more granularity? Create more specific projects.

Do you dislike a lot of projects? Separate concerns using folders.

I'm here to give you options to explore. But it's up to you to decide what's best.

Whenever you're ready, there are 4 ways I can help you:

  • Modular Monolith Architecture (NEW): This in-depth course will transform the way you build modern systems. You will learn the best practices for applying the Modular Monolith architecture in a real-world scenario. Join 2,800+ students here.
  • Pragmatic Clean Architecture: This comprehensive course will teach you the system I use to ship production-ready applications using Clean Architecture. Learn how to apply the best practices of modern software architecture. Join 2,800+ students here.
  • Patreon Community: Join a community of 1,050+ engineers and gain access to the source code I use in my YouTube videos, early access to future videos, and exclusive discounts for my courses. Join 1,050+ engineers here.
  • Promote yourself to 48,000+ subscribers by sponsoring this newsletter.

Become a Better .NET Software Engineer

Join 48,000+ engineers who are improving their skills every Saturday morning.

Subscribe to the Newsletter

Join 48,000+ readers of The .NET Weekly for practical tips and resources to improve your .NET and software architecture skills.

Share This Article On:

Clean architecture tutorial: Design for enterprise-scale apps

Clean Architecture Tutorial

  • Blazor WASM 🔥
  • ASP.NET Core Series
  • GraphQL ASP.NET Core
  • ASP.NET Core MVC Series
  • Testing ASP.NET Core Applications
  • EF Core Series
  • HttpClient with ASP.NET Core
  • Azure with ASP.NET Core
  • ASP.NET Core Identity Series
  • IdentityServer4, OAuth, OIDC Series
  • Angular with ASP.NET Core Identity
  • Blazor WebAssembly
  • .NET Collections
  • SOLID Principles in C#
  • ASP.NET Core Web API Best Practices
  • Top REST API Best Practices
  • Angular Development Best Practices
  • 10 Things You Should Avoid in Your ASP.NET Core Controllers
  • C# Back to Basics
  • C# Intermediate
  • Design Patterns in C#
  • Sorting Algorithms in C#
  • Docker Series
  • Angular Series
  • Angular Material Series
  • HTTP Series
  • .NET/C# Author
  • .NET/C# Editor
  • Our Editors
  • Leave Us a Review
  • Code Maze Reviews

Select Page

Clean Architecture in .NET

Posted by Muhammed Saleem | Updated Date Apr 18, 2024 | 0

Clean Architecture in .NET

Want to build great APIs? Or become even better at it? Check our Ultimate ASP.NET Core Web API program and learn how to create a full production-ready ASP.NET Core API using only the latest .NET technologies. Bonus materials (Security book, Docker book, and other bonus files) are included in the Premium package!

In this article, we are going to discuss Clean Architecture in .NET.

So let’s get going.

VIDEO : Clean Architecture with MediatR and CQRS in .NET.

Become a patron at Patreon!

What is Clean Architecture?

Clean Architecture is an architecture pattern aimed at building applications that we can maintain, scale, and test easily.

It achieves this by separating the application into different layers that have distinct responsibilities:

The Clean Architecture layers

  • Domain Layer – The domain layer represents the application’s core business rules and entities. This is the innermost layer and should not have any external dependencies. 
  • Application Layer – The application layer sits just outside the domain layer and acts as an intermediary between the domain layer and other layers. In other words, it contains the use cases of the application and we expose the core business rules of the domain layer through the application layer. This layer depends just on the domain layer.
  • Infrastructure Layer – We implement all the external services like databases, file storage, emails, etc. in the infrastructure layer. It contains the implementations of the interfaces defined in the domain layer.
  • Presentation Layer – The presentation layer handles the user interactions and fetches data to the user interface.

A fundamental principle of Clean Architecture is that the dependencies should point from the concrete outer layers to the abstract inner layers .

This makes it possible to change the specific implementations in the future without affecting other areas of the application. Additionally, the Clean Architecture follows a well-structured approach to organizing the code which helps in maintainability and testability. 

Differences Between the Clean Architecture and Onion Architecture

Both the Clean Architecture and the Onion Architecture pattern follow the same principles and aim to achieve similar goals such as separation of concerns, loose coupling of components, etc. Many developers consider these as different interpretations of the same fundamental concepts due to their similar goals and principles. However, they do have some slight differences.

Clean Architecture separates different layers based on the level of abstraction , with dependencies always pointing inwards from concrete outer layers to abstract inner layers.  It is significant for large projects that require their components to be decoupled and need to support independent development and deployment cycles.

On the other hand, Onion Architecture is more focused on the central layer known as the Core, using interfaces and dependency inversion to decouple the application layers and enable a higher degree of testability. It is focused on domain models and business rules, with all additional concentric layers pointing towards the core. It is particularly beneficial for projects that need to adhere to a domain-driven design approach and is suited for small to medium-sized projects.

In this way, while they share similar foundational concepts, the choice between Clean Architecture and Onion Architecture can depend on the specific needs and scale of the project.

How to Implement Clean Architecture in .NET?

Now let’s see how to implement an ASP.NET Core Web API project using the Clean Architecture design pattern. We’ll take a look at the different layers and what code needs to go in each layer.

Let’s start by creating a new solution for the application:

Shows Clean Architecture project structure of our ToDoApp

First, we create a solution called ToDoApp with three folders – Core , Infrastructure, and Presentation . After that, we add the following projects to it:

  • ToDoApp.Domain – This is a class library project to represent the Domain layer of the application.
  • ToDoApp.Application – This is a class library project as well and represents the Application layer of the application. This project will refer only to the ToDoApp.Domain project.
  • ToDoApp.Infrastructure – This is another class library project for representing the Infrastructure layer of the application.
  • ToDoApp.Persistence – This is a class library project as well and part of the Infrastructure layer. This is specifically for dealing with the data persistence of the application.
  • ToDoApp.API – This is an ASP.NET Web API project that represents the Presentation layer of the application. Ideally, this should depend on just the ToDoApp.Application project. However, for dependency injection, we will need to add a reference to ToDoApp.Infrastructure and ToDoApp.Persistence . But remember that those should be just run time dependencies and we should not create any compile time dependencies with those layers. 

Here notice that we organize the Domain and Application projects into the Core folder. Similarly, the Infrastructure and Persistence projects go into the Infrastructure folder. However, the API project goes into the Presentation folder. By doing so, we will have a solution structure that follows the Clean Architecture principles.

The Domain Layer

Now let’s see what code needs to go in the Domain Layer. The Domain layer is primarily for keeping the entities and interfaces of the application.

Keeping this in mind, first, let’s add the ToDoItem entity class:

In the class, we define the Id, Description , and IsDone properties.

After that, let’s add the IToDoRepository interface:

In the repository interface, let’s just add two methods – GetAllAsync() and CreateAsync() . This is for implementing the repository pattern . The repository pattern introduces an abstraction layer between the data access layer and the business logic layer of the application. This improves code maintainability, readability, and testability. 

The Application Layer

While implementing Clean Architecture in .NET, CQRS with MediatR is a popular choice.

CQRS (Command Query Responsibility Segregation) design pattern separates the components responsible for reading and writing data.

Similarly, MediatR helps in implementing the mediator pattern. By using a mediator pattern, we can manage communications between different parts of the application that are loosely coupled.

In this example, we are going to use CQRS and Mediator patterns for implementing the application layer of our ToDoApp. Keeping this in mind, we are going to create a command for creating a ToDoItem and a query for listing all the ToDoItem instances.

First, let’s add the MediatR NuGet package:

dotnet add package MediatR

Then, let’s create a command:

The CreateToDoItemCommand class implements the IRequest interface defined in the MediatR library and provides the response type as the parameter. We add the Description property to the class.

After that, let’s create a handler for our CreateToDoItemCommand class:

The CreateToDoItemCommandHandler class implements the IRequestHandler interface from the MediatR library and provides both the request and response types as parameters. In the Handle() method, we call the CreateAsync() method of the repository and pass the ToDoItem into it.

With that, the command is ready. 

Now, let’s create a simple query:

Here the ToDoItemQuery class body is empty as there are no parameters for this operation and the response type is a list of ToDoItem .

After that, let’s add a handler for our query class:

In the ToDoItemQueryHandler class we implement the Handle() method, internally calling the GetAllAsync() method of the repository.

Finally, let’s add the dependency injection for MediatR as well:

With that, the Application layer is ready.

The Infrastructure Layer

In the Infrastructure layer, let’s add a concrete service with data storage logic. To do that, we are going to add an in-memory data storage service to the Persistence project as this is related to data persistence.

Let’s create an InMemoryToDoRepository service that implements the IToDoRepository interface:

Here first we define a list to hold the ToDoItem . Then, in the CreateAsync() method, we add the ToDoItem to an in-memory list. Similarly, in the GetAllAsync() method, we get all items from the list.

That’s all for the Infrastructure layer for now. If we have integrations with other external components such as email services, file storage services, etc., we can add separate sections or projects for each of those.

The Presentation Layer

In the Presentation layer, we have an ASP.NET Core Web API project.

So let’s go ahead and add a controller:

In the ToDoItemController class, we inject the Mediator and define two action methods- Get() and  Post() . The Get() method sends a request to the ToDoItemQueryHandler   class using MediatR . Similarly, the Post() method sends a request to the CreateToDoItemCommandHandler class.

Here, for the sake of simplicity, we are using the command object directly in the API Controller. However, in real-world projects, it is always better to create separate Data Transfer Objects (DTOs) for each layer and map them to the respective types before sending them into the next layer.

Finally, let’s add the dependencies into the DI container:

First, we call the AddApplicationDependencies() method in the Application project. After that, we add the InMemoryToDoRepository type to the DI container.

With that, we have created an ASP.NET Core Web API project that follows the Clean Architecture design pattern. We should be able to create new ToDoItem instances and list all the items by running the app.

Advantages of Clean Architecture

As the above example shows, Clean Architecture has several advantages. Let’s discuss those in detail.

Clear Separation of Concerns

The Clean Architecture separates our application into clear and distinct layers such as Domain , Application , Infrastructure , Presentation , etc.

Each layer is independent and has a distinct responsibility. This makes the code more organized and maintainable. Additionally, it makes our code easier to understand. With Clean Architecture, we will have a clear picture of where certain behaviors and logic should live in our application.

Loose Coupling Between Components

In Clean Architecture, the UI and infrastructure components depend only on the application’s core.

This means we can change those components without affecting other parts of the application:

Shows Clean Architecture dependencies internal and external dependencies

For example, if we decide to change the in-memory repository with an SQL database using EF Core , we just need to change the concrete implementation of the repository in the Infrastructure layer:

We do that by replacing the InMemoryToDoRepository class with a new class SqlToDoRepository that implements the IToDoRepository interface. In the new repository class, we inject the EF Core DbContext and change the methods to save and retrieve from the SQL database using EF Core methods.

After that, we update the DI container to use this new repository. Other parts of the application such as the Core and Presentation need not be aware of this change.  

Testability

Another advantage of Clean Architecture is the ability to test each layer independently. The business logic resides at the core of the application and can be tested in isolation of the Infrastructure and Presentation layer. 

For instance, we can write unit tests for the application layer commands and handlers independently.

First, let’s write a unit test for CreateToDoItemCommand :

After that, let’s write a unit test for ToDoItemQuery :

Likewise, if we had any entity-specific behaviors or validations in the Domain layer, we could write independent tests for those. Not only that, we can write independent tests for UI or Infrastructure components as well. 

Scalability

With Clean Architecture, it is possible to scale each layer of the application independently. This gives us the flexibility to adapt to the changing performance requirements of the application. For example, the Core business logic layer can be scaled separately from the Infrastructure or the Presentation layers. We can either scale horizontally by adding more instances of services or vertically by increasing computing power, memory, etc. for specific services.

Team collaboration

With Clean Architecture, it is possible to have different teams working independently on different application layers. This gives us the flexibility of different teams with different skill sets working on different layers in parallel without much dependency on other teams. Of course, this results in faster development as the time lost by waiting on dependencies is minimal.

Disadvantages of Clean Architecture

While Clean Architecture offers a plethora of advantages, it is not without some potential disadvantages and challenges that can occur in certain scenarios such as:

Increased Complexity & Abstraction – The structured and layered approach of Clean Architecture can potentially lead to increased complexity. For smaller projects, creating these layers and abstractions can be an overhead and there could be a steep learning curve as well.

Dependency Injection Overhead – Setting up dependency injection for all the layers and components can be cumbersome as the project grows. 

Performance Issues – In some cases, strict separation of concerns might introduce performance issues. For instance, we might need to map data between different layers and make multiple calls within an operation which may be performance-intensive. 

Keeping this in mind, we should carefully evaluate the benefits of Clean Architecture against potential drawbacks before adopting this pattern for our project .

When to Use Clean Architecture?

Even though Clean Architecture is a software design pattern with many benefits, it’s not a one-size-fits-all solution for all projects. So we should carefully evaluate the requirements of our application to determine if Clean Architecture is a good option for it. Here are some scenarios where we can consider using Clean Architecture:

  • Large, complex, and evolving projects   – Separation of concerns helps manage large and complex projects by making sure the core domain logic will be independent of both the UI layer and infrastructure layer and remains unchanged. 
  • Projects with large testability requirements – The layered structure and loosely coupled components make it easier to write unit tests and integration tests in different layers. This is specifically helpful for long-term projects that have very high test coverage requirements.
  • Projects where multiple development teams work together – The clear separation of concerns makes it easier for multiple teams to work on different layers without much dependency on other teams.
  • Projects that need to support infrastructure changes in the future with minimal impact – Since infrastructure doesn’t have a direct coupling with core business logic, we can change the infrastructure components in the future with minimal impacts to other areas.

In this article, we explored Clean Architecture with ASP.NET Core Web API development. We looked at its principles, different layers, and implementation. Apart from that, we discussed some advantages and potential disadvantages that can occur while using Clean Architecture. Going beyond this, we looked at scenarios where Clean Architecture is a good choice for our projects.

guest

Join our 20k+ community of experts and learn about our Top 16 Web API Best Practices .

Search for articles

Sorry, but we couldn't find any matches..., popular articles, making the leap from azure to codemagic, how tuist migrated from github actions to codemagic for faster and more reliable ci, codemagic helps mobi lab deliver mission-critical projects while saving them time and money, clean architecture explored.

This article is written by Jahswill Essien

It’s your first day at an exciting company, and everything’s going great. It’s time to familiarize yourself with the codebase. So you fork it from GitHub, and lo and behold, your warm smile is replaced with utter confusion. The codebase is filled with spaghetti code. Simply, it’s chaotic.

We developers are often faced with scenarios like this. True, we all have our unique coding styles — however, we need some guiding principles to adhere to in order to avoid writing chaotic code.

Over the years, many software designs and architecture patterns have sprung up with the aim of adding clarity and structure to the way software developers write applications.

This article aims to explore the clean architecture design pattern. Its intended audience is developers who are comfortable with the Flutter framework and are concerned about using the right architecture for their Flutter apps.

Spaghetti code is unstructured, unmaintainable, and anti-patterned source code.

Before delving into why you should care about the architecture of your software, it’s crucial to understand the concepts of a software application’s components and elements .

Components and elements of software

For this article, we will adhere to the following definitions.

Components are detachable parts of a system. Although they communicate with other parts of the systems, they can be developed independently.

The organization of components and the way they interact with each other forms the structure of the software architecture.

We can subdivide software into two major elements: policy and details .

The policy element is the main sauce of your software. It encompasses the business logic of your application.

The details are elements that are not directly related to the business logic of your software.

If you are developing software that automates employee payments, for example, the policy element is the logic of the system that tells it when to make payments, whom to make them to, and how much should be paid.

On the other hand, the details are things like the database, servers, frameworks, and devices used for this payment system.

The policy doesn’t care about the details of the system since they can be replaced or their implementation can be deferred. For instance, I can decide to change my database from a SQL to a NoSQL database.

Why should you care about your software’s architecture?

If you were to open the codebase of a two-screen app and find that all of the screens, network and local repositories, and network client classes were defined in a single Dart file, it would be weird, but you could overlook it.

However, if you were to find the same situation in a more complex program like a banking app, it would be chaotic and difficult to manage. This is because a banking app typically involves a large amount of data and functionality, and organizing it all within a single file would make it incredibly unwieldy and hard to maintain. Good luck fixing a bug in this codebase.

You start to appreciate the essence of architecture in your software when you begin to add more and more features and use cases.

Have you ever revisited a project you haven’t worked on in months and can’t figure out what the heck is going on? Have you worked with a complicated codebase and broken the app by making a few slight changes? Have you been in a situation in which you can’t find certain classes in a codebase? If your answers to some or all of these questions are yes , then you should care about the architecture of the software you build.

What makes good architecture?

When considering architecture for your software, remember that good architecture should accomplish the following things:

  • Make a system easy to understand, develop, maintain, and deploy
  • Decouple the system’s policy from its details (it should not depend on the framework, state management, database, or servers you use)
  • Make your system testable
  • Encourage code reusability

In other words, a well-architected Flutter codebase should make it easy for you to do the following:

  • Locate and understand files in the codebase
  • Change back-end technology, for example, from Firebase to RESTful APIs (or vice versa)
  • Switch state management solutions
  • Write unit, widget, and integration tests

What is clean architecture?

The clean architecture was proposed by Robert C. Martin and relies heavily on the SOLID principles . Clean architecture aims to encourage developers to design and structure source code in a clean and organized way. It follows the separation of concerns design principle by introducing four distinct layers.

Separation of concerns is a design principle that ensures that software components are grouped based on the correlation between the kind of work they execute.
Image by Robert C. Martin

This image illustrates the clean architecture proposed by Robert C. Martin. We can see that it comprises four different layers pointing inwards. It doesn’t tell us much about structuring a Flutter app, but it does lay down the core concepts of clean architecture: the separation of concerns and the dependency rule .

It comprises these layers:

Frameworks and Drivers : This layer contains the “details” of a system. These can include the user interface (UI), devices, or external interfaces. Assuming we are building an ordering machine, this layer deals with the machine interface.

Interface Adapters : This layer consists of things like controllers , state-holders , or view-models . It is responsible for getting data from the UI or device and transforming it into something usable for the business logic. Considering our ordering machine system, this layer will consist of objects that hold the user’s input from the screen, and it sends it to the use case for processing.

Application Business Rule/Use Cases : This layer deals with the specific intent of the system. It encompasses application logic that helps accomplish business needs. This rule governs how the application behaves under certain conditions and is specific to the application. Using our ordering machine as a case study, this would be the logic that handles user input to order food or drinks, calculate the total cost of the order, and validate that the user has enough funds in their wallet to complete the transaction.

Enterprise Business Rule/Entities : This layer deals with core logic specific to business needs. Unlike application logic, the business rule covers multiple applications. Examples of the business rules for the ordering machine include rules that manage how data is stored across applications (client and server-side applications), govern data security, control access to data, and so on.

One thing to note is that the directional flow is inwards . The arrow direction signifies that an outer level is dependent on the inner level.

Frameworks and Drivers depend on Interface Adapters, which depend on Use Cases, which depend on Entities.

Clean architecture for mobile applications

Quoting directly from Robert’s text, “There’s no rule that says you must always have just these four layers. However, the Dependency Rule always applies. Source code dependencies always point inwards.” Therefore, for mobile applications, we can categorize the layers of clean architecture into three layers.

Source: https://www.youtube.com/watch?v=K1aC7eO6vbw

Reso Coder designed a more detailed architecture representation for Flutter apps.

Image by Reso Coder

Presentation layer

The presentation layer deals with the UI of the system. In practical terms, any code that displays information on the screen or handles UI logic ought to be in this layer. Specifically, widgets, controllers, and state-holders are citizens of the presentation layer.

This layer depends on the domain layer and must not have any reference whatsoever to the data layer.

Domain layer

The domain layer sits between the presentation layer and the data layer. It contains business logic. This layer consists of entities, use cases, and contracts — (abstract) classes of repositories. It’s a crime (according to clean architecture rules) for this layer to reference classes, functions, and imports of the presentation or data layer.

To bridge the gap between the data layer and domain, we use the dependency inversion rule .

The dependency inversion rule states that a higher-level module should not depend on the concrete implementation of lower-level modules. Rather, it should depend on abstractions or interfaces.

The data layer contains code that communicates with the server or database. It consists of an implementation of contracts (abstract classes) defined in the domain layer, local/remote data sources, services, models, and so on.

Demonstration

To further understand this concept and how components interact with each other, we have a demo application that fetches the characters of the cartoon Ricky and Morty and has a feature that enables you to create and delete your favorite characters.

Run the command git clone [email protected]:JasperEssien2/ricky_and_morty.git to clone the project.

You’ll see three top-level folders under the lib folder. This folder arrangement corresponds to the layers of clean architecture.

The presentation layers contain necessary widgets and a data controller.

Domain layer walkthrough

The domain layer contains the following:

A CharacterEntity class, which is defined in the character_entity.dart file. It is just a simple data class. Think of entity objects as model classes but for the domain layer. Entities should only contain data that is needed to display on the UI.

A contract, or an abstract class with abstract methods, is in the repository.dart file. This is the bridge between the domain layer and the data layer.

The use_cases folder under the domain folder defines all the use cases of this app. We will spotlight the DeleteFavouriteCharactersUseCase class to understand the role of use cases in clean architecture.

lib/domain/use_cases/delete_favourite_character_use_case.dart

In the above snippet, the use case is responsible for deleting a favorite character from the database. Here are a few key points to note when defining use cases:

A use case can only depend on the repository contract and other use cases

A single use case class should only perform one action per class

You make the instance of a Dart class callable as a function by defining a call() method

You’re probably thinking, “Should I create a separate use case class for each use case of my application?” The answer to that is yes if you intend to adhere to clean architecture strictly.

As discouraging as this sounds, it has some benefits. For example, if you encounter an issue with deleting characters, you can quickly identify and fix it. It encourages code reusability, as use cases can be reused.

At the end of the day, users are only concerned with the UI of our app, not its internal code. The next section will walk you through how the domain layer connects with the presentation layer.

Presentation layer walkthrough

The presentation folder contains all our widgets and state-holder classes.

The state-holders are simply components that store and manage the state of an application. In clean architecture, state-holders depend on use case classes. The code snippet below shows the fetch() method of the CharactersDataController state-holder class and how it uses the get characters use case to fetch characters from the database.

On the home screen, a reusable widget named Consumer is defined. Its job is to listen to DataController — a subclass of ChangeNotifier — and rebuild when it is updated.

Even without prior knowledge of the API response data structure, it’s possible to create a functional app by focusing on the application’s use cases. The data logic can be worked on independently of other layers.

Data layer walkthrough

In the data layer of the codebase, a CharacterModel class is defined in the file data/character_model.dart . This is a data class with the ability to serialize and deserialize JSON data.

You may be wondering why we have to define data classes for the domain layer (entities) and data classes for the data layer (models). The reason is simple: Clean architecture encourages the separation of concerns.

One of the rules of clean architecture is that a component should have only one reason to change . With this, we can ensure each layer has a clear and distinct responsibility.

For example, if the data structure of the API response changes, we’ll be forced to modify the model class. Because our presentation layer utilizes the entity data class, both the domain and presentation layers remain unaffected. This approach improves the overall modularity and maintainability of the codebase.

We can introduce mapper classes that will be responsible for mapping a model class to and from an entity class.

In the repository contract, entity classes are typically used as the return value. This means that the conversion of model classes, which are obtained from data sources, to an entity class (or vice versa) is done in the repository implementation.

But what are data sources? To use an analogy, think of a data source as a well of water. Requesting data from the server or database is akin to pumping water out of the ground. The repository acts as the channel by which water flows from the well to the tank.

Below is a snippet of a remote source defined in the app.

lib/data/data_sources/remote_data_source.dart

The repository contract is implemented in this layer, and it depends on the data source.

With this, you are now equipped to build your app using clean architecture.

Now let’s look at the practical benefits of clean architecture.

Benefits of clean architecture

Some benefits of using clean architecture are as follows:

Fosters collaboration between teams

The use of clean architecture leads to the creation of loosely coupled applications. This means that there is minimal dependence between each layer. As a result, various teams can work on different layers of the application without interfering with each other’s work.

You don’t have to resolve complicated merge conflicts and fixes if multiple team members modify some part of the codebase simultaneously, breaking the part of the codebase you are working on.

Highly maintainable codebase

Since the system’s components are arranged systematically, it’s easy for team members to modify parts of the system without affecting other parts. Additionally, clean architecture helps team members identify the appropriate layer to develop new code, promoting a clear and organized development process.

Enhances code testability

By following clean architecture, you make your codebase testable. Separation of concerns makes it easy to test business logic independently of details. Clean architecture also encourages the abstraction of dependencies, making it easy to replace these dependencies with a mocked version during testing.

Enables easy replacement of dependencies with alternative implementations

Another significant advantage of clean architecture is that you can provide an alternative implementation quickly and effortlessly.

For practical purposes, let’s assume our team decides to use GraphQL instead of the RESTful API for our app. You can effect this change by creating a concrete implementation of the remote data source. Even if the data structure changes, you can add a model class to suit the new data structure.

To learn more about GraphQL, see our article on how to implement GraphQL .

You easily altered the underlying request client without affecting the other layers.

With this benefit, you can also defer making decisions that affect the details of the software (database, back-end technology, and so on) while focusing on what matters.

Downsides of clean architecture

As you might have noticed already, there are also some downsides to clean architecture.

Increased development time

Clean architecture can increase development time since modularization and separation of concerns are prioritized, leading to the creation of multiple files to achieve a simple task.

Introduces more boilerplate code

Boilerplate code is sections of code that are repeated in multiple places with little to no variation. For example, we have to define model and entity data classes, which aren’t very different.

The increase in boilerplate code also increases the overall code that needs to be maintained by developers.

Increases chances of over-engineering

Over-engineering is solving a problem in a more complicated way than necessary.

Using a clean core architecture for a simple application is over-engineering, as you will introduce unnecessary abstractions and layers, adding overhead complexities.

Your dedication to reaching the end of this article shows you care about the architecture of the software you build. The information presented in this post may have been a lot to absorb, but it was intended to demonstrate clean architecture and educate you on its existence and significance. With some more practice, you’ll soon get the hang of it.

In practice, applying core clean architecture principles to a basic application like the one we demoed is excessive. The main objective here was merely to demonstrate the concepts of clean architecture.

Take note that during software development, tradeoffs must be made. Some developers may prefer not to utilize use case classes because they consider it an unnecessary step. In this case, their state-holder classes depend directly on the repository.

While it’s not necessary to adhere rigidly to the rules of clean architecture, it’s essential to uphold its principles. Remember that clean code doesn’t only make your team and future coworkers’ lives easier — it saves your future self from dealing with a messy codebase.

  • “Architecture: The Domain Layer - MAD Skills” — Android Developers
  • “Flutter TDD Clean Architecture Course [5] – Contracts of Data Sources” — Reso Coder
  • “The Clean Architecture” — Robert C. Martin
  • “Clean Architecture in Android in 5 minutes” — Renaro Santos

How did you like this article?

Thanks what hurt your eye, thanks for your feedback.

This will help us improve our content.

We are happy you like our content.

Related articles

Flutter tutorial: architect your app using provider and stream, latest articles, deploy your app to app store connect with codemagic cli tools and github actions, upcoming changes to google play for developers, grow your business with codemagic.

Sign up today and deliver your apps in record time

This site uses cookies. By continuing to use our site, you agree to our use of cookies. Learn more

Jason Taylor

Developer • Speaker • Microsoft MVP

Clean Architecture with .NET Core: Getting Started

Over the past two years, I’ve travelled the world teaching programmers how to build enterprise applications using Clean Architecture with .NET Core. I started by providing a sample solution using the iconic Northwind Traders database. Recently, I’ve developed a new Clean Architecture Solution Template for .NET Core.

This post provides an overview of Clean Architecture and introduces the new Clean Architecture Solution Template, a .NET Core Project template for building applications based on Angular, ASP.NET Core 3.1, and Clean Architecture.

Let’s start with an overview of Clean Architecture.

With Clean Architecture, the Domain and Application layers are at the centre of the design. This is known as the Core of the system.

The Domain layer contains enterprise logic and types and the Application layer contains business logic and types. The difference is that enterprise logic could be shared across many systems, whereas the business logic will typically only be used within this system.

Core should not be dependent on data access and other infrastructure concerns so those dependencies are inverted. This is achieved by adding interfaces or abstractions within Core that are implemented by layers outside of Core . For example, if you wanted to implement the Repository pattern you would do so by adding an interface within Core and adding the implementation within Infrastructure .

All dependencies flow inwards and Core has no dependency on any other layer. Infrastructure and Presentation depend on Core , but not on one another.

presentation layer clean architecture

This results in architecture and design that is:

  • Independent of frameworks it does not require the existence of some tool or framework
  • Testable easy to test – Core has no dependencies on anything external, so writing automated tests is much easier
  • Independent of UI logic is kept out of the UI so it is easy to change to another technology – right now you might be using Angular, soon Vue, eventually Blazor!
  • Independent of the database data-access concerns are cleanly separated so moving from SQL Server to CosmosDB or otherwise is trivial
  • Independent of anything external in fact, Core is completely isolated from the outside world – the difference between a system that will last 3 years, and one that will last 20 years

In the above design, there are only three circles, you may need more. Think of this as a starting point. Just remember to keep all dependencies pointing inwards.

Let’s take a look at a simple approach to getting started with the new Clean Architecture Solution Template .

Solution template

This template provides an awesome approach to building solutions based on ASP.NET Core 3.1 and Angular 8 that follow the principles of Clean Architecture. If Angular is not your thing, worry not, you can remove it with ease. In this section, you will install the template, create a new solution, and review the generated code.

Prerequisites

The first step is to ensure you meet the following prerequisites:

  • .NET Core SDK  (3.1 or later)
  • Node.js  (6 or later)

Check the .NET Core version by running this command:

Check the node version by running this command:

Next, install the solution template using this command:

Create a new solution

Creating a new solution is easy. Within an empty folder, run the following command:

The following message will be displayed:

This command will create a new solution, automatically namespaced using the name of the parent folder. For example, if the parent folder is named Northwind , then the solution will be named Northwind.sln , and the default namespace will be Northwind .

The solution is built using the Angular project template with ASP.NET Core. The ASP.NET Core project provides an API back end and the Angular CLI project provides the UI.

Note Read Use the Angular project template with ASP.NET Core to learn more about this approach.

Launching the solution from Visual Studio 2019 is trivial, just press F5 .

In order to launch the solution using the .NET Core CLI, a few more steps are required. You can learn more by visiting the above link, but I’ll include the information here for completeness.

First, you will need an environment variable named ASPNETCORE_Environment with a value of Development . On Windows, run SET ASPNETCORE_Environment=Development . On Linux or macOS, run export ASPNETCORE_Environment=Development .

Next, run the following command from the solution folder:

Note The initial build will take a few minutes, as it will also install required client-side packages. Subsequent builds will be much quicker.

Then run dotnet run to start the application. The following message will be displayed:

The port is usually 5001. Open the web site by navigating to https://localhost:port .

Note You will also see a message similar to the following: NG Live Development Server is listening on localhost:port, open your browser on http://localhost:port Ignore this message, it’s not the URL for the combined ASP.NET Core and Angular CLI application

If everything was successful you will see the following:

presentation layer clean architecture

Let’s take a look at the structure of the newly generated solution.

Solution structure

The solution template generates a multi-project solution. For a solution named Northwind , the following folder structure is created:

presentation layer clean architecture

The project names within src align closely to the layers of the Clean Architecture diagram, the only exception being WebUI , representing the Presentation layer.

The Domain project represents the Domain layer and contains enterprise or domain logic and includes entities, enums, exceptions, interfaces, types and logic specific to the domain layer. This layer has no dependencies on anything external.

The Application project represents the Application layer and contains all business logic. This project implements CQRS (Command Query Responsibility Segregation), with each business use case represented by a single command or query. This layer is dependent on the Domain layer but has no dependencies on any other layer or project. This layer defines interfaces that are implemented by outside layers. For example, if the application needs to access a notification service, a new interface would be added to the Application and the implementation would be created within Infrastructure .

The Infrastructure project represents the Infrastructure layer and contains classes for accessing external resources such as file systems, web services, SMTP, and so on. These classes should be based on interfaces defined within the Application layer.

The WebUI project represents the Presentation layer. This project is a SPA (single page app) based on Angular 8 and ASP.NET Core. This layer depends on both the Application and Infrastructure layers. Please note the dependency on Infrastructure is only to support dependency injection. Therefore Startup.cs  should include the only reference to Infrastructure.

The tests folder contains numerous unit and integration tests projects to help get you up and running quickly. The details of these projects will be explored in a follow-up post. In the meantime, feel free to explore and ask any questions below.

Technologies

Aside from .NET Core, numerous technologies are used within this solution including:

  • CQRS with MediatR
  • Validation with FluentValidation
  • Object-Object Mapping with AutoMapper
  • Data access with Entity Framework Core
  • Web API using ASP.NET Core
  • UI using Angular 8
  • Open API with NSwag
  • Security using ASP.NET Core Identity + IdentityServer
  • Automated testing with xUnit.net , Moq , and Shouldly

In follow-up posts, I’ll include additional details on how the above technologies are used within the solution.

Additional resources

In this post, I have provided an overview of Clean Architecture and the new solution template. If you would like to learn more about any of these topics, take a look at the following resources:

  • Clean Architecture Solution Template
  • Clean Architecture with ASP.NET Core 3.0 (NDC Sydney 2019)

Thanks for reading. Please post any questions or comments below.

EzzyLearning Logo

Building ASP.NET Core Apps with Clean Architecture

  • Post author: Waqas Anwar
  • Post category: Architecture / ASP.NET Core / Design Patterns
  • Post published: April 23, 2023
  • Post comments: 24 Comments

You are currently viewing Building ASP.NET Core Apps with Clean Architecture

SHARE THIS POST Share this content

  • Opens in a new window

In my previous post, A Guide for Building Software with Clean Architecture , I explained how clean architecture allows developers to build testable, maintainable, and flexible software systems. We learned the benefits, principles, and challenges of using clean architecture. We learned how clean architecture focuses on dividing the software into independent and loosely coupled layers in a way that code modifications done in one layer don’t affect the code in other layers. In this post, I will show you how to implement the clean architecture in an ASP.NET Core Web API project. You will learn how to organize the application code into separate layers or modules with a specific responsibility.

Table of Contents

A Quick Introduction to Clean Architecture

In the context of ASP.NET Core, the clean architecture is implemented by organizing the application code into multiple layers which can contain one or more projects each with a specific responsibility. These layers typically include:

Domain Layer = This layer is the backbone of the clean architecture and all other projects defined in other layers should depend on this layer. This layer is highly abstracted and it contains domain entities, events, value objects, aggregates, etc.   

Application Layer = The application business rules and use cases are available in this layer. Mostly it defines interfaces that are implemented by the outer layers. This layer contains business services, DTOs, mappers, validators, etc.

Infrastructure Layer = This layer contains the implementation of the interfaces defined in the Application layer. This layer is responsible for implementing the technical aspects of the system, such as data access, logging, and security, etc. It can have multiple projects using different third party libraries or frameworks.

Presentation Layer = This layer is responsible for presenting some user interface and handling user interaction with the system. It includes the views, controllers, and other web components.

Clean Architecture

Setting Up Clean Architecture Project in ASP.NET Core

Before we dive into the actual implementation details of the application, we need to decide what type of application we are about to build. I have to admit that I am fed up with typical e-commerce or shopping cart applications so I have decided to build something more interesting such as a fictitious football league application that can have entities such as football clubs, players, stadiums, countries, etc.

I have decided to use Visual Studio 2022 with .NET 7.0 to build the demo application so let’s get started.

  • Open Visual Studio 2022 and create a new blank solution with the name “ CleanArchitectureDemo ”.
  • Infrastructure
  • Presentation
  • CleanArchitectureDemo.Domain
  • CleanArchitectureDemo.Application
  • CleanArchitectureDemo.Infrastructure
  • CleanArchitectureDemo.Persistence
  • CleanArchitectureDemo.Shared
  • CleanArchitectureDemo.WebAPI

Once the above projects are created, the project structure in Visual Studio solution explorer will look similar to the following screenshot. 

ASP.NET Core Clean Architecture Project Structure

Before we start actual implementation, we need to add the following nuget packages in different projects of the solution.

CleanArchitectureDemo.Domain project needs the following nuget packages

  • MediatR (12.0.1)

CleanArchitectureDemo.Application project needs the following nuget packages

  • Microsoft.EntityFrameworkCore  (7.0.5)
  • AutoMapper  (12.0.1)
  • AutoMapper.Extensions.Microsoft.DependencyInjection (12.0.1)
  • FluentValidation (11.5.2)
  • FluentValidation.AspNetCore (11.3.0)

CleanArchitectureDemo.Persistence project needs the following nuget packages

  • Microsoft.EntityFrameworkCore.SqlServer (7.0.5)
  • Microsoft.Extensions.Configuration (7.0.0)

CleanArchitectureDemo.WebAPI project needs the following nuget packages

I have already written multiple blog posts on some of the Nuget packages and libraries mentioned above and you can read the following posts to learn more about these packages.

  • Mediator Design Pattern in ASP.NET Core
  • Implement CQRS Pattern in ASP.NET Core 5
  • A Step by Step Guide of using AutoMapper in ASP.NET Core
  • ASP.NET Core Data Validations with FluentValidation
  • Data Access in ASP.NET Core using EF Core (Database First)
  • Data Access in ASP.NET Core using EF Core (Code First)

Implementing Clean Architecture Domain Layer

The domain layer is the core component of clean architecture and it represents the domain and use-case-independent business logic of the system. This layer has no dependency on any technology, third-party library, or frameworks. It includes interfaces, entities, and value objects. All other projects should depend on the Domain layer. For our demo project, let’s create the following two folders Common and Entities in the project.

ASP.NET Core Clean Architecture Domain Project

Common Folder

The Common folder contains base classes and interfaces.

This file contains a base IEntity interface and all domain entities will implement this interface either directly or indirectly.

IAuditableEntity.cs

This file defines a child interface of IEntity interfaces defined above. This interface adds additional properties to keep track of the entity’s audit trail information.

IDomainEventDispatcher.cs

This interface declares a method that can be used to dispatch domain events throughout the application.

BaseEvent.cs

This file contains the BaseEvent class that will become the base class of all domain events throughout the application. It only has one property DateOccurred that tells us when a particular event has occurred.

BaseEntity.cs

This file contains BaseEntity class that implements the IEntity interface. The BaseEntity class also contains a collection of domain events and also some helper methods to add, remove, and clean domain events from this collection. The idea of storing events in the collection and then dispatching them once the entity is saved is first introduced by Jimmy Bogard in his blog post A better domain events pattern and it is used in many clean architectures implementations since then.

BaseAuditableEntity.cs

This class is the child class of BaseEntity and it implements the IAuditableEntity interface defined above.

Entities Folder

The Entities folder contains domain entities. All domain entities inherit from the above BaseAuditableEntity class.

The following diagram shows the relationships between different classes and interfaces defined in the Domain layer.

Clean Architecture Domain Layer

Implementing Clean Architecture Application Layer

The Application layer contains the business logic and defines abstractions in the form of interfaces. These interfaces are then implemented by outer layers. The application layer depends on the Domain layer and acts as a bridge between the Domain layer and external layers such as Persistence or Presentations layer. This layer contains business services, DTOs, Commands, Queries, etc.

ASP.NET Core Clean Architecture Application Project

Repositories Folder

This folder contains interfaces such as IUnitOfWork, IGenericRepository, and other domain-specific interfaces such as IPlayerRepository, etc. These interfaces define methods to read and update data.

IGenericRepository.cs

This interface defines a generic repository and it contains generic CRUD methods.

IUnitOfWork.cs

This interface defines a unit of work pattern that allows us to save changes made by multiple repositories at once.

IPlayerRepository.cs

Most of the time, repositories will only use the generic methods defined in the IGenericRepository class but if they have some additional functionality and require a custom method implementation then these methods can be defined in specific repository interfaces. In the following example, IPlayerRepository is defining an additional method to get players by the club.

Features Folder

In the MVC design pattern, the code is organized by types which means you normally have a Controllers folder that contains a huge list of controllers and a Models folder that contains a huge list of models. If you are working on a particular feature, then it is difficult to find related controllers, models, etc. In clean architecture, it is a standard convention to organize the application code by functional features. This makes it easier to find all the related classes in one place and to understand and maintain the codebase over time.

If you want to have multiple features related to a particular entity or domain then you can create a separate subfolder for each feature e.g. Players, Clubs, Stadiums, etc. Each feature folder can contain subfolders such as Queries and Commands which can contain CQRS commands and queries.

ASP.NET Core Clean Architecture Application Features Folders

Check how features are organized in two subfolders Commands and Queries which are using CQRS pattern to separate reads and writes. If you are not familiar with the CQRS pattern then read my post Implement CQRS Pattern in ASP.NET Core 5

The Commands folder inside the Players folder has features related sub-folders such as:

  • CreatePlayer – To implement the functionality of creating new players in the database.
  • UpdatePlayer – To implement the functionality of updating players in the database.
  • DeletePlayer – To implement the functionality of deleting players from the database.

The Queries folder inside Players has features related sub-folders such as:

  • GetAllPlayers – To implement the functionality of fetching all players from the database.
  • GetPlayerById – To implement the functionality of fetching a single player by matching the id from the database.
  • GetPlayersByClub – To implement the functionality of fetching all players by matching clubs from the database.
  • GetPlayersWithPagination – To implement the functionality of fetching all players with pagination from the database.

Each of the above feature folders can contain Commands, Queries, Handlers, Events, DTOs, Validators, and other components specific to that particular feature. Let’s review the files and the code available in the CreatePlayer feature.

CreatePlayerCommand.cs

This file contains one record CreatePlayerCommand and CreatePlayerCommandHandler . You can separate these two into two separate files but traditionally most developers prefer to keep these two together in the same file because it is easier to see both the command and the handler in one place and quickly understand what is going on rather than jumping from one file to another file.

The CreatePlayerCommand is defined as a C# record and not as a class because records only represent a set of data without any functionality. The CreatePlayerCommandHandler class implements IRequestHandler<TRequest, TResponse> interface available in the MediatR library. We are passing CreatePlayerCommand as TRequest and Result<int> object as TResponse. The Result class is our class which is defined in a CleanArchitectureDemo.Shared library.

The actual functionality is implemented inside the Handle method of CreatePlayerCommandHandler. First, we created a new player entity and mapped the properties of the command object with the player entity.

Next, we are adding the player in the database using the generic AddAsync method.

Next, we are adding the PlayerCreatedEvent event in the domain events collection available in BaseEntity class.

Next, we are

Finally, we are sending the Result with the newly created player Id and the message “Player Created”.

PlayerCreatedEvent.cs

The PlayerCreatedEvent domain event inherits from the BaseEvent class we created earlier in the CleanArchitectureDemo.Domain project. This event will carry the newly created player object so that the event handler/subscriber can read the information from the player object.

Running the CreatePlayerCommand through an ASP.NET Web API will look something like the following screenshot.

ASP.NET Core Clean Architecture CQRS Create Command

GetPlayersWithPagination.cs

This file contains GetPlayersWithPaginationQuery and GetPlayersWithPaginationQueryHandler . We are passing GetPlayersWithPaginationQuery as TRequest and PaginatedResult<GetPlayersWithPaginationDto> object as TResponse. The PaginatedResult class is our custom class and it is defined in a CleanArchitectureDemo.Shared library.

Inside the Handle method, we are using the ProjectTo<T> extension method available in AutoMapper.QueryableExtensions namespace. This method maps IQueryable<Player> to IQueryable< GetPlayersWithPaginationDto> using the AutoMapper mapping engine. The ToPaginatedListAsync is our custom extension method that creates a paginated result.

GetPlayersWithPaginationDto.cs

The above query and handler are using the following DTO class also defined in the GetPlayersWithPagination folder.

Running the GetPlayersWithPaginationQuery through an ASP.NET Web API will look something like the following screenshot.

ASP.NET Core Clean Architecture CQRS Get Paginated Results

GetPlayersWithPaginationValidator.cs

The GetPlayersWithPagination folder also has the following GetPlayersWithPaginationValidator class that can be used to validate the input parameters of the query.

Interfaces Folder

All interfaces related to application and business services can be defined in this folder. Here is one example of such a service.

IEmailService.cs

Iservicecollectionextensions.cs (cleanarchitecturedemo.application).

To configure the dependencies defined in the Application layer, the following class is added to the project. 

Implementing Clean Architecture Infrastructure Layer

This layer contains the implementation of the interfaces defined in the Application layer. The project(s) defined in this layer communicate with external systems and technologies, such as databases, APIs, or cloud services. This layer should only interact with the domain layer through the application layer and should not contain any business logic or domain knowledge. The main goal of the infrastructure layer is to encapsulate the technical details of the application so that they can be easily changed or replaced without affecting the rest of the application.

It is also very common practice to create multiple infrastructure projects in this layer especially if you are working on a very large project where you need to communicate with multiple data sources or external systems. In our demo app, we created two infrastructure projects CleanArchitectureDemo.Infrastructure and CleanArchitectureDemo.Persistence.

ASP.NET Core Clean Architecture Infrastructure Projects

The CleanArchitectureDemo.Infrastructure project will implement the business services defined in the application layer such as the following.

EmailService.cs

Iservicecollectionextensions.cs (cleanarchitecturedemo.infrastructre).

All business services defined in the application layer are registered with the dependency injection container.

The CleanArchitectureDemo.Persistence project contains data contexts, repositories, migrations, etc.

Contexts Folder

There can be multiple database contexts in a large project so it is always a good idea to create a separate folder for all context classes. Currently, this folder will only contain ApplicationDbContext.cs file.

ApplicationDbContext.cs

This file contains the EntityFramework DbContext. The important code is available in the SaveChangesAsync method where we are checking if the entity we are saving has some domain events associated with it and if there are some events available we are dispatching them all using our IDomainEventDispatcher.

The Repositories folder contains the implementation of the repository and unit of work interfaces.

GenericRepository.cs

The implementation of GenericRepository is very straightforward. It uses ApplicationDbContext to perform standard CRUD operations.

PlayerRepository.cs

If any repository has any custom method, it can be defined in its respective repository. In our demo app, the IPlayerRepository has a custom method GetPlayersByClubAsync which is implemented in PlayerRespository below.

UnitOfWork.cs

Iservicecollectionextensions.cs (cleanarchitecturedemo.persistence).

To configure the dependencies defined in the Persistence project, the following class is added in the project. 

Implementing Clean Architecture Presentation Layer

The presentation layer is the out most layer of the clean architecture and it presents some GUI or exposes some public API to interact directly with the end user or other client applications. The presentation layer should not contain business logic or domain knowledge and should only interact with the rest of the application through the application layer. The presentation layer can be implemented using various technologies, such as a Web API, gRPC, or MVC Web Application, etc. For our demo application, we created an ASP.NET Core 7.0 Web API project that will expose some RESTful endpoints to perform CRUD operations on Player entity.

Controllers Folder

In a Web API project, we usually create API controllers in the Controllers folder. These controllers handle incoming HTTP requests and return the appropriate HTTP response. For our demo application, let’s create a PlayersController class.

PlayersControllers.cs

The Program.cs file is the entry point of the application. The Program.cs configure the services required by the application, and also defines the application request handling pipeline. In our demo app, we will call the extension methods AddApplicationLayer, AddInfrastructureLayer, and AddPersistenceLayer defined in different layers.

Clean Architecture is a software design pattern that emphasizes the separation of concerns and the separation of dependencies in order to achieve a highly maintainable and testable codebase. It promotes a clear and modular structure, making it easier to understand and modify the application over time.

Some key benefits of Clean Architecture in ASP.NET Core include improved maintainability, testability, flexibility, and scalability. It allows for better separation of concerns, making it easier to understand and modify different parts of the application independently.

Clean Architecture encourages the use of interfaces and dependency injection, which makes it easier to write unit tests for individual components or modules of the application. By isolating dependencies and relying on abstractions, you can mock or substitute dependencies during testing, resulting in more effective and isolated unit tests.

Clean Architecture typically consists of several layers, including the Domain Layer (representing the core business logic), Application Layer (containing application-specific use cases and services), Infrastructure Layer (dealing with data access and external dependencies), and Presentation Layer (handling user interfaces and interaction).

ASP.NET Core can be easily integrated with Clean Architecture principles. The framework provides the necessary tools and features to implement a clean and modular architecture, such as dependency injection, middleware pipeline, and the MVC pattern. This allows developers to build scalable, maintainable, and testable applications using Clean Architecture principles.

Clean Architecture is particularly useful for larger or complex projects where maintainability and flexibility are critical. However, for smaller or straightforward projects, the overhead of implementing Clean Architecture may not be necessary or practical.

In the ASP.NET Core context, the clean architecture is usually implemented by organizing the application code into separate layers or modules in such a way that each has a specific responsibility. In this article, I tried to give you a detailed example of implementing clean architecture in ASP.NET Core. The complete source code of our CleanArchitectureDemo application is available on GitHub . If you have any comments or suggestions, please leave your comments below. Don’t forget to share this tutorial with your friends or community.

You Might Also Like

A Step by Step Guide to ASP.NET Core Dependency Injection

A Step by Step Guide to ASP.NET Core Dependency Injection

Decorator Design Pattern in ASP.NET Core 5

Decorator Design Pattern in ASP.NET Core 5

A Step by Step Guide to Bundling and Minification in ASP.NET Core

A Step by Step Guide to Bundling and Minification in ASP.NET Core

This post has 24 comments.

presentation layer clean architecture

i need a Login Tutorial link in clean archicture with jwt token authorisation can anyone help me .

presentation layer clean architecture

Why would an API have reference to Persistence?

presentation layer clean architecture

How would you implement Identity (without IdentityServer) in this solution or do you have a blog that already covers this? Thanks! 🙂

presentation layer clean architecture

Might you have the Database.sql script. So I can recreate the database.

presentation layer clean architecture

Hello, I cannot use dotnet ef migrations. The response is: unable to create an object of type context. for the different patterns supported at design time

presentation layer clean architecture

You don’t need to use migrations with my reference project as I am using EF Core with database first approach and connecting to an existing SQL Server database.

Using this project structure you won’t be able to do ef migrations. His Database Context is in Infrastructure layer and have reference to Domain Entities.

presentation layer clean architecture

Hi Anwar, We dont want to use mediatr….. can we still implement this architecture?

Yes, you can implement your own application services and call repositories in your services.

presentation layer clean architecture

coming from a database background, can the database architecture diagrams be provided ?

presentation layer clean architecture

What is the purpose of AddDomainEvent method and why are we adding our events in AddDomainEvent method.

Instead of dispatching to a domain event immediately, It is a much better approach to add/record all events before committing the transaction and dispatch all events once the transaction is committed. This approach has several benefits such as they make the testing of events much simpler because the global domain event dispatcher is not firing events all the time.

presentation layer clean architecture

You have not specified the implementation of various class such as Result, PaginatedResult etc in the above article.

I excluded them from blog post to keep the post shorter but you can find them in the source code of the demo project I uploaded on Github.

presentation layer clean architecture

In the source code you also did not implement them too

presentation layer clean architecture

You say that the domain layer has no external dependencies to third party libraries. But you need to install MediatR into the CleanArchitectureDemo.Domain project, Why is that?

I added Mediatr package because I want to publish domain events using Mediatr from a central place like I did inside DomainEventDispatcher class. I mentioned in the post that this type of domain events pattern is recommended by Jimmy Bogard in one of his post and I liked this approach. Obviously, if you are using some other approach of handling domain events then you don’t need to add Mediatr package reference.

presentation layer clean architecture

Why is EF.Core is referenced in the Application layer?

We need EF Core because we need to use EF Core methods in CQRS Commands and Queries.

presentation layer clean architecture

Amazing! Everything is explained in detail with such simplicity. I would suggest if you have time to add Blazor as follow up tutorial to complete the frontend application and tutorial set. Thumbs up!

Here is my new tutorial related to implementing clean architecture using Blazor Server Apps. https://www.ezzylearning.net/tutorial/building-blazor-server-apps-with-clean-architecture

presentation layer clean architecture

Let me put my 5 cents. In spite, the overall solution is quite good, but it has some drawbacks. I would be happy if you’ll find my comment useful.

– Creating a common interface for entities with identifier makes impossible to use composite keys referencing other entities. For instance, A possible composite key might be a pair of two referenced entities. That’s why I prefer to not define the Id property in the base inteface/class.

– There are no strict aggregate roots (aka IAggregateRoot). It might cause some spaghetti code that saves entities. It would be better to strictly distinguish aggregate roots and dependents that cannot exist without a root.

– Domain event dispatcher represents an infrastructure layer. Entities usually cannot subscribe on domain events, because a domain event usually represents a side effect of a transaction.

– In spite the fact that implementation of a generic repository is quite common scenario, it rarely works in complex cases, e.g. if a result of a repo should be an aggregated object of several domain entities or an entity has a composite key. In such cases, I personally prefer query objects. (BTW, if I use Nhibernate, I tend to decline re-defining repos/UoW, because ISession/ITransaction represent the same).

– When you invoke UnitOfWork.Save() directly in the handler, the Mediator pipeline might become broken or cause inconsistent data, because other pipes also might be interested in data modification. I would rather move transaction commit to a custom Mediator pipe that commits all changes on finish.

– It would be better to return HTTP statuses in controllers alongside results. For example, it can be done on this way:

[ProducesResponseType(typeof(CreatePlayerResponse)), StatusCodes.Http201Created] public async Task Create(CreatePlayerCommand command) { var result = await mediator.Send(command); var playerUrl = Url.Action(nameof(GetPlayerById), new { result.PlayerId }); return Created(playerUrl, result); }

I read all your points and I really appreciate you spend some time to give this valuable feedback. I agree with you that these points can improve my clean architecture implementation even further.

Leave a Reply Cancel reply

Save my name, email, and website in this browser for the next time I comment.

  • ASP.NET Core
  • Design Patterns
  • Architecture
  • ASP.NET MVC
  • .NET Framework
  • Visual Basic
  • Other Cheat Sheets
  • Infographics

Privacy Overview

Clean Architecture with .NET by Dino Esposito

Get full access to Clean Architecture with .NET and 60K+ other titles, with a free 10-day trial of O'Reilly.

There are also live events, courses curated by job role, and more.

The presentation layer

Learn the rules like a pro, so you can break them like an artist.

— Pablo Picasso

A bstractly speaking, the presentation layer is simply the segment of a computer system responsible for providing a user-friendly interface, representing data visually, ensuring a positive user experience, and facilitating communication with other layers of the software application. In more concrete terms, however, the presentation layer ultimately serves one main purpose: collecting external input and routing commands to the more operational layers of the system.

In any interactive application, all activity consists of requests sent by human or software agents to a known set of endpoints, and responses generated by those endpoints. ...

Get Clean Architecture with .NET now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.

Don’t leave empty-handed

Get Mark Richards’s Software Architecture Patterns ebook to better understand how to design components—and how they should interact.

It’s yours, free.

Cover of Software Architecture Patterns

Check it out now on O’Reilly

Dive in for free with a 10-day trial of the O’Reilly learning platform—then explore all the other resources our members count on to build skills and solve problems every day.

presentation layer clean architecture

presentation layer clean architecture

Multiple ways of defining Clean Architecture layers

Igor Wojda 🤖

Igor Wojda 🤖

ProAndroidDev

Good architecture is a key to build a modular, scalable, maintainable and testable application. Uncle Bob Clean Architecture (CA) is a core architecture for many application nowadays, mainly because it allows to separate business logic and scales well.

It is advised to be at least a bit familiar with Uncle Bob Clean Architecture before reading this article further.

Brief into to Clean Architecture

Without going into too many details about CA we will define classic 3-layer architecture (we could have more layers). Each layer has a distinct set of responsibilities:

  • Presentation layer - presents data to a screen and handle user interactions
  • Domain layer - contains business logic
  • Data layer - manages application data eg. retrieve data from the network, manage data cache
This articles focuses on different aproaches of applying CA. If want to see contents of each layer check my Android-Showcase project .

The core aspect of CA is proper layer separation (dependency rule) where the domain layer is independent of any other layers:

This means that inside the domain layer we should not access any classes defined in other (outer) layers. By preserving this rule (boundary) we gain confidence that any change applied to data or presentation layers would not affect the domain layer ( this is the core idea behind CA) eg.

  • If we update our data layer by migrating database engine from SQLite to Realm domain and presentation layers will not be affected
  • If we change a way we display the same data in the presentation layer the domain and data layers will not be affected.

Ideally, the domain layer should be independent of libraries and frameworks. It is fine to have Kotlin Standard Library and some dependency injection library dependency, but we should always try and avoid other libraries and frameworks in the domain layer (especially the Android framework).

Dependency injection setup should be implemeented per clean architecture layer (avoid having one hudge setup in the main app module)

The road from theory to practical application

Clean Architecture is a quite abstract concept, so you probably wonder how can we implement this concept in our (Android) application? There are actually multiple ways to do this, so let’s take a look at a few of them and discuss the potential pros and cons of each approach.

Approach 1 — CA layers in a single module

The simplest approach would be to have 3 packages ( presentation , domain , data ) inside the app module.

This approach works, but it has a few serious flaws. First of all, there is no mechanism of layer dependency verification, meaning that we can access (usually by accident) classes from the presentation or data layers inside the domain layer breaking the core assumption of CA.

Another issue is that this solution does not scale well. As our app grown whole code is stored inside a single module. There is no division by feature and it is easy to end up coupling code (we will get back to this later).

Approach 2— One CA layer per module

To gain more confidence and enforce layer separation we could create separate modules (Gradle subprojects) for each CA layer and define dependencies between them.

This solution looks similar to the first one, so let’s look at Android Studio project view to see the difference:

Projects like android-clean-architecture-boilerplate and Android-CleanArchitecture utilize this approach.

In this configuration presentation module usually substitute app module, however it still servers as the main application module.

By separating layer into different modules we gain the layer separation confidence and a bit of scalability, but the approach still has scalability problems — while implementing or removing features we would have to jump across multiple modules. Code may be accidentally coupled between features and this adds hidden cross-feature dependencies that may be hard to track and maintain.

Over time each of the layers would contain more and more code leading to more confusion and increase application compilation time. To solve this issue (and potentially splitting work across team-members or multiple even multiple teams) many projects take advantage of feature modules .

When working with features ideally, we should be able to delete most of the feature related code by deleting single package.

We have modules, but we have to find a better way of utilizing them — separate things by feature, not by the CA layer.

Approach 3— CA layers inside the feature module

To solve the above problems we can take one step back and move all CA layers inside the (feature) module, but this time each feature will contain its own set of CA layers:

This time app module wires everything together.

Usually package structure of the app module is a bit different than feature modules, because it mostly contains “fundamental app configuration” (dependency injection, application class, retrofit configurations, etc.) and code that wire multiple module together (eg. some internal event bus).

Looking at Android Studio project view we will see something like this:

With this approach, we gained proper code separation from a feature perspective and more solid cross-feature boundaries. It is much easier to define cross-feature dependencies and certain features may depend on 3rd party libraries that are not needed for other features. On top of that Gradle adds some caching where only some of thee modules are may be recompiled instead of the whole project and using feature modules you can take advantage of Android dynamic delivery. Now we can also have proper feature ownership per team (eg. the team X can work on code stored within a single feature module) and unit tests separation(unit tests for a feature are contained within feature module).

While a feature module approach has more benefits it still has the initial issue that each feature can break the dependency rule. To solve this problem we can implement a custom lint check rule or ArchUnit test that would check all the imports (layer dependencies).

We can check if imports of each class defined in the domain layer and flag and error if there are imortas that point to other layers.

Personally I think that approach 3 is suitable for most of the projects (including my personal showcase project), but let’s briefly look at how we could scale it even further.

We should also consider having additional shared modules eg. feature_base module containing common classes (BaseActivity, BaseFragment etc.) or modules that contain some common resources/code to avoid duplication (thx Stoycho Andreev for pointing this in the comment ).

Approach 4— CA layers per feature modules

We could have 3 modules for each feature, each one representing one of the layers:

This approach is similar to approach 2, however this time, feature module layers are top modules of our architecture (not just layer modules). Android Studio would present these modules like this:

There are multiple problems with this approach. First of all, it’s quite easy to end up with dependency hell as the number of modules goes quite fast (especially when the domain layer of one module depends on the domain layer of another module). Another issue is that Gradle slows down a bit with each new module.

Compare approaches

Below table presents a brief summary of all the approaches:

As we can see there are multiple ways of defining the CA layer within the Android project. Personally I usually prefer to go with approach 3, because it is sufficient for most projects and scales quite well.

It’s tempting to start with approach 1 and overtime slowly migrate project into approach 2, approach 3 however, migration is not always that straight forward (due to hidden dependencies). It’s much more cost (dev time) effective to start a project with properly separated features.

👉 Follow me on Twitter and check my other articles.

The Konsist architectural linter can be used to guard clean architecture layers in the project:

Review Konsist documentation for more details and take a look at these clean architecture snippets .

  • Android showcase project
  • Intro to App Modularization
  • Why do we need Clean Architecture
  • A detailed guide on developing Android apps using the Clean Architecture pattern
  • Tackling Android Development at Scale

Igor Wojda 🤖

Written by Igor Wojda 🤖

👉Android Developer Advocate at Vonage 👉Author of “Android Development with Kotlin” book 👉Follow me on twitter to learn more https://twitter.com/igorwojda

More from Igor Wojda 🤖 and ProAndroidDev

Reducing APK size by using ABI Filters and APK split

Reducing APK size by using ABI Filters and APK split

This article describes ways of dealing with native libraries in android applications..

How to safely update state in your Kotlin apps

How to safely update state in your Kotlin apps

In this article nikita describes how to update your application state using mvi or mvvm in a fast, durable and consistent way.

Kotlin Design Patterns: Mediator

Michal Ankiersztajn

Kotlin Design Patterns: Mediator

Mediator is a behavioral design pattern that reduces object coupling and dependencies chaos..

Introducing Konsist: A Cutting-Edge Kotlin Linter

Kt. Academy

Introducing Konsist: A Cutting-Edge Kotlin Linter

Linters are vital tools in software development, helping to enforce code standards and best practices across the code base. by analysing…, recommended from medium.

Clean Architecture: A Comprehensive Guide with C#

Pooja Keshri

Clean Architecture: A Comprehensive Guide with C#

Software developers face a constant challenge of creating scalable, maintainable, and flexible applications. as applications grow in….

A Deep Dive into Clean Architecture and Solid Principles

Amandeep Singh

A Deep Dive into Clean Architecture and Solid Principles

Building software for the future.

presentation layer clean architecture

Staff Picks

Demystifying Design Patterns — Rule-based pattern / Rule-engine pattern

CodeChuckle

Demystifying Design Patterns — Rule-based pattern / Rule-engine pattern

A rule-based software design pattern is an architectural approach that relies on a set of predefined rules or conditions to dictate the….

Multi Module Architecture in Android

Yigitkaantonkaz

Multi Module Architecture in Android

Today, i am going to talk about multi-module architecture, why we use it and how we implementing it..

Dependency Injection in Compose

Jonathan Koren

Android Developers

Dependency Injection in Compose

Learn how hilt provides and scopes dependencies in a traditional android app and compose changes our approach..

Kotlin Clean Architecture and CQRS 🚀👋👨‍💻

Alexander Bryksin

Kotlin Clean Architecture and CQRS 🚀👋👨‍💻

In this article, we will implement the microservice using clean architecture and cqrs. a tech stack used kotlin, spring webflux with….

Text to speech

Unpacking the Layers of Clean Architecture – Domain, Application, and Infrastructure Services

avatar

Clean Architecture Overview

What is a service and when should i use one, what is an application service, what is a domain service, what is an infrastructure service, do you need an infrastructure service at all, service examples, service cheat sheet.

Recently, I’ve noticed some confusion relating to Clean Architecture and the concept of ‘services’. In popular Clean Architecture templates such as the SSW CA Template and Jason Taylor’s CA template , there is a single service called DateTimeService in the Infrastructure project. This can mistakenly lead developers to think this is where ALL services should live (which is not the case).

This post will use the term ‘service’, but other terms like ‘manager’, ‘helper’, or ‘utilities’ are equally applicable.

So where should services live? Let’s dive in and take a look.

Before we discuss services, let’s touch on the different layers within Clean Architecture and what the purpose of each layer is

  • Presentation : UI or API related concerns
  • Application : Business logic and orchestration
  • Domain : Entities and business logic (when using DDD)
  • Infrastructure : Integration with external systems (DB, Network, Disk, API, etc)

For a more in-depth explanation, see my previous blog post .

A service is a somewhat overloaded term. Generally, it is a class that contains functionality relating to a single responsibility. Depending on the layer the service lives in, the responsibility will be slightly different.

A service can be a good idea whenever you need to re-use common logic, or encapsulate some underlying infrastructure.

Many Clean Architecture templates (such as the ones above), use MediatR to help facilitate CQRS commands and queries. Most of your logic should live in the Application layer in your MediatR handlers (or alternatively, in the Domain if you are using Domain Driven Design).

However, there are times when you may need to share logic between commands and queries. This is where services come in to play. Services can be placed in a common area and re-used as needed.

But remember, you should default to placing your logic in MediatR handlers. Only use services for truly common code.

Application services are typically unit testable as they are free of infrastructure concerns.

When using Domain-Driven Design, we are often mapping real world nouns to entities in our software. However, sometimes we come across a concept that “just isn’t a thing”. In these cases, it’s appropriate to create a service instead.

Eric Evans states that a good Domain service has 3 characteristics:

  • The operation relates to a domain concept that is not a natural part of an ENTITY or VALUE OBJECT
  • The interface is defined in terms of other elements of the domain model
  • The operation is stateless

We need to take care when creating services that we are not stripping all the behavior from domain entities.

Domain services are typically unit testable as they are free of persistence concerns.

To decouple Infrastructure from Application in Clean Architecture, we create Interfaces in Application that are implemented in Infrastructure . This allows us to write the business logic in our MediatR handlers against the interfaces without being coupled to the specific implementation. This is all thanks to the Dependency Inversion Principle. 💪

It’s worth keeping in mind that we want to keep our Infrastructure services as small as possible and ensure that any business logic stays in the Application layer.

A good rule of thumb when calling into the Infrastructure Layer is to “get in, and get out quick”.

Infrastructure services are typically not unit testable, but may be covered in integration tests.

Infrastructure services facilitate the communicate with out outside piece of infrastructure. Due to this some developers like using the term ‘Broker’ which can more accurately describe the function that Infrastructure services tend to perform.

*Persistence services can be integration tested, but other forms of infrastructure are usually mocked out.

As we’ve seen services don’t need to all live in a single layer within Clean Architecture. They can be spread across Domain , Application , and Infrastructure depending on the responsibility of the service. Domain Services should be used for Domain Logic when using DDD. Application services should be used for common application logic and orchestration. Infrastructure services should be used for Infrastructure related implementations.

When appropriate services can make sense, but we need to be careful that they don’t become dumping grounds for everything. Logic should still go into our commands/queries/domain model as appropriate.

Do you have any other ways to distinguish different types of services? Please let me know in the comments below.

presentation layer clean architecture

The Presentation Layer - Clean Architecture & Domain-Driven Design on PHP

February 24, 2022 by Northon Torga

The entry point of our application is not coincidentally the last article of the introduction series about Clean Architecture and DDD on PHP . When developing using Clean Architecture and DDD, the Presentation layer is the last thing we focus on .

We already discussed the main aspects of our application, but I've never really mentioned HTTP yet. This should come as a surprise if you never develop using Clean Architecture and DDD.

When you rely too much on frameworks like Laravel, Express.js, etc and/or is used to MVC architecture, you usually first start with the Controllers and work your way down to the other layers, if there is any other layer at all.

Plug-and-play Presentation

The beauty of Clean Architecture is not only having a plug-and-play infrastructure , but also having a plug-and-play presentation . It really does not matter if your user is going to access the application via HTTP, CLI, telnet or even smoke signals.

Accessing  the Presentation directory you will only see a single directory there: Api. The proof of concept code available at GitHub  created for  this series has only one entry point , therefore so far our application is only a REST API .

It could easily be more than that, but for the sake of simplicity we'll focus on how the Presentation layer was created so that our application becomes accessible as a REST API .

The Presentation layer has 2 fundamental goals: handle I/O and inject infrastructure. Let's dive into these goals, shall we? 🦈

Handling I/O

The Presentation layer has 3 layers:

  • Controllers are responsible for handling the inputs;
  • Presenters are responsible for handling the outputs;
  • Middlewares exist in the middle, they can either help during the input or the output.

Inside the Api directory you will only see Middlewares and Controllers . That's because the Presenters are embedded into the Controllers for the sake of simplicity.

The first task when receiving an user input in the Controllers is to transform the received data into Value Objects . Remember, we'll hardly never use native types on our application, everything must be objects .

This is done by the getExecutionParams() method which gets the params sent by the user and tries to create the Value Objects.

The proof of concept is a 2 years old code, currently I'm not longer using try/catch on the Presentation layer at all. You may want to check an article I wrote about Error Handling with Middlware later to understand how I was able to simplify the process a lot.

Middlewares can also play an important role in converting inputs. Take for example the Authorization process of an API. The API key can be converted into a Value Object by an Authorization Middleware so that the format of the key is checked and then an infrastructure implementation can be used to query a database to validate if the API key is or not valid.

Most of the time, the output of the API is a success message ( line 66) or an information that was requested by the user. That information is very likely an Entity or a Value Object, such as seem on the GetContactController.php :

All Entities and Value Objects on the code implements the JsonSerializable interface of PHP so it's convertible into JSON by the json_encode() method. That's why the "Presenter" part of our Controller is basically the json_encode() with the Entity Contact inside it (line 47) .

In cases where the Presenter does more than just return an object, for example an endpoint that returns an HTML table converted from an Entity, then it would make sense to have it separated. In CLIs having the Presenter in it's own class makes a lot of sense so you can format the output with colors, columns, etc.

Oh, we can't forget about the role of Middlewares in the output. A ResponseMiddleware can later be used to transform the JSON into XML if the user sends an Accept header requesting a response in JSON. That way your API is able to respond both in JSON and in XML for instance.

You can also use Middlewares to handle the output for exceptional cases, such as the one mentioned on the Error Handling with Middlware article. Seriously, check that article, you won't regret. 😁

Enough about I/Os. Now let's get into the real fun part. Dependency Injection.

Injecting Infrastructure

Dependency Injection sounds cool because it's cool. With Clean Architecture you won't be requiring dependencies directing on your code as you use to. Now, all the infrastructure is regulated by interfaces , just like explained on the very first article of this series .

Since we're following interfaces, we can have multiple implementations for the infrastructure. It's the Controller task to provide an UseCase (Domain Layer) with an infrastructure implementation that guess what, implements an interface the UseCase knows how to use.

It's probably sounding like jibber-jabber for you now, but we can see that on code. Take the GetContactController.php controller again:

You can see that I'm initiating a ContactQueryRepository object (line 34) . This is an infrastructure implementation, file-based (although the name does not tell right away - my bad), of the ContactQueryRepositoryInterface :

Once I initiate the ContactQueryRepository object, I pass it to the GetContactInteractor UseCase right on the next line. That's it. That's dependency injection.

Why is that great? Well, let's see. Imagine that tomorrow I want to have a database-based implementation of that same interface, to get contacts. However, I only want to use that database-based implementation if the ContactId is greater than 1000. I don't know, maybe I was in a rush and couldn't migrate the files into a database, thus the first 1000 Contacts will be kept in file format.

The only thing I need to do besides creating a DatabaseContactQueryRepository class, is to add an if in my controller so that I pass to the GetContactInteractor UseCase the database implementation of ContactQueryRepositoryInterface instead of the standard file-based one.

I didn't change a single line on the Domain layer. In fact I didn't change anything, I created a new implementation and added an if into my controller. That's plug-and-play infrastructure right there .

The idea of having multiple implementations for the same interface is denominated  " Strategy Design Pattern ". I highly recommend you read more about Strategy in the Refactoring Guru website . That website is pure gold.

Final Thoughts

Combining Clean Architecture and DDD is a natural process. They share a lot of common principles. Once you get the hang of it, it feels like you have just learned how to program for the first time . At the same that it's liberating, you feel ashamed of what you have been writing so far.

Don't worry about that though. That's what progress feels like . Now your code has exactly the idea of what you mean by a concept that only existed in real life. No more fat controllers and skinny models, now the model (Domain) is at the center of your application, everything just fits right together.

I'm pretty sure the ethical hackers out there will agree with me when I say DDD and Clean Architecture makes an attempt to invade way, way, way harder . It's such a pain that I would rather resort to social engineering if I'm trying to pentest a system designed with DDD and Clean Architecture concepts in mind rather than spending the whole month barking up the wrong tree. 😁

What we usually see when pentesting is that code is as much vulnerable as a team without social engineering training. A chain is only as strong as its weakest link they say. At least with Clean Architecture and DDD you're strengthening one part of your business. It's one last thing to worry about when going to sleep.

« The Domain Layer - Clean Architecture & Domain-Driven Design on PHP

DEV Community

DEV Community

Julian Lasso 🇨🇴

Posted on Sep 19, 2023 • Updated on Sep 23, 2023

Clean Architecture (Domain Layer)

In this post, I want to share my approach to developing the domain layer, applying the principles I've learned from the book "Clean Architecture" by Robert C. Martin , as well as some concepts extracted from "Domain-Driven Design Distilled" by Vaughn Vernon .

For this layer, I've used my small boilerplate, which you can check out at the following link: https://dev.to/julianlasso/boilerplate-para-typescript-jm3

What's all this about?

My current project involves developing a To-Do application with user authentication. Despite being a seemingly straightforward task, it has become a valuable opportunity to apply the knowledge I've gained about clean architecture and the application of some concepts of what is Domain-Driven Design (DDD).

The project has been organized into three main layers: Domain, Application, and Infrastructure, and possibly the Presentation layer in the future.

Domain Layer

Clean Architecture Diagram

In the domain layer, I've focused on four key aspects:

Value Objects : They represent immutable and fundamental concepts in the application's domain.

Entities : These are objects that have a unique identity and can change over time.

Commands and Their Validators : Handling the actions that can be performed in the domain and their associated validation rules.

Aggregates : Structures that encapsulate multiple value objects and entities.

I've also considered the design of interfaces for future repositories and the handling of domain layer-specific exceptions. However, I'm evaluating whether information related to repository interfaces and commands along with their validators should be placed in the application layer. Time and experience will guide me in this decision.

You can find the repository for the domain layer at the following link, where I've achieved 100% unit test coverage:

https://github.com/ProfeJulianLasso/todo-backend-domain

The following is the current structure of the domain layer.

If for some reason you do not wish to review the code, here are the modeling diagrams of the most relevant sections.

aggregates

Value Objects

value objects

Final words

I appreciate any questions, doubts, concerns, or contributions you may want to make.

I'm completely open to receiving any type of feedback. Please don't hesitate to contact me; I'll be delighted to receive your comments.

Update September 23, 2023

Commands and their validations are passed to the application layer.

Top comments (1)

pic

Templates let you quickly answer FAQs or store snippets for re-use.

omegamaxy profile image

  • Education UCLL, EHB
  • Joined Oct 26, 2022

Hi, what application did you use for the diagrams?

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink .

Hide child comments as well

For further actions, you may consider blocking this person and/or reporting abuse

fabrikapp profile image

How to Use Typed Routes in Next.js

Fabrikapp - Apr 22

ramunarasinga profile image

Tips from open-source: An Object with Map and Set.

Ramu Narasinga - Apr 12

rivea0 profile image

LeetCode Meditations: Linked List Cycle

Eda - Apr 8

How to Implement a LangGraph (LangChainJS) in TypeScript (in 5 minutes)

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Framework-Independent Architecture (FIA) - Clean Architecture で iOS アプリを爆速でビルドする -

presentation layer clean architecture

Framework-Independent Architecture (FIA) - Clean Architecture で iOS アプリを爆速でビルドする -

--- marp: true theme: gaia class: invert ---

## Framework-Independent Architecture (FIA) #### - Clean Architecture で iOS アプリを爆速でビルドする -

![bg right:35%](./assets/images/account.jpg)

- 高橋 俊 - iOS エンジニア - アカウント - X: [@ikuraikuraaaaaa]( https://twitter.com/ikuraikuraaaaaa ) - GitHub: [@suguruTakahashi-1234]( https://github.com/suguruTakahashi-1234 ) - 技術 - Swift, iOS, IoT

- **Clean Architecture を使って iOS アプリを爆速でビルドする方法** - = [Framework-Independent Architecture (FIA)]( https://github.com/suguruTakahashi-1234/framework-independent-architecture ) の紹介 - **MV → MVP (MVVM) → Clean Architecture → FIA へのリアーキテクチャの実演**

- Clean Architecture の詳細

# iOS アプリ開発における現状のアーキテクチャ候補

## 大きくこれらの 3 パターンに分けられる

- Layered Architecture 系 (MVVM, MVP, [VIPER]( https://cheesecakelabs.com/blog/ios-project-architecture-using-viper/ )) - → View と ビズネスロジック の分離 - Redux 系 ([TCA]( https://github.com/pointfreeco/swift-composable-architecture ), [ReSwift]( https://github.com/ReSwift/ReSwift )) - → 単方向データフロー - [Clean Architecture]( https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html ) 系 ([VIPER]( https://cheesecakelabs.com/blog/ios-project-architecture-using-viper/ )) - → 内側方向への依存性の統一、依存性の逆転原則、関心事の分離

![](./assets/drawio/architecture_venn_diagram_delete_fia.drawio.svg)

### iOS アプリ開発 アーキテクチャ パターン

![](./assets/drawio/architecture_venn_diagram.drawio.svg)

### 今回、紹介する FIA は Clean Architecture 系 である

## Framework-Independent Architecture とは

### F = Framework Layer = Framework 層に ### I = Independent = 非依存な ### A = Architecture = アーキテクチャ

## → Framework 層に 非依存な アーキテクチャ

# Framework Layer ?

## Framework Layer ?

- Clean Architecture の最も外側の層 - Data Access Layer やInfrastructure Layer とも呼ばれる - iOS アプリ開発においては3rd パーティー製 SDK やギークな処理を扱う層

※ 一般的な用語ではない

![bg right 100%](./assets/images/clean_architecture.jpg)

## FIA を採用する目的

- **Xcode でのビルド時間の短縮** - テスト、Previews も対象 - Clean Architecture のメリットの享受 - 独立性 - テスタビリティー - メンテナビリティー - etc...

![bg contain 35%](./assets/drawio/architecture_outline.drawio.svg)

#### ポイント: 開発用の Application Layer が Clean な領域である

## Clean Architecture 円との比較

![bg contain 80%](./assets/images/clean_architecture.jpg) ![bg contain 80%](./assets/drawio/architecture_circle.drawio.svg)

### 本質的に両者は同じことを表している

## リアーキテクチャを通して FIA での実装の実演

[LIVE 動画リンク]( https://www.youtube.com/watch?v=5blwYSQcL2E )

## リアーキテクチャのステップ

1. MV 2. MVP (MVVM) (Not Repository Pattern) 3. MVP (MVVM) + Repository Pattern 4. Clean Architecture 5. [Framework-Independent Architecture (FIA)]( https://github.com/suguruTakahashi-1234/framework-independent-architecture ) 1. Dependency Injection in Application Layer 2. Development Application Layer into Clean Area 3. Dependency Injection with DI Container 6. extra: Swift 6 support (any protocol → some protocol)

# それぞれのアーキテクチャの特徴

- メリット✨ - シンプル - デメリット⚠️ - ビジネスロジックのテストができない - テスト🧪 - 🆕 XCUITest での UI テスト - 🆕 Previews での View の確認

## MVP (MVVM) (Not Repository Pattern)

- メリット✨ - View とビジネスロジックの分離 - ビジネスロジックのテスト可能 - デメリット⚠️ - Previews で View のバリエーションを増やすのが難しい - テスト🧪 - 🆕 Presenter (ViewModel) のビジネスロジックのテスト

## MVP (MVVM) + Repository Pattern

- メリット✨ - ビジネスロジックとデータアクセスの分離 - モックによるデータの差し替えが可能 - データアクセスロジックのテストが可能 - デメリット⚠️ - View→Presenter での Repository (Driver) のバケツリレーの発生 - テスト🧪 - 🆕 Previews でのモックを使ったバリエーションテスト - 🆕 Repository (Driver) のデータアクセスロジックの単体テスト

## Clean Architecture

- メリット✨ - Presentation 層 (View, Presenter (ViewModel)) が、 Framework 層 (Repository (Driver)) に非依存になる - → 3rd パーティー製ライブラリの乗換えによる影響が限定的 - デメリット⚠️ - Domain Entity の定義の発生 - テスト🧪 - Clean Architecture に変更しても MVP (MVVM) + Repository Pattern から追加で実施できるテストは特にない

## Framework-Independent Architecture (FIA)

- メリット✨ - Framework 層に非依存なアプリ/モジュールのビルドの高速化 - デメリット⚠️ - Application 層からの Repository (Driver) のバケツリレーの発生 - → DI Container の導入で解決 - テスト🧪 - Framework 層に非依存なアプリの XCUITest の高速化

table { table-layout: fixed; width: 100%; display:table; font-size: 24px; }

## FIA で可能なテスト

| Test Type | DI Container | Test Target: | | | | | | ---------- | :-----------: | :-----------------: | :---------------: | :-------: | :--------: | :----: | | | | ViewInteraction | ViewVariation | Presenter | Interactor | Driver | | XCUITest | Actual / Mock | ◎ | ◯ | ◯ | ◯ | ◯ / - | | Previews | Mock | - | ◎ | ◯ | ◯ | - | | Presenter | Actual / Mock | - | - | ◎ | ◯ | ◯ / - | | Interactor | Actual / Mock | - | - | - | ◎ | ◯ / - | | Driver | Actual | - | - | - | - | ◎ |

#### → 各テストがどの範囲をカバーするかが明確

## FIA の実装課題とその解決策

- protocol を any → some とする場合、型解決が複雑になる - アーキテクチャ実現のための、多くのボイラーコードが必要 - モック用の DI Container の準備が手間になる - View のテスト制約 - XCUITest: 長い実行時間、低いメンテナンス性 - Previews: 目視確認が必要、エラーが自動的には検出されない

### → [Sourcery]( https://github.com/krzysztofzablocki/Sourcery)、[Mockolo](https://github.com/uber/mockolo)、[PreviewSnapshots](https://github.com/doordash-oss/swiftui-preview-snapshots ) の導入

## FIA の実装を助けるライブラリの紹介

- [Sourcery]( https://github.com/krzysztofzablocki/Sourcery ) - 繰り返しとなるボイラーコードの自動生成 - [Mockolo]( https://github.com/uber/mockolo ) - モック用の DI Container の自動生成 - typealias での some protocol の型解決にも対応 - [PreviewSnapshots]( https://github.com/doordash-oss/swiftui-preview-snapshots ) - Previews のコードをスナップショットテストとして転用可能

これらのライブラリを採用したリポジトリを公開: https://github.com/suguruTakahashi-1234/fia-practical-sample

- [Framework-Independent Architecture (FIA)]( https://github.com/suguruTakahashi-1234/framework-independent-architecture ) - Clean Architecture をベースにしたアーキテクチャ - Framework 層に非依存である - FIA 採用の目的 - ビルド時間の短縮 - Clean Architecture のメリットの享受 - FIA での実装 - MVP (MVVM) からリアーキテクチャが可能である - [Sourcery]( https://github.com/krzysztofzablocki/Sourcery ) や [Mockolo]( https://github.com/uber/mockolo ) などの自動生成ツールが有効である

# Thank You🌸

presentation layer clean architecture

Suguru Takahashi

Other decks in programming.

presentation layer clean architecture

自己紹介 高橋 俊 iOS エンジニア アカウント X: @ikuraikuraaaaaa GitHub: @suguruTakahashi-1234

話すこと clean architecture を使って ios アプリを爆速でビルドする方法 = framework-independent architecture (fia), 話さないこと clean architecture の詳細 4, ios アプリ開発における 現状のアーキテクチャ候補 5, 大きくこれらの 3 パターンに分けられる layered architecture 系 (mvvm, mvp, viper) →, architectural patterns for ios app development clean architecture-based layered architecture-based, framework-independent architecture とは f = framework layer = framework 層に, framework layer 10, framework layer clean architecture の 最も外側の層 data access layer, fia を採用する目的 xcode でのビルド時間の短縮 テスト、previews も対象 clean architecture のメリットの享受 独立性, clean area non-clean area application layer (development) application layer (production), framework-independent architecture (fia) - circle domain 3rd party presentation framework, リアーキテクチャを通して fia での実装の実演 live 動画リンク 15, リアーキテクチャのステップ 1. mv 2. mvp (mvvm) (not repository pattern) 3., それぞれのアーキテクチャの特徴 17, mv メリット シンプル デメリット ビジネスロジックのテストができない テスト xcuitest での ui テスト, mvp (mvvm) (not repository pattern) メリット view とビジネスロジックの分離 ビジネスロジックのテスト可能 デメリット, mvp (mvvm) + repository pattern メリット ビジネスロジックとデータアクセスの分離 モックによるデータの差し替えが可能 データアクセスロジックのテストが可能 デメリット, clean architecture メリット presentation 層 (view, presenter (viewmodel)) が、  framework, framework-independent architecture (fia) メリット framework 層に非依存なアプリ/ モジュールのビルドの高速化 デメリット application 層からの, fia で可能なテスト test type di container test target: view interaction, fia の実装課題とその解決策 protocol を any → some とする場合、型解決が複雑になる アーキテクチャ実現のための、多くのボイラーコードが必要 モック用の, fia の実装を助けるライブラリの紹介 sourcery 繰り返しとなるボイラーコードの自動生成 mockolo モック用の di container の自動生成 typealias, まとめ framework-independent architecture (fia) clean architecture をベースにしたアーキテクチャ framework 層に非依存である fia, thank you 27.

presentation layer clean architecture

IMAGES

  1. Clean Architecture

    presentation layer clean architecture

  2. A primer on the clean architecture pattern and its principles

    presentation layer clean architecture

  3. Introducing Clean Architecture by refactoring a Go project

    presentation layer clean architecture

  4. A quick introduction to clean architecture

    presentation layer clean architecture

  5. Clean Architecture based on my open-source project

    presentation layer clean architecture

  6. Flutter Clean Architecture Sample App

    presentation layer clean architecture

VIDEO

  1. Beginner's Guide to Clean Architecture Project Structure for ASP.Net Core C#

  2. MVVM vs. Clean Architecture

  3. Thick soil layer, clean donkey hooves!

  4. Clean Architecture Application Layer

  5. 맑은 한 겹 톤 업 선(One Layer Clean Tone up Sun)

  6. BLoC Clean Architecture and Presentation Layer with Use cases

COMMENTS

  1. Clean Architecture Guide (with tested examples): Data Flow ...

    Clean Architecture Layers. Let's identify the different layers & boundaries. Presentation Layer contains UI (Activities & Fragments) that are coordinated by Presenters/ViewModels which execute 1 or multiple Use cases. Presentation Layer depends on Domain Layer. Domain Layer is the most INNER part of the onion (no dependencies with other layers) and it contains Entities, Use cases ...

  2. How To Approach Clean Architecture Folder Structure

    Clean Architecture is a popular approach to structuring your application. It's a layered architecture that splits the project into four layers: Domain. Application. Infrastructure. Presentation. Each of the layers is typically one project in your solution. Here's a visual representation of the Clean Architecture:

  3. Clean Architecture

    An introduction to Clean Architecture, along with a comparison to the traditional N-Tier architecture. ... The Presentation Layer is the entry point to the system from the user's point of view. Its primary concerns are routing requests to the Application Layer and registering all dependencies in the IoC container. Autofac is my favourite ...

  4. Clean architecture tutorial: Design for enterprise-scale apps

    Clean architecture is a staple of the modern app development space. Particularly popular for Java and Android developers, this architecture is designed to make it easier to create stable apps even when outer elements such as UI, databases, or external APIs are always changing. The focus on constant iteration has become a staple of companies ...

  5. Clean Architecture: Understand the Presentation Layer's Purpose

    ☄️ Master the Modular Monolith Architecture: https://bit.ly/3SXlzSt📌 Accelerate your Clean Architecture skills: https://bit.ly/3PupkOJ🚀 Support me on Patre...

  6. Clean Architecture in .NET

    With Clean Architecture, it is possible to scale each layer of the application independently. This gives us the flexibility to adapt to the changing performance requirements of the application. For example, the Core business logic layer can be scaled separately from the Infrastructure or the Presentation layers.

  7. Clean Architecture with .NET and .NET Core

    With Clean Architecture, ... This layer is also called a Presentation. Presentation Layer contains the UI elements (pages, components) of the application. It handles the presentation (UI, API, etc ...

  8. Clean architecture explored

    The domain layer sits between the presentation layer and the data layer. It contains business logic. This layer consists of entities, use cases, and contracts — (abstract) classes of repositories. It's a crime (according to clean architecture rules) for this layer to reference classes, functions, and imports of the presentation or data layer.

  9. Clean Architecture With React

    Transform React Application Into Clean Architecture. When you start your application code from the react application's template (e.g. skeleton created by create-react-app), all codes are included in Presentation layer at first.This is because react (and all UI frameworks) focuses on how to present data to users.

  10. Clean Architecture with .NET Core: Getting Started

    The project names within src align closely to the layers of the Clean Architecture diagram, the only exception being WebUI, representing the Presentation layer.. The Domain project represents the Domain layer and contains enterprise or domain logic and includes entities, enums, exceptions, interfaces, types and logic specific to the domain layer.This layer has no dependencies on anything external.

  11. Comparing Three-Layered and Clean Architecture for Web Development

    Classic three-layer architecture. UI or presentation layer. This is the layer with which the user directly interacts. This layer is a user interface, the mechanism for getting input from the user. ... The only significant advantage I can think of when comparing three-layer architecture to Clean Architecture is simplicity:

  12. Building ASP.NET Core Apps with Clean Architecture

    Implementing Clean Architecture Presentation Layer. The presentation layer is the out most layer of the clean architecture and it presents some GUI or exposes some public API to interact directly with the end user or other client applications. The presentation layer should not contain business logic or domain knowledge and should only interact ...

  13. Chapter 4. The presentation layer

    The presentation layer. Learn the rules like a pro, so you can break them like an artist. Abstractly speaking, the presentation layer is simply the segment of a computer system responsible for providing a user-friendly interface, representing data visually, ensuring a positive user experience, and facilitating communication with other layers of ...

  14. Multiple ways of defining Clean Architecture layers

    Brief into to Clean Architecture. Without going into too many details about CA we will define classic 3-layer architecture (we could have more layers). Each layer has a distinct set of responsibilities: Presentation layer - presents data to a screen and handle user interactions; Domain layer - contains business logic

  15. Flutter Clean BLoC Architecture

    The Presentation Layer plays a crucial role in Flutter applications built using the Clean BLoC Architecture. As the UI layer, it handles user interactions, displays information, and acts as an ...

  16. Exploring Clean Architecture in Flutter: Presentation, Data, and Domain

    Understanding Clean Architecture. Clean architecture is a software design philosophy that advocates for the separation of concerns in application development. It encourages the organization of code into distinct layers, each with a specific responsibility. The primary layers include: Presentation Layer: This layer is responsible for user ...

  17. Clean Architecture with Dependency Rule

    Clean architecture is the most commonly used architecture pattern in software engineering. It is a software design practice that separates the elements of a design into circle levels .

  18. Unpacking the Layers of Clean Architecture

    Layer Service Responsibilities; Application: AccountExportService - Validates the account exists - Queries the DB for all transactions belonging to the account - Passes the data to Infrastructure to generate an XML file - Returns the XML file to the Presentation layer: Domain: TaxCalculationService - Based on applicable tax rates and account funds will calculate and return the amount of tax ...

  19. The Presentation Layer

    The Presentation layer has 3 layers: Controllers are responsible for handling the inputs; Presenters are responsible for handling the outputs; Middlewares exist in the middle, they can either help during the input or the output. Inside the Api directory you will only see Middlewares and Controllers. That's because the Presenters are embedded ...

  20. Clean Architecture: Mapping between layers

    Going by Guide to app architecture for android, the higher layer should depend on the lower layer and not the other way around. To make this possible, the mappers between two layers should be defined in the higher layer. Take a look at my answer to a similar question. It should also be noted that these are mere guidelines and you are free to ...

  21. What is the responsibility of Infrastructure layer in a clean architecture?

    I am trying to follow Clean Architecture by Uncle Bob. I have 3 layers: Core (Hosts business logic, and is the central layer) Application (Host application usecases, and is directly above the core) Infrastructure; I know the responsibility of the Infrastructure layer is to host any external dependencies that our application needs.

  22. In clean architecture, is the presentation layer allowed to communicate

    I have an application using the classic clean architecture with all the dependencies set up as described (i.e. flowing inward). I have an external service I wish to use in my project, so defined the functionality (objects that interact with the service, some interfaces etc.) for interacting with that service in the Infrastructure layer.. Currently the Presentation layer is consuming the ...

  23. Clean Architecture (Domain Layer)

    Domain Layer. In the domain layer, I've focused on four key aspects: Value Objects: They represent immutable and fundamental concepts in the application's domain. Entities: These are objects that have a unique identity and can change over time. Commands and Their Validators: Handling the actions that can be performed in the domain and their ...

  24. Framework-Independent Architecture (FIA)

    Clean Architecture メリット Presentation 層 (View, Presenter (ViewModel)) が、 Framework 層 (Repository (Driver)) に非依存になる → 3rd パーティー製ライブラリの乗換えによる影響が限定的 デメリット Domain Entity の定義の発生 テスト Clean Architecture に変更しても MVP (MVVM) + Repository Pattern から追加で実施できるテストは ...