Clean Architecture With .NET 6 And CQRS - Project Setup
Introduction to Clean Architecture
Overview of Clean Architecture
- Milan introduces the topic of clean architecture, outlining that the first part will cover the "why" behind it, while the second part will demonstrate a project setup and implementation details.
Layers of Clean Architecture
- The clean architecture consists of four distinct layers: domain layer (core), application layer (orchestrates business logic), infrastructure layer (external systems), and presentation layer (user interaction).
Domain Layer
- The domain layer is central to the architecture, defining domain entities, aggregates, value objects, and custom exceptions. It should not reference any outer layers.
Application Layer
- This layer orchestrates use cases and is typically implemented as application services or using CQRS patterns with commands and queries.
Infrastructure Layer
- The infrastructure layer handles external system integrations like database access and messaging services while hiding implementation details.
Presentation Layer
- This layer serves as an entry point for users to interact with the system, often implemented as RESTful APIs or modern alternatives like gRPC.
Project Setup in Visual Studio
Structure of Projects
- Milan demonstrates a Visual Studio project setup that mirrors the clean architecture layers: core folder containing domain and application layers; external folder containing infrastructure and presentation projects.
Domain Layer Implementation
- In the domain layer, there is an 'entities' folder defining a single entity called Webinar with properties such as ID, name, and scheduled date.
Entity Class Details
- The entity class contains only one property: ID. In DDD (Domain Driven Design), two entities are equal if they share the same identifier.
Custom Exceptions in Domain Layer
- A custom exception for when a webinar is not found is defined here; this exception is thrown from the application layer during database fetch attempts for non-existent webinars.
Abstractions in Domain Layer
- Interfaces for repository patterns are defined in this section; implementations reside in other layers. This includes interfaces for repositories and unit of work patterns.
Application Layer Implementation
Commands and Queries Structure
- The application layer uses CQRS pattern with separate folders for commands (writing data) and queries (reading data).
Command Example: Create Webinar
- A command named "Create Webinar" contains necessary data fields such as name and scheduled date.
Command Handler Functionality
- Inside its handler method, it creates a new webinar using the repository defined earlier. It completes transactions via unit of work to return the new webinar's ID.
Understanding Clean Architecture in Application Development
Query Handling and Performance Optimization
- The application features a query to retrieve webinars by ID, which requires only the webinar ID for response. This is managed through the
get webinarquery handler.
- To enhance performance, raw SQL is executed directly on the database instead of using repositories or unnecessary abstractions, allowing efficient data retrieval.
Implementation of CQRS Pattern
- A library called Mediator is utilized for implementing the Command Query Responsibility Segregation (CQRS) pattern, featuring a pipeline behavior akin to middleware in ASP.NET.
- Commands sent via Mediator are validated; any errors trigger a validation exception that is handled at higher layers of the application.
Infrastructure Layer Overview
- The infrastructure layer includes a defined DB context using Entity Framework and a simple repository implementation for inserting webinars.
- It’s common to separate the infrastructure layer into persistence (database access) and other external systems (e.g., email notifications, message queues).
Presentation Layer Structure
- Controllers are defined outside of the web application to support dependency injection without referencing all projects in the solution.
- Two endpoints are created: one for retrieving webinars by ID and another for creating new webinars, utilizing Mapster as a mapping library.
Dependency Injection Considerations
- Defining controllers outside of the web application allows control over project references, preventing direct access to infrastructure components from presentation layers.
- Moving controllers into a presentation class library enforces architecture integrity by limiting what can be referenced within different projects.
Configuration for Controller Functionality
- In
startup.cs, service registrations include adding controllers from the presentation assembly to ensure proper configuration and routing functionality.
Exception Handling Middleware
- An exception handling middleware class wraps application execution with try-catch blocks to log errors and return standardized API error responses.
Future Directions in Clean Architecture Implementation
- The speaker plans future videos detailing implementation steps starting from the domain layer up through other clean architecture layers. Feedback on previous experiences with clean architecture is encouraged.