Companion Repository for the Medium Article: > Mastering Domain-Driven Design: A Tactical DDD Implementation
This repository demonstrates a production-grade implementation of Tactical Domain-Driven Design (DDD) using .NET (targeting .NET 10 standards). It moves beyond simple "Hello World" examples to tackle real-world complexity, focusing on Rich Domain Models, Encapsulation, and Automated Architectural Governance.
The goal is to show how to build systems that are secure by design, maintainable, and strictly aligned with business rules.
The solution follows Clean Architecture principles with a strict dependency flow.
Domain-Centric: The Domain layer has zero dependencies. It contains strictly pure C# logic.
Rich Domain Models: No "Anemic" models with public setters. State changes occur only through behavioral methods (e.g., MarkAsShipped()).
CQRS with MediatR: Separation of Reads (Queries) and Writes (Commands).
Internal Visibility: Command Handlers are internal to the Application assembly to prevent leakage and enforce encapsulation.
-
Advanced Value Objects Value Objects are implemented as sealed records to ensure immutability and structural equality. We use custom operators for arithmetic logic (e.g., Money/Currency).
public sealed record Price(decimal Value, Currency Currency) { public static Price operator +(Price p1, Price p2) => ... }
-
Encapsulated Aggregates Entities use private or protected setters and expose collections as IEnumerable to prevent external modification.
public class Order : AggregateRoot { // Collections are read-only to the outside world private readonly List<OrderItem> _orderItems = []; public IEnumerable<OrderItem> OrderItems => _orderItems.AsReadOnly(); public void AddOrderItem(OrderItem item) { // Business Invariants are checked here, not in the controller ValidateMaxPriceLimit(item); _orderItems.Add(item); } }
-
Automated Architecture Guards 🛡️ Instead of relying on manual code reviews, this project uses NetArchTest to enforce architectural rules via unit tests. If a developer breaks a rule (e.g., puts a Repository in the Domain layer), the build fails.
Guards included:
✅ Domain Entities must not have public setters.
✅ Repositories interfaces must reside in Domain.
✅ Persistence layer must not contain Interfaces (only implementations).
✅ Domain layer must not depend on Application or Infrastructure.
.NET 10
Entity Framework Core (Fluent API Configuration)
MediatR (In-process messaging)
FluentValidation (Input validation)
NetArchTest.Rules (Architecture testing)
xUnit & FluentAssertions (Testing)
SQL Server (Persistence)
Prerequisites
✅ NET SDK ✅ SQL Server (LocalDB or Docker)
Installation
-
Clone the repository:
git clone [https://github.com/tomajexpress/Domain.Driven.Implementation.In.CSharp.NET.Core.git](https://github.com/tomajexpress/Domain.Driven.Implementation.In.CSharp.NET.Core.git)
-
Navigate to the solution folder and build:
dotnet build
| Project | Responsibility |
|---|---|
| EShoppingTutorial.Core.Domain | The heart of the software. Entities, Value Objects, Domain Services. |
| EShoppingTutorial.Core.Application | Use cases, CQRS Commands/Queries, Validators. |
| EShoppingTutorial.Persistence | EF Core DbContext, Repository Implementations, Migrations. |
| EShoppingTutorial.API | Minimal API Endpoints, Dependency Injection setup. |
| EShoppingTutorial.ArchTests | The Guardians. Tests ensuring architectural integrity. |
Contributions are welcome! Please ensure that any PR maintains the "Green" status of the Architecture Tests.
Aman Toumaj Senior Software Developer & Architecture Enthusiast