diff --git "a/zh/ater.web/\346\225\231\347\250\213/.order" "b/zh/ater.web/\346\225\231\347\250\213/.order" index ab37c55..272df1d 100644 --- "a/zh/ater.web/\346\225\231\347\250\213/.order" +++ "b/zh/ater.web/\346\225\231\347\250\213/.order" @@ -1,3 +1,3 @@ 项目结构说明 分层项目说明 -实体定义 \ No newline at end of file +组织代码 \ No newline at end of file diff --git "a/zh/ater.web/\346\225\231\347\250\213/\347\273\204\347\273\207\344\273\243\347\240\201.md" "b/zh/ater.web/\346\225\231\347\250\213/\347\273\204\347\273\207\344\273\243\347\240\201.md" new file mode 100644 index 0000000..0c5f0c2 --- /dev/null +++ "b/zh/ater.web/\346\225\231\347\250\213/\347\273\204\347\273\207\344\273\243\347\240\201.md" @@ -0,0 +1,115 @@ +# 组织代码 + +模板已经提供了层级结构来帮助我们组织代码,对于单体应用来说,根据项目结构说明去组织相应的代码即可。 + +但是当我们有很多开发人员,并且有很多服务的时候,也许我们会感到困惑。这里给大家分享一下相应的解决方案,具体使用哪种方案由用户自己决定。 + +## 单体应用 + +模板提供的结构以及`Modules`可以非常方便的帮助开发者组织代码,并具备一定扩展性和协作开发的抗干扰(根据模块分工)。 +最终都通过`Http.API`对外提供接口服务,这非常容易理解,也很容易实施。 + +## 多服务 + +首先要明确一下,这里的多服务,指的是在发布生产环境时,会有多个独立且不同的应用服务运行。 + +对于多个服务,或者说拆分成微服务,我们可以有不同的实施方案,这取决于您的团队! + +> [!IMPORTANT] +> 对于方案的选择应该考虑开发者的开发体验,这主要体现在开发效率,易实施,小风险等方面,切勿为了实现别人口中所谓的“设计模式”而牺牲自己的精力和时间。 + +### 共享业务代码的多服务 + +这种方案非常容易实施,也非常容易理解,它的主要特点如下: + +- 我需要在部署时部署多个服务,以让每个服务可以具备高可用。 +- 我的服务共享业务逻辑代码,不同的服务只是开放不同的接口(Http/Grpc)。 + +这种方案让事情变得简单,假设我们最终要部署三个服务 + +- 用户接口服务:`Http.API` +- 管理员接口服务:`AdminService` +- 用户订单服务:`OrderService` + +这意味着我们将有三个`WebAPI`项目,我们将在`Microservice`中创建`AdminService`和`OrderService`项目。 + +我们将有两种方式进行开发: + +#### 1 共享业务代码 + +- 所有实体在`Entity`中定义,所有业务逻辑在`Application`中实现。 +- 所有服务都引用`Application`项目,但只定义需要对外开放的接口。 + +这意味着,项目共享了所有的业务逻辑,业务逻辑并没有根据服务去拆分和解耦。 + +#### 2 使用模块来拆分业务代码 + +- 所有实体在`Entity`中定义 +- 分别创建`UserMod`,`AdminMod`,`OrderMod`三个模块,分别实现各个模块的业务逻辑(即`Manager`)。 +- `Http.API`项目引用 `UserMod`,`AdminService`引用`AdminMod`,`OrderService`引用`OrderMod`。 + +这样可以在业务逻辑上实现拆分解耦,服务只会引用自己的业务实现。 + +由于每个模块,仍然需要引用`Application`项目,这意味着,如果有共用的业务,仍然可以进行复用,当然这也意味着,每个服务之间仍然不是完全独立和解耦的。 + +我们可以看到,通过模块的切分,我们可以比较灵活的进行业务逻辑的拆分,部署的拆分,同时还可以在一定程度上复用一些代码。这对于多数情况已经足够了。 + +如果您非要实施更加独立和解耦的服务,可继续阅读! + +### 每个服务独立项目 + +在具体说明之前,我们需要考虑几个现实问题: + +- 是否是多个团队实施微服务 +- 是否使用多种语言实现 +- 是否各个服务采用统一的通讯协议,如统一使用Grpc/Http,或通过消息队列进行服务间通讯。 + +这里会涉及到团队之间,服务之间的协作问题,可能会非常复杂。为了简化问题,我们给一些限定,以方便更好的讨论。 + +> 如果我们团队使用统一的语言和框架去实施微服务 + +我们将在这个提前下去讨论。然后我们仍然会面对一些问题: + +- 是否一个解决方案对应一个服务 +- 是否一个解决方案包含所有的服务 +- 是否每个服务都有自己独立的仓库 + +关于这些问题,我们仍然需要假设一些情境,以便更好的进行讨论。 + +> - 使用一个仓库(主仓库)管理所有服务代码,如果服务有自已的仓库,则作为主仓库的子仓库进行管理。 +> - 使用一个解决方案将所有项目进行管理。 + +对于.NET开发者,使用解决方案是一件非常自然的事情,这意味着你可以在一个IDE实例中处理多个项目。 + +接下来,假设我们需要按照`DDD`的微服务实践,让服务之间保持独立,我们应该如何去实施。 + +我们先明确几点: + +- 每个服务只包含自己的实体(领域)模型 +- 每个服务只包含自己的业务逻辑实现 +- 每个服务只提供领域业务的接口 +- 每个服务有自己单独的配置和依赖项 +- 每个服务有自己的构建和部署需求 + +简而言之,服务之间几乎是完全独立的。互相是不能复用业务逻辑代码的,对于功能性代码可以通过类库的方式进行复用。 + +#### 1. 创建多个解决方案 + +其中一种方案就是为每个服务都新建一个模板项目,然后进行完全独立的开发。 + +那么应该如何联调么? 我们可以单独创建一个解决方案,向这个解决方案添加服务项目,然后使用`.NET Aspire`进行联调。 + +#### 2. 只使用一个解决方案 + +我们的模板自带了一个独立服务的示例。同时使用`Ater.Dry`也可以在现有解决方案中添加新的独立服务。 + +这些独立的服务,拥有自己的实体定义、数据库上下文、业务实现层以及接口层。这些分层不再以`独立项目`的形式存在,而是以`文件夹`的形式存在。 +这很容易理解,因为所有的代码只在当前服务内起作用,并不需要封装成项目而被其他项目去引用。 + +`Ater.Dry`会自动发现解决方案下的微服务项目,并且代码生成时也可以识别微服务中的实体,并在对应的服务中进行代码生成。 + +## 建议 + +根据实际情况的不同,如果你的团队或业务需求不是要求您必须将各个服务进行拆分,并且相互独立,我们建议您使用模块的方式进行业务逻辑的拆分。 + +如果您必须去实现独立的服务,我们建议您使用一个解决方案包含所有服务方式来管理整个项目。 diff --git "a/zh/ater.web/\346\225\231\347\250\213/\345\256\236\344\275\223\345\256\232\344\271\211.md" "b/zh/ater.web/\347\272\246\345\256\232\345\222\214\350\247\204\350\214\203/\345\256\236\344\275\223\345\256\232\344\271\211.md" similarity index 100% rename from "zh/ater.web/\346\225\231\347\250\213/\345\256\236\344\275\223\345\256\232\344\271\211.md" rename to "zh/ater.web/\347\272\246\345\256\232\345\222\214\350\247\204\350\214\203/\345\256\236\344\275\223\345\256\232\344\271\211.md"