You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
abp/docs/zh-Hans/Best-Practices/Module-Architecture.md

89 lines
5.5 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

## 模块化架构最佳实践 & 约定
### 解决方案结构
* **推荐** 在Visual Sudio中为每个模块创建一个单独的解决方案.
* **推荐** 将解决方案命名为*CompanyName.ModuleName*(对于ABP核心模块来说,它的命名方式是*Volo.Abp.ModuleName*).
* **推荐** 一个模块做为分层项目开发,因为它有几个包(项目)是相互关联的.
* 每个包都有自己的模块定义文件,并显式声明所依赖的包/模块的依赖关系.
### 层(layers) & 包(packages)
下面展示了一个分层良好的模块中的包以及它们之间的依赖关系:
![module-layers-and-packages](../images/module-layers-and-packages.jpg)
最终的目地是让应用程序以灵活的方式使用该模块. 示例应用程序:
* **A)** **单体**应用程序;
* 添加对**Web**和**Application**包的引用.
* 根据需要添加对**EF Core** 或 **MongoDB** 包的引用.
* 效果;
* 应用程序可以显示**模块的UI**.
* 它在**同一进程**中托管**应用层**和**领域层** (这就是为什么它引用对数据库集成包).
* 此应用程序还提供了模块的**HTTP API**(因为它通过Web包引用了HttpApi包).
* **B)** 仅为**微服务**提供模块的应用程序;
* 添加对**HttpApi**和**Application**包的引用.
* 根据需要添加对**EF Core** 或 **MongoDB** 包的引用.
* 效果;
* 应用程序**无法显示模块的UI**, 因为它没有对Web包的引用.
* 它在**同一进程**中托管**应用层**和**领域层** (这就是为什么它引用对数据库集成包).
* 此应用程序提供了模块的**HTTP API**(它的主要目标).
* **C)** 显示模块**UI**但是不托管应用层的应用程序(仅将其用作由应用程序A或B托管的远程服务)
* 添加对**Web**和**HttpApi.Client**包的引用.
* 配置HttpApi.Client包的远程端点.
* 效果;
* 应用程序可以显示**模块的UI**.
* 它不会在同一进程中托管模块的应用层和领域层. 而是将其用作**远程服务**.
* 此应用程序还提供了模块的**HTTP API**(因为它通过Web包引用了HttpApi包).
* **D)** **客户端**应用程序 (或微服务) 只使用模块作为远程服务(由应用程序A,B或C托管);
* 添加对**HttpApi.Client**包的引用.
* 配置HttpApi.Client包的远程端点.
* 效果;
* 应用程序可以使用模块的所有功能作为**远程客户端**.
* 应用程序只是一个客户端,**无法提供**模块的**HTTP API**.
* 应用程序只是一个客户端,**无法显示**模块的**UI**.
* **E**) 托管模块的HTTP API但只是将所有请求转发给另一个应用程序的代理应用程序 (由应用程序A, B或C托管);
* 添加对**HttpApi**和**HttpApi.Client**包的引用.
* 配置HttpApi.Client包的远程端点.
* 效果;
* 应用程序可以将模块的所有功能用作**远程客户端**.
* 应用程序也服务于模块的**HTTP API**, 但实际上它的工作方式与代理一样,将所有请求(模块)重定向到另一个远程服务器.
下一节将详细地介绍这些包.
#### 领域层
* **推荐** 将领域层划分为两个项目:
* **Domain.Shared** 包(项目) 命名为*CompanyName.ModuleName.Domain.Shared*,包含常量,枚举和其他类型, 它不能包含实体,存储库,域服务或任何其他业务对象. 可以安全地与模块中的所有层使用. 此包也可以与第三方客户端使用.
* **Domain** 包(项目) 命名为*CompanyName.ModuleName.Domain*, 包含实体, 仓储接口,领域服务接口及其实现和其他领域对象.
* Domain 包依赖于 **Domain.Shared** 包.
#### 应用服务层
* **推荐** 将应用服务层划分为两个项目:
* **Application.Contracts** 包(项目) 命名为*CompanyName.ModuleName.Application.Contracts,包含应用服务接口和相关的数据传输对象(DTO).
* Application contract 包依赖于 **Domain.Shared** 包.
* **Application** 包(项目)命名为*CompanyName.ModuleName.Application*,包含应用服务实现.
* Application 包依赖于 **Domain** 包和 **Application.Contracts** 包.
#### 基础设施层
* **推荐** 为每个orm/数据库集成创建一个独立的集成包, 比如Entity Framework Core 和 MongoDB.
* **推荐** 例如, 创建一个抽象Entity Framework Core集成的*CompanyName.ModuleName.EntityFrameworkCore* 包. ORM 集成包依赖于 **Domain** 包.
* **不推荐** 依赖于orm/数据库集成包中的其他层.
* **推荐** 为每个主要的库创建一个独立的集成包, 在不影响其他包的情况下可以被另一个库替换.
#### HTTP 层
* **推荐** 创建命名为*CompanyName.ModuleName.HttpApi*的**HTTP API**包, 为模块开发REST风格的HTTP API.
* HTTP API 包只依赖于 **Application.Contracts** 包. 不要依赖 Application 包.
* **推荐** 为每个应用服务创建一个Controller (通常通过实现其接口). 这些控制器使用应用服务接口来委托操作. 它根据需要配置路由, HTTP方法和其他与Web相关的东西.
* **推荐** 创建一个为HTTP API包提供客户端服务的**HTTP API Client**包, 它的命名为*Companyname.ModuleName.HttpApi.Client*. 这些客户端服务将应用服务接口实现远程端点的客户端.
* HTTP API Client 包仅依赖于 **Application.Contracts** 包.
* **推荐** 使用ABP框架提供的动态代理HTTP C客户端的功能.
#### Web 层
* **推荐** 创建命名为*CompanyName.ModuleName.Web*的 **Web**包. 包含页面,视图,脚本,样式,图像和其他UI组件.
* Web 包仅依赖于 **HttpApi** 包.