This is a project I've decided to make in order to show-case the depth of domain-driven design and how it tackles complexity in the heart of software.
I hope that this project can help someone getting started with Domain-Driven design, to sort of grasp ideas that they may have missed out on.
I've also been writing a blog series about Domain-Driven design that's quite provocative but very informative. Also please understand that there many different ways of solving problems in code, and mine isn't necessarily what I think is the "best" or the "only" way, its rather a way, the way I chose to tackle this.
Note: I have severely over-complicated the design in this project to try and show difficult concepts and capture the depth of domain-drivne design. Much of this work can be simplified and not every project, in fact most (small-scale) projects do not warrant the use of Domain-Driven design, let alone clean-architecture.
The overall business problem (space), aka the domain, that we will be focusing on is a business that rents out cars to customers. It may seem straight-forward at first, however, this can be a very complicated domain, depending on how deep we go. There are many invariants and state transitions that require cross-context communication.
- Strategic Design (Subdomains, BoundedContexts, ContextMapping)
- Tactical Design (AggregateRoots, Entities, ValueObjects)
- Event-Driven Architecture (Domain Events)
- CQRS
- ... and more
Domain-Driven Design is not an architectural pattern or a folder structure but rather a way of thinking that encourages modelling code based on the business.
There are many different ways of applying this in terms of code structure and there isn't a "best" way, but for the purpose of this project, I will be using Clean Architecture, an evolution of the Onion architecture that encourages inward-pointing dependencies, adapted by Robert C. Martin in the book "Clean Code".
All of the different variations: clean architecture, onion, ports-and-adapters, hexagonal, etc. are a variation, different visualization, or cosmetic differences of two principles regarding Dependency Inversion as a foundational:
- Abstractions should not depend upon details; details should depend upon abstractions.
- Higher-level modules should not depend upon lower-level modules; both should depend upon abstractions.
Folder structure:
📁 src/
├── 🥜 Demo.SharedKernel/
│ └── ...
├── 🏦 Demo.Domain/
│ └── ...
├── 🔌 Demo.Application/
│ └── ...
├── 🛠️ Demo.Infrastructure/
│ └── ...
└── 🛜 Demo.WebApi/
└── ...
Before running this project, ensure the following are installed on your system:
- .NET SDK 9.0
- Required to build and run the application
- Confirm installation with:
dotnet --version
- VSCode (optional: for development)
- Download the C# Dev Kit extension.
- Alternatively you can use Visual Studio (v17.10 or later)
- Docker
- Used to run the Database & Object-Storage
- Setting up local env
# You can clone directly or fork the repo if you like
git clone git@github.com:L1nque/Portfolio-Domain-Driven-Design.git
# make sure everything is working
dotnet restore && dotnet build
# this will run Psql & MinIO
docker-compose up
# optionally use 'watch'
dotnet run
# You can also run individual tests if you like
dotnet test
All contributions are welcome
Here are some related projects:
Event-Sourcing: A Portfolio Project (coming soon)
Vertical-Slice Architecture (coming soon)
Microservices with .NET (coming soon)