Overview
SGRH implements Clean Architecture principles to ensure separation of concerns, maintainability, and testability. The system is organized into distinct layers, each with specific responsibilities and clear dependency rules.The key principle: Dependencies flow inward. Outer layers depend on inner layers, but inner layers never depend on outer layers.
Architecture Layers
Domain Layer (Core)
The innermost layer containing business logic, entities, and domain rules. Has zero dependencies on other layers.
- Location:
SGRH.Domain/ - Contains: Entities, Value Objects, Domain Events, Exceptions, Enums
- Dependencies: None (pure C# business logic)
Application Layer
Contains use cases and orchestrates domain objects to fulfill business requirements.
- Location:
SGRH.Application/ - Contains: Commands, Queries, DTOs, Mappings, Application Services
- Dependencies: Only
SGRH.Domain - Frameworks: MediatR, FluentValidation
Infrastructure Layer
Implements interfaces defined by domain/application layers for external concerns.
- Location:
SGRH.Infrastructure/,SGRH.Persistence/ - Contains: Database access, Email services, File storage (S3), External APIs
- Dependencies:
SGRH.Domain,SGRH.Application
Project Structure
Dependency Flow
Implementation Examples
Domain Layer Independence
The domain layer defines interfaces for what it needs, but doesn’t implement them:Persistence Layer Implementation
The persistence layer implements domain interfaces using Entity Framework:SGRH.Persistence/UnitOfWork/UnitOfWork.cs
Domain Services
Complex business rules are encapsulated in domain policies:SGRH.Domain/Abstractions/Policies/IReservaDomainPolicy.cs
The domain defines the policy interface, but the implementation lives in
SGRH.Persistence where it can access the database.Benefits of This Architecture
1. Testability
- Domain logic can be tested without databases or external services
- Application use cases can be tested with mocked repositories
- Each layer can be tested independently
2. Maintainability
- Changes to infrastructure (e.g., switching databases) don’t affect business logic
- Business rules are centralized in the domain layer
- Clear separation makes code easier to navigate
3. Framework Independence
- Business logic is pure C# - no framework dependencies
- Can swap Entity Framework for Dapper without touching domain
- Can change from REST API to gRPC by only changing presentation layer
4. Flexibility
- Multiple presentation layers (API + Desktop app) share the same application layer
- Infrastructure can be swapped (e.g., AWS SES → SendGrid)
- Domain remains stable while outer layers evolve
DbContext Configuration
TheSGRHDbContext is configured in the presentation layer but used by the persistence layer:
SGRH.Api/Program.cs
SGRH.Persistence/Context/SGRHDbContext.cs
Best Practices
Keep Domain Pure
Never reference external frameworks in the domain layer. Use only pure C# and .NET standard libraries.
Define Abstractions
When domain needs external data, define an interface in
Domain/Abstractions/ and implement it in infrastructure.Use Dependency Injection
All dependencies should be injected through constructors, following the Dependency Inversion Principle.
Separate Concerns
Each layer should have a single responsibility. Don’t mix business logic with data access or presentation.
Common Pitfalls to Avoid
Related Concepts
Domain-Driven Design
Learn how DDD patterns structure the domain layer
CQRS Pattern
Understand how commands and queries separate concerns