Domain-driven Design (DDD): File Structure
Tags: ddd, javascript, architecture, computerscience
Published: 2020-09-01 22:51:39

# Project Current File Structure
*src* folder
 -*config* folder
 -*database* folder
 -*errors* folder
 -*middlewares* folder
 -*models* folder
 -*repositories* folder
 -*routes* folder
 -*services* folder

The *src* folder should contain our application *modules*. Everything in it impacts directly **how our application functions**.

We currently **separate** our application by **file types**. So files of the service type are stored in the services folder.

The **problem** with this is: if we had 10 models, we would have around 40–50 services. Having so many files that do not deal with the **same module**, or in other words, do not deal with the **same domain** becomes confusing.

# Domain
Is the *sphere of knowledge* that involves that **particular file** or **module**. A set of **business rules**.

So it is not always good to build our project structure around separating files by their type.

A good way to build our project structure is to isolate things according to their **domain**, by using **modules**.

So services related to *users* such as Authenticate User Service, Create Appointment Service, Create User Service, Update User Avatar Service should all belong to the **User Domain**.

There would be an **Appointment Domain** that should only take care of **business logic** related to *appointments*, be it to create appointments, list appointments, check available appointments or cancel appointments.

![DDD can divide an ecommerce in the the delivery context with order, product and customer and the finance context.](https://dev-to-uploads.s3.amazonaws.com/i/achtyekeojee4h8edu2c.png)

# DDD (Domain-driven Design)

**Scrum** is an *agile methodology* that allows the team to organize and execute their tasks in an agile manner.

But **Scrum** does not work in the same way for all teams and projects, we implement the ideas and concepts in the way that makes more sense for our context. **DDD** works in the same way, there are some concepts that only make sense in enterprise applications (very big applications).
# Modules
What are the **modules** (*spheres of knowledge*) that  we have in our application? The **user domain** and the **appointment domain**.
We must create a ***modules*** **folder** to accommodate our modules and inside it we create the ***users*** and ***appointments*** **subfolders**.
## What can we store inside the modules/users folder?
* DTOs
* Entities/Models
* Repositories (including our fake/mock implementations of them for TDD), services
* Providers that are specific to users (a hash provider that hashes the user password)
* Infra that is specific to users (we will see below what the infrastructure layer means).

# Shared
Files with logic that is shared between all modules or multiple modules should be saved in the *shared folder* that is outside of the modules folder.
## What can we store inside the shared folder?
* Errors
* Shared database files(connections and migrations)
* Shared routes
* Shared middleware
* Shared providers (storage provider, email provider).

# Infrastructure Layer vs Domain
**Domain**: Is the ***sphere of knowledge*** that involves that particular module. A set of **business rules**. It takes care of how the application should work.

**Infrastructure Layer**: Is how data that is initially held by in the domain's entities (memory) is persisted in databases or another persistent store. the infrastructure layer must not "contaminate" the domain model layer. 
**NOTE**: It contains our application's technical decisions

When creating [eBarber](https://github.com/stevescruz/ebarber_web) a **meeting with the barbers or the users** will help you better determine the Domain/Business Logic. But a barber does not have the expertise to tell you what tools you should use: if you should use an ORM or a Query Builder.

A CTO and/or senior engineers decide things that are related to the infrastructure layer.

The **user domain** knows that when a user signs up he should receive an email, but it does not know what tool is being used to send emails. That is the role of the Infrastructure Layer.

![The domain layer (service, repository, domain object) should not depend on the infrastructure layer nor the application layer](https://dev-to-uploads.s3.amazonaws.com/i/h134ezqol2olgh6h8ojs.png)

Read: [Microsoft & DDD-oriented Microservices](https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/ddd-oriented-microservice)
## Infra
To accommodate the infrastructure layer we can create multiple *infra* folders. We can have an *infra* folder inside our *shared* folder and inside each of our *modules* (*users* and *appointments*).

We can create a *database* folder inside the *infra* folder to deal with things related to our database. We should give it a specific name, since our project uses TypeORM, we should name our *database* folder as ***typeorm***.

We can also create a *http* folder inside the *infra* folder to deal with things related to our http requests and responses such as *server.ts*, routes and middleware.
**NOTE**: Once again we should give it a specific name. If we were using another type of protocol such as **gRPC** we would give it another name.
## Additional Notes
1. Infra will store all information that is responsible for a specific package or library.
Example: TypeORM.
2. Errors may be shared but they are not part of the infra layer.
3. It is good to include things that could change in the infra folder.
  * Example 1: Express routes and middleware.
  * Example 2: Imagine if we need to change the communication protocol from HTTP to gRPC.

# Project File Structure using DDD

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/6oxzwmipotzwlrkcmjv4.png)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/vhwtp9azq29evtl0ade1.png)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/1c4ftl981yqwdpyndcwv.png)

#Final considerations

The **main advantage** of Domain Driven Design is being able to create code with well-defined components that have **clear contracts** between them. This allows us to better define their responsibilities, makes **updating** or **replacing** one of these components much easier with **less impact** on the overall system.

The key **disadvantage** is that DDD assumes that you have a fairly clear picture of the solution you are trying to produce, but that is not always the case. A solution to this problem is to create a small prototype, possibly iterate over it multiple times until you have enough understanding to come up with the reasonable design. This can delay the start of the project, but is likely to result in a more maintainable solution.

This post only touches the tip of the iceberg, I encourage you to **read more about DDD** including about the **application layer**.

# Keep in touch
Contact me through my social media. Let's talk about DDD, TDD and good practices, be it on [LinkedIn](https://www.linkedin.com/in/stevescruz/) or [GitHub](https://github.com/stevescruz).

Share with us how you decide your project file structure.