How to Structure Your Domain Driven Design Project in ASP.NET Core

Charles
6 min readSep 6, 2023

--

Software development has evolved over the years and the need for new architectures to build a more robust software’s is key. These architectures are:

These architectures are used in building software and depending on the kind of application you are developing should determine the kind of architecture to use.

If you are developing a simple crud application, you may end up using the Monolithic or the N-Layer architecture. But, if you are developing a complex business application that is ever-changing, the clean architecture or the DDD may be the right choice and they are similar.

The Microservices architecture are services that are independent, loose-coupled, scalable and independent deployable services.

This article is not about software architectures but how to structure a DDD architecture project from ground-up. If you want to learn about the DDD architecture and all its concepts, check out this Udemy full course on DDD with source code included. It contains all the information listed in this article.

DDD and Clean Architecture

Domain Driven Design and the Clean Architecture are similar. The difference between them is that the DDD architecture requires domain experts that understands the business domain. In DDD, domain experts and the Software Engineers work together. A domain expert doesn't need to have any programming experience, but can defined use-cases and understands how the business domain works. The Clean Architecture focuses on organizing the application in a way that encourages maintainability and testability through a clear separation of concerns.

DDD emphasizes modeling the core business concepts, situations, processes, and rules in a way that closely reflects the real-world domain.

Structure of a DDD Application

A DDD project contains three layers:

  • The Domain Layer
  • The Infrastructure Layer
  • The Application Layer
Structure

Domain Layer

The Domain layer is the hearth of the business software. Without this layer, other layers cannot exist because they are dependent on this layer. This is where the domain expert and software engineers defines the business concepts, situations, behaviors and rules. This layer is “persistence ignorant”, that means it does not define any database logic and it does not depend on any other layer.

Domain Layer

Project Structure

Entities Folder

  • Entities: Entities are domain object that are identified by their identity. Popular DDD author Eric Evans says, “an object primarily defined by its identity is called an Entity.” If you are familiar with Entity Framework, the entities are just POCO classes with an rich domain model that defines behaviors, private setter properties and read-only collections.
    Entities can also be a child entity that the parent entity depends on and can also define aggregates.
  • Aggregates: Aggregates are group of entities that can be treated as a cohesive unit. For example, a Student entity would contains a StudentCourse child entity because a student can enroll for multiple courses. The Student and StudentCourse entity are related, so they should be in a StudentAggregate folder. The Student entity can be seen as the aggregate root or root entity within the StudentAggregate folder and the StudentCourse entity is a child entity. The StudentAggregate folder can also contain value objects.
  • ValueObjects: Value objects are like owned entities in EF. As Eric Evans has noted, “Many objects do not have conceptual identity. These objects describe certain characteristics of a thing.” For example, the Address class can be a value object because it does not have any conceptual identity and it belong to the Student entity. The value object can be configured in the Infrastructure layer as owned entity in EF core. Note, behaviors are mostly defined in the aggregate root or root entity.

SeedWork: A folder that contains base classes and interfaces and can also be named Common or SharedKernel

DomainEvents: A folder that contains classes that implement the MediatR INotification interfaces. Domain events are used to communicate with other entities or aggregates when something happens in the domain. For more information on DomainEvents with the MediatR library check this article.

Specification: A folder that contains concrete and base classes for the specification pattern in DDD. The Specification pattern can be applied to the Domain Driven Design Architecture that is intended to be used to define logic for optional sorting, filtering and paging logic. For more information on Specification pattern check this article.

For a basic DDD project, the Specification folders can be optional. DDD is best suited for complex business applications. If you are developing a simple application, you may not need this architecture.

After the domain layer, the next layer to develop should be the infrastructure layer that defines the persistence technology.

Infrastructure Layer

The Infrastructure layer defines the persistence technology. In this layer Entity Framework is used to map the Entities defined in the Domain Layer. This class references the Domain Layer.

Infrastructure Layer

Project Structure

EntityConfiguration: A folder that defines how the entities would be configured for each entities that is held in the Domain layer. EF is used to configure the entities.

Extensions: A folder that defines extension classes. For example, the optional MediatorExtension class that is used to dispatch all events to their respective handlers before SaveChanges() can be defined here.

Migrations: All changes made to the entities are in EF are stored in this folder.

Repositories: A folder that defines the repository pattern. This folder contains the GenericRepository<T> class that implements the IGenericRepository<T> contract interface defined in the Domain Layer.

DBContext class: A class that defines the EF database context that contains the entity properties defined in the Domain layer as DBSets<TEntity>.

Application Layer

In a DDD project, the application layer is usually a WebAPI project but can be a mobile app project or razor pages. This layer is for presentation purposes. This layer depends on the Domain layer as a compile time dependency and also the Infrastructure layer as a runtime dependency.

The application layer makes heavy use on DI through constructor DI, so there is no direct dependency on the Infrastructure layer but a runtime dependency.

Project Structure

Application Folder

CQRS: CQRS stands for Command Query Responsibility Segregation. CQRS is a pattern that separates the reads and writes operation for a data store. This folder defines two folders:

  • Command: Command a not side-effect free and this is where the writes are defined. Writes can be anything that changes the state of the database like the updates and inserts statements. This folder contains classes with handlers. The handlers is responsible for dispatching changes by using the MediatR library. For example, the EnrollCourseCommand class and the EnrollCourseCommandHandler. To trigger the handler, the Mediator.Send(EnrollCourseCommand) is called in the controller or anywhere else that will trigger the Handler method in the EnrollCourseCommandHandler class.
  • Queries: Queries are side-effect free. This is where you define classes with reads. You can write direct queries using dapper or work with repositories.

DomainEventHandlers: This folder contains the domain event handlers with their respective domain events defined in the Domain layer. The classes implement the INotificationHandler<TDomainEventClass> from the MediatR library.

Conclusion

Once you become acquainted with the MediatR mediator pattern library, things will become clearer. CQRS and DomainEvents utilize the mediator implementation provided by the MediatR library.

To gain a deeper understanding of how DDD operates, consider exploring an easily comprehensible Udemy course that explains everything from the basics with the source code included.

Once you feel comfortable with DDD, knowledge of Clean Architecture and others will prove beneficial.

Additionally, if you’re interested in learning a robust frontend framework, take a look at an all-in-one course covering Typescript, React, and NextJs. This course also includes a backend developed in .NET to further enhance your software development skills.

Happy coding!

--

--