Clean Architecture In Enterprise Application
A brief introduction to Clean architecture
Clean architecture is a software architecture guideline proposed by Robert C. Martin(Uncle Bob) that aims to build scalable, testable, and maintainable software. It’s derived from many architectural guidelines like Hexagonal Architecture, Onion Architecture, etc. over the years.
Clean Architecture concepts
Clean architecture is a software architecture pattern that aims to achieve the following goals:
- Independent of frameworks: The core business logic of the application should not be dependent on any specific framework or technology. This makes the application more flexible and easier to maintain.
- Testable: The business logic should be easily testable in isolation from the rest of the application.
- Maintainable: The code should be well-organized and easy to understand. This makes it easier for devs to make changes to the application without breaking things.
The basic principles of clean architecture are:
- Dependency rule: Dependencies should always point inwards.
- Abstraction: Use interfaces to abstract away the details of the implementation.
- Separation of concerns: Separate the different parts of the application into different layers. This makes the code easier to understand and maintain.
Layers in Clean Architecture
- Entities:
This layer contains enterprise-wide business rules and is independent of the other layers. In OOP, this is the Object with methods and properties that comply with the Encapsulation principle — only inside the Object can change its own state.
Example: Entity could be a User
object that contains properties like Age
, etc. The Age
property can’t be less than 1. If we need to change Age
, we must write a public function set Age
, which is also responsible for checking conditions related to Age
.
The business logic of the Entities layer won’t care about or depend on the business logic in external layers such as Use Cases. Assuming the user must be 18 years old or older to create an account, the Age
attribute rule in Entities remains unchanged.
2. Use cases
This layer contains application-specific business rules and is dependent on the Entity layer.
Example: The use case could be a CreateUser
class that contains methods for creating a new user.
The business logic of the Use Case won’t care and depends on where the data comes from, what libraries are used as adapters, how the data is presented, etc. Because that is the task of the Interface Adapters
layer.
3. Interface Adapters
This layer contains adapters that convert data from the Use Case layer into a format that can be displayed by the user interface
Example: Interface Adapters could be a UserController
class that handles HTTP requests and responses for user-related operations.
Thus, the input and output data at the Interface Adapters layer only needs to be sufficient and reasonable. It won’t care how specifically the data will be displayed or collected. Because that is the task of the Frameworks & Drivers layer.
4. Frameworks and Drivers
This layer contains frameworks and tools that support the other layers such as devices, web, applications, databases, etc.
Example: An example of this layer could be a Database
class that handles database operations for the application.
This table below is to help you quickly keep track of layers in Clean architecture.
| Name | Content | Dependency |
|---------------------|--------------------------------------------------------------|-------------------------------------------------|
| Entities | Core business data and rules. | None |
| Use Cases | Application-specific business rules. | Depends on Entities, independent of Frameworks |
| Interface Adapters | Input and output mechanisms (UI, databases, frameworks). | Depends on Use Cases, independent of Frameworks |
| Framework & Drivers | External tools, frameworks, and technology-specific details. | Depends on Interfaces and Use Cases |
Project structure
Clean architecture aims to create modular and maintainable software by organizing code in a way that separates concerns and dependencies.
The primary goal is to achieve a clear separation of concerns while allowing flexibility for change.
🛠️MyAppServiceSolution/
├── #️⃣MyApp.Shared/ - (It contains shared components, which aren't required in Clean architecture. It serves as your common service or packages in the future)
│ └── …
├── #️⃣MyApp.API/
│ ├── 📂Controllers/
│ │ ├── UserController.cs
│ ├── 📂Extentions/ - Contains config extensions for the API layer
│ │ ├── AppExtension.cs
│ ├── Startup.cs
│ └── …
├── #️⃣MyApp.Dtos/
│ ├── 📂Users/
│ │ ├── UserRequestModel.cs
│ │ ├── UserResponseModel.cs
│ └── …
├── #️⃣MyApp.Application/
│ ├── 📂Services/
│ │ ├── 📂Interfaces
│ │ ├── IUserService.cs
│ │ ├── UserService.cs
│ ├── 📂Dtos/
│ │ ├── UserDto.cs
│ └── …
├── #️⃣MyApp.Domain/
│ ├── 📂Entities/
│ │ ├── User.cs
│ ├── 📂Repositories/
│ │ ├── IUserRepository.cs
│ └── …
├── #️⃣MyApp.Infrastructure/
│ ├── 📂Persistence/
│ │ ├── 📂EntityConfigurations
│ │ ├── 📂Migrations
│ │ ├── 📂Repositories/ - Implement interface repositories from MyApp.Domain
│ │ │ ├── UserRepository.cs
│ │ ├── 📂Extentions/ - Contains config extensions for the Infrastructure layer
│ │ │ ├── ModelBuilderExtensions.cs
│ │ ├── MyAppContext.cs
│ └── …
└── #️⃣MyApp.Tests/
├── 📂MyApp.UnitTests/
├── 📂MyApp.IntegrationTests/
Map project structure to Clean Architecture
| Name | Layer | Content |
|----------------------|--------------------------------------------|--------------------------------------------------------------------------------------------------------------------------|
| MyApp.API | Interface Adapters | Could be considered as the entry point for your application, interacting with the application layer. |
| MyApp.Application | Use Cases (Application) | It contains services that implement application-specific business rules. |
| MyApp.Contracts | Interface Adapters | The interface layer for Data Transfer Objects (DTOs) is shared between layers. |
| MyApp.Domain | Entities and Business Rules (Core layer) | It contains business entities, repositories, and repository interfaces. |
| MyApp.Infrastructure | Frameworks & Drivers | It manages the database (persistence), contains external configuration extensions, and implements repository interfaces. |
I’ll skeleton Clean Architecture in the next chapter. See ya.
You also reach my blog on dev.to by this link: Clean Architecture In Enterprise Application — DEV Community
When you find this post informative, don’t forget to share it with your team and colleagues, thanks.
You can reach me on Twitter @linhvuquach
to get my new blog every week with a bunch of categories like software engineer, problem-solving, and how to make your product …
Cheers!
References
- What is Clean Architecture? — by Dr Milan Milanović (techworld-with-milan.com)
- How To Approach Clean Architecture Folder Structure (milanjovanovic.tech)
- The Clean Architecture — Beginner’s Guide | by Bharath | Better Programming
- A quick introduction to clean architecture (freecodecamp.org)
- Clean architecture tutorial: Design for enterprise-scale apps (educative.io)
- Implementing clean architecture solutions: A practical example | Red Hat Developer
- Practicing Clean Architecture in C# | by Genny Allcroft | Better Programming
- Clean Architecture Example & Breakdown — CodeOpinion
- Repositories:
- Without DDD: jasontaylordev/CleanArchitecture: Clean Architecture Solution Template for ASP.NET Core (github.com)
- With DDD, and domain events pattern:
— ardalis/CleanArchitecture: Clean Architecture Solution Template: A starting point for Clean Architecture with ASP.NET Core (github.com)
— jasontaylordev/CleanArchitecture: Clean Architecture Solution Template for ASP.NET Core (github.com)