跳到主要内容

项目风格

前言

今天是 1024,祝大家节日快乐。🥳 最近想拿 Nest 写个开源项目。但是我发现很多开源项目的目录风格都各有不同。不过想了想项目结构是根据团队的需求、项目复杂度和个人偏好进行自定义,不同开发者和团队可能根据具体需求调整架构风格,比如有些项目会采用 MVC 模式 、DDD 模式、而有些会按模块化划分等。

NestJS 官方推荐的模块化结构:

NestJS 的核心是 模块化,每个功能可以拆分成不同的模块。模块通常是功能的逻辑单元,比如 UserModule 负责用户管理,AuthModule 负责认证逻辑等。这样的结构能提升代码的可维护性和重用性,同时具有高内聚、低耦合

基本结构:

src/
├── app.controller.ts # 应用程序的主控制器
├── app.module.ts # 应用程序的主模块
├── app.service.ts # 应用程序的主服务
├── main.ts # 应用程序的入口文件
└── modules/ # 具体功能模块
├── user/
│ ├── user.controller.ts # 用户模块控制器
│ ├── user.module.ts # 用户模块
│ ├── user.service.ts # 用户模块服务
├── auth/
│ ├── auth.controller.ts # 认证模块控制器
│ ├── auth.module.ts # 认证模块
│ ├── auth.service.ts # 认证模块服务

我们可以用过 以下命令分别生成 controller 和 service 文件

nest g controller modules/user
nest g service modules/user

典型项目结构

如果 spring 系列用得比较多,可以尝试这个结构,也可以按照功能模块拆分,每个模块都有自己的控制器、服务、数据访问逻辑等。每个模块负责一块独立的功能,模块之间可以互相引用和共享资源。

结构说明:

  • controllers:控制器负责处理 HTTP 请求,并调用服务来处理业务逻辑。
  • services:服务层负责业务逻辑和与数据库、API 等外部服务的交互。
  • modules:模块将控制器和服务组合在一起,每个模块可以包含多个控制器和服务。
  • dto/(Data Transfer Object):用于定义请求和响应的数据格式,常用于验证和数据转换。
  • entities/ models/:定义数据库实体或模型。

MVC 结构

这个也是典型的项目结构,通常应用划分为三层:

  • Model:处理数据层逻辑(如数据库交互)。
  • View:处理视图层(例如,NestJS 中这可能是响应数据的生成,或者在 SSR 中生成 HTML)。
  • Controller:处理路由和用户请求,将请求交给相应的服务。

基本结构

src/
├── controllers/
│ ├── user.controller.ts
│ └── auth.controller.ts
├── models/
│ ├── user.model.ts
│ └── auth.model.ts
├── services/
│ ├── user.service.ts
│ └── auth.service.ts
└── main.ts

按模块划分

有时候我们会按照 功能化来组织项目文件。每个模块负责一个功能区域,这样当项目规模变大时,每个功能之间可以独立开发、调试和维护。说到这是不是觉得和 DDD 架构有所关联。但两者并不完全等同。 🤔

基本结构

src/
├── user/
│ ├── user.controller.ts
│ ├── user.service.ts
│ └── user.module.ts
├── auth/
│ ├── auth.controller.ts
│ ├── auth.service.ts
│ └── auth.module.ts

领域驱动设计 (DDD)

DDD 更关注的是如何将业务逻辑通过代码进行建模。DDD 包含诸如 聚合根实体值对象领域事件领域服务 等概念。它强调将业务逻辑分为不同的“领域”,并通过 bounded context(有界上下文)将这些领域分开,每个领域有自己的边界。

在 DDD 的项目结构中,不仅仅是按功能分组,还会进一步细分为 domain(领域逻辑)application(应用逻辑)infrastructure(基础设施层)。每个模块包含相应的领域逻辑和应用逻辑,比如:

src/
├── auth
│ ├── domain
│ │ ├── auth.entity.ts
│ │ └── auth.value-object.ts
│ ├── application
│ │ └── auth.service.ts
│ └── infrastructure
│ └── auth.repository.ts
├── users
│ ├── domain
│ │ ├── user.entity.ts
│ │ └── user.value-object.ts
│ ├── application
│ │ └── users.service.ts
│ └── infrastructure
│ └── users.repository.ts

按此结构的文件夹作用:

  • domain:定义实体和值对象等领域模型,以便业务逻辑能正确映射真实业务。
  • application:服务文件,封装业务逻辑并供控制器等外部模块调用。
  • infrastructure:存储库(repository),与数据库或其他存储交互。

总结

模块化结构 是 NestJS 推荐的最佳实践。这种结构使每个模块能够独立开发、维护和测试,提升代码的可读性与可管理性。但在实际项目中,具体的项目结构可以根据团队风格或开发者的个人习惯进行调整和优化,以便更好地适应项目需求。🥳