NestJS is a Node.js framework that utilizes TypeScript for backend development. Domain-Driven Design (DDD) is a methodology for organizing application structure, enhancing maintainability, and facilitating scalability. This text explains how DDD principles are applied within NestJS, adhering to best practices that streamline development and ensuring fluidity, security, and organization.
One of the initial considerations when starting a project is where to place files and how they will relate to each other. A well-organized folder structure is crucial for maintaining and scaling an application. Here are some key concepts to follow for standardizing folder organization:
The project should be divided into unique folders for each feature. This approach enhances code location and standardization. All functionalities related to users, for instance, should reside within a users
folder.
Additionally, file names should reflect their functionalities, further aiding in easy location. Files handling the same functionality should be within the same folder, ensuring all necessary components are consolidated.
Here's an example that illustrates this concept:
src/
├── users/
│ ├── controllers/
│ │ └── users.controller.ts
│ ├── services/
│ │ └── users.service.ts
│ ├── dtos/
│ │ └── create-user.dto.ts
│ ├── entities/
│ │ └── user.entity.ts
│ ├── repositories/
│ │ └── users.repository.ts
│ ├── users.module.ts
├── auth/
│ ├── controllers/
│ │ └── auth.controller.ts
│ ├── services/
│ │ └── auth.service.ts
│ ├── dtos/
│ │ └── login.dto.ts
│ ├── entities/
│ │ └── auth.entity.ts
│ ├── repositories/
│ │ └── auth.repository.ts
│ ├── auth.module.ts
├── products/
│ ├── controllers/
│ │ └── products.controller.ts
│ ├── services/
│ │ └── products.service.ts
│ ├── dtos/
│ │ └── create-product.dto.ts
│ ├── entities/
│ │ └── product.entity.ts
│ ├── repositories/
│ │ └── products.repository.ts
│ ├── products.module.ts
├── app.module.ts
├── main.ts
Modules act as the glue between components, services, and controllers. They are defined using the @Module()
decorator, encapsulating specific functionalities and able to import other modules as needed.
Controllers handle HTTP requests and are responsible for API endpoints. They utilize services to execute business logic and return specific information to users.
Controllers should not contain business logic; instead, the logic should reside within the Service layer, limiting the controller to handling requests and delegating business logic applications to services.
Services are crucial files within the application containing business logic. They are used by controllers to perform complex operations such as database interactions, validations, and data manipulation.
Defined using the @Injectable()
decorator, services can be injected into controllers or other services.
Data Transfer Objects (DTOs) are objects used to transfer data between different parts of the application. They ensure data validity checks, consistency, and organization.
An example of their use is when constructing an application where users can register. Here’s how it looks:
Define a DTO to represent the data transferred between the user creation route. The DTO may contain specific properties required for creating a new user, such as name, email, and password:
class CreateUserDTO {
constructor(public name: string, public email: string, public password: string) {}
}
export default CreateUserDTO;
userService
) for additional processing, such as saving to the database.
Folder structures should align with the functionality of each folder type: