Giới thiệu về CQRS trong NestJS

nestjs cqrs article cover

Một cách tiếp cận phổ biến để phát triển NestJS là xây dựng các dịch vụ mà bộ điều khiển giao tiếp để truy cập dữ liệu. Nhưng cách tiếp cận này không phải là mẫu thiết kế hợp lệ duy nhất trong NestJS. Có các mẫu thiết kế khác, chẳng hạn như mẫu thiết kế CQRS.


CQRS là một mẫu thiết kế phân tách hoạt động đọc và ghi của một ứng dụng. Sự tách biệt này có thể giúp cải thiện khả năng mở rộng, hiệu suất và khả năng bảo trì.

Tìm hiểu tất cả về CQRS và cách bạn có thể áp dụng nó khi xây dựng API NestJS.


CQRS là gì?

CQRS viết tắt của phân biệt trách nhiệm truy vấn lệnh. Nó thực hiện việc sử dụng mệnh lệnh để tạo, cập nhật và xóa dữ liệu và truy vấn để lấy dữ liệu. Điều này giúp loại bỏ nhu cầu triển khai các lệnh gọi cơ sở dữ liệu của ứng dụng vào các dịch vụ.

Nó cũng cho phép phân biệt rõ ràng giữa logic truy vấn cơ sở dữ liệu để tìm dữ liệu và thực hiện các hành động khác trong một ứng dụng.

Phương pháp CQRS rất hữu ích trong thiết kế hướng miền, cho phép bạn tách các hoạt động cơ sở hạ tầng và logic miền trong ứng dụng của mình. Bạn cũng có thể sử dụng nó để triển khai logic nghiệp vụ phức tạp, nhưng điều này không được khuyến nghị cho các ứng dụng đơn giản hơn.

Sử dụng CQRS trong API NestJS

Bạn có thể sử dụng mẫu thiết kế CQRS trong API mà bạn tạo trong NestJS. Để làm theo, bạn cần cài đặt Node.js trên máy tính của mình và phiên bản NestJS gần đây.

Sử dụng các bước sau để xây dựng ứng dụng viết blog đơn giản triển khai mẫu thiết kế CQRS.

Tạo một dự án Nest

Tạo một dự án Nest mới và tạo một bưu kiện tài nguyên cho một ứng dụng blog. Bạn có thể thực hiện việc này bằng cách chạy các lệnh sau trong terminal:

 nest new nestjs-cqrs
nest g module posts
nest g controller posts
nest g service posts

Cài đặt phụ thuộc

Sau khi bạn hoàn thành các bước trên, hãy chạy lệnh đầu cuối này để cài đặt gói NestJS CQRS:

 npm install --save @nestjs/cqrs 

Tạo dịch vụ đăng bài

Thêm đoạn mã sau vào của bạn bài viết.service.ts tập tin để xác định Dịch vụ bưu chính lớp học.

 
import { Injectable } from '@nestjs/common';
export interface Post {
    title: string;
    content: string;
}


@Injectable()
export class PostService {
  private readonly posts: Post[] = [];


  create(post: Post): Post {
    this.posts.push(post);
    return post;
  }


  findById(id: number): Post {
    return this.posts.find(post => post.id === id);
  }
}


Các Dịch vụ bưu chính định nghĩa tạo nênfindById các phương pháp để tạo một bài đăng mới và nhận một bài đăng hiện có từ ID của nó.

Xác định các lệnh và truy vấn

Bước tiếp theo là xác định các truy vấn và lệnh là cốt lõi của mẫu thiết kế CQRS.

bên trong bài viết thư mục, tạo hai tệp mới: tạoPostCommand.command.tsgetPostQuery.query.ts. Tệp lệnh sẽ trông như thế này:

 
export class CreatePostCommand {
  constructor(public readonly title: string, public readonly content: string) {}
}

Và tệp định nghĩa truy vấn, như thế này:

 
export class GetPostQuery {
  constructor(public readonly id: number) {}
}

Tạo trình xử lý lệnh và truy vấn

Sau khi bạn đã xác định thành công các lệnh và truy vấn của mình, bạn cần tạo các trình xử lý cho chúng. Trình xử lý là một hàm chạy lệnh hoặc truy vấn và trả về kết quả.

Tạo một xử lý.ts tập tin trong của bạn bưu kiện thư mục và dán đoạn mã sau vào đó:

 
import { CommandHandler, ICommandHandler } from '@nestjs/cqrs';
import { CreatePostCommand } from './createPostCommand.command.ts';
import { PostService } from './post.service';
@CommandHandler(CreatePostCommand)
export class CreatePostHandler implements ICommandHandler<CreatePostCommand> {
  constructor(private readonly postService: PostService) {}


  async execute(command: CreatePostCommand) {
    const { name, price } = command;
    const post = await this.postService.create(title, content);
    return post;
  }
}


trong cùng một xử lý.ts tệp, bạn có thể sửa đổi các câu lệnh nhập để bao gồm các câu lệnh bên dưới, nhằm cho phép làm việc với các truy vấn. Sau đó, bạn có thể triển khai trình xử lý truy vấn như trong đoạn mã dưới đây:

 
import { QueryHandler, IQueryHandler } from '@nestjs/cqrs';
import { GetPostQuery } from './getPostQuery.query';
import { PostService } from './post.service';

@QueryHandler(GetProductQuery)
export class GetPostHandler implements IQueryHandler<GetPostQuery> {
  constructor(private readonly postService: PostService) {}


  async execute(query: GetPostQuery) {
    const { id } = query;
    const post = await this.postService.findOneById(id);
    return post;
  }
}

Đăng ký xử lý

Bước cuối cùng là đăng ký trình xử lý lệnh và truy vấn với mô-đun NestJS.

 
import { Module } from '@nestjs/common';
import { CommandHandlers, QueryHandlers } from 'handlers.ts';
import { PostService } from './post.service';
@Module({
  providers: [
    PostService,
    ...CommandHandlers,
    ...QueryHandlers,
  ],
})
export class PostModule {}


Mã này đăng ký các Dịch vụ bưu chính, Trình xử lý lệnhTrình xử lý truy vấn bên trong nhà cung cấp mảng. Việc sử dụng toán tử trải rộng () là hợp nhất các mảng của truy vấn xử lý và yêu cầu xử lý vào nhà cung cấp mảng.

Thực hiện các lệnh và truy vấn

Các lệnh đã đăng ký và trình xử lý truy vấn có thể sử dụng được trong bộ điều khiển. Đoạn mã sau đây là việc thực hiện một bài viết bộ điều khiển sẽ chấp nhận các yêu cầu HTTP và trả về các phản hồi cần thiết.

 
import { Body, Controller, Post } from '@nestjs/common';
import { CommandBus } from '@nestjs/cqrs';
import { CreatePostCommand } from './createPostCommand.command.ts';

@Controller('posts')
export class PostController {
  constructor(private readonly commandBus: CommandBus) {}


  @Post()
  async createPost(@Body() body: { title: string; content: string }) {
    const { title, content } = body;
    const command = new CreatePostCommand(title, content);
    const post = await this.commandBus.execute(command);
    return post;
  }
}


Trong đoạn mã trên, Chỉ HuyXe Buýt thực hiện Tạo BàiLệnh và tạo một bài viết mới.

Mã này cho biết cách triển khai bộ điều khiển sử dụng truy vấn:

 
import { Controller, Get, Param } from '@nestjs/common';
import { QueryBus } from '@nestjs/cqrs';
import { GetPostQuery } from './getPostQuery.query';
@Controller('posts')
export class PostController {
  constructor(private readonly queryBus: QueryBus) {}


  @Get(':id')
  async getPost(@Param('id') id: number) {
    const query = new GetPostQuery(id);
    const post = await this.queryBus.execute(query);
    return post;
  }
}


Các xe buýt truy vấn thực hiện GetPostQuery nhận bài đăng có ID đã cho và trả về.

Sau khi hoàn thành tất cả các bước trên, bây giờ bạn sẽ có một ứng dụng hoạt động tối giản để tạo và tìm nạp các bài đăng trên blog.

Mặc dù mã ở đây sử dụng một mảng để lưu trữ các bài đăng đã tạo trong bộ nhớ, nhưng nhiều khả năng bạn sẽ sử dụng cơ sở dữ liệu trong quá trình sản xuất. Bạn có thể sử dụng cơ sở dữ liệu SQL hoặc cơ sở dữ liệu NoSQL như MongoDB, vì NestJS hỗ trợ cả hai tùy chọn.

Xây dựng API với Mẫu thiết kế CQRS

Việc kết hợp mẫu thiết kế CQRS vào ứng dụng NestJS của bạn có thể hỗ trợ khả năng mở rộng, hiệu suất và khả năng bảo trì. CQRS cho phép các hoạt động được tối ưu hóa và hiệu quả hơn bằng cách tách biệt các thao tác đọc và ghi mà một ứng dụng thực hiện.

Gói @nestjs/cqrs cung cấp một khối xây dựng để triển khai CQRS trong NestJS bằng các lệnh và trình xử lý truy vấn. Nhìn chung, CQRS là một mẫu mạnh mẽ có thể giúp tạo các ứng dụng hiệu quả hơn và có khả năng mở rộng hơn, đồng thời bạn nên cân nhắc các lựa chọn của mình trước khi sử dụng nó.

Previous Post
Next Post

post written by: