• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

代码模型组织方式

开发技术 开发技术 6天前 8次浏览

结构划分迷雾

Asp.Net Boilerplate中默认项目结构是如下所示(项目代号Gravel),每层都是一个单独的类库或是应用程序。

- Gravel.sln
  - Gravel.Web
  - Gravel.Application
  - Gravel.Core
  - Gravel.EFCore

在这种固有分层方式下,ABP没有指明要采用什么形式去划分限界上下文,是采用文件夹隔离形式还是采用类库隔离形式,并没有严格说明。
注意:具体是在应用层领域层基础设施层中需要隔离限界上下文。

文件夹隔离

如采用文件夹隔离形式,则解决方案结构如下,在每一层中建立文件夹形式以此来划分限界上下文的边界。

- Gravel.sln
  - Gravel.Web
  - Gravel.Application
    - OrderCenter
    - ProductCenter
    - CustomerCenter
  - Gravel.Core
    - OrderCenter
    - ProductCenter
    - CustomerCenter
  - Gravel.EFCore
    - OrderCenter
    - ProductCenter
    - CustomerCenter

类库隔离

如采用类库隔离形式(即依照限界上下文拆分类库),则解决方案结构如下,Gravel作为承载体,其余三个作为上下文独立出来,按照上下文的边界高于分层的边界(这种划分也更加合理)。

- Gravel.sln
  - Gravel
    - Gravel.Web
    - Gravel.Application
    - Gravel.Core
    - Gravel.EFCore
  - OrderCenter
    - Application
    - Core
    - EFCore
  - ProductCenter
    - Application
    - Core
    - EFCore
  - CustomerCenter
    - Application
    - Core
    - EFCore

对于Asp.Net Boilerplate,见到的几个Demo及博客园内一些作者,都是采用的第一种风格形式,即分层边界高于上下文的边界。
而对于第二种形式,在ABP VNext的MicroserviceDemo中采用的是这种形式。并且在ABP VNext中,这种形式的变体是可以从单体切换到微服务的。

注意:这里的解决方案结构并不是固定如此,因ABP中模块化设计,有些是可以删除的。

回归本质

这样拆分的目的是什么?为了划分限界上下文,为了达到清晰边界,从而控制住上下文内部。

架构没有清晰的层次,职责缺乏合理的分配,代码变得不可阅读和维护,最终形成一种无序设计

从分层形式角度出发,分层形式有物理分层和逻辑分层,DDD中提到的分层是属于逻辑分层,逻辑上划分了应用层领域层基础设施层,并没有规定物理分层的形式,即没有规定是整个项目划分成一个类库还是多个类库,也没有规定整个项目是划分成多个上下文,每个上下文是一个类库还是多个类库。

代码模型组织方式

如果不考虑内部类库的数量,本身其实关注的就是如何组织多个限界上下文,是在一个项目中组织还是一个项目中拆分成多个限界上下文组织。

代码模型组织策略

http://www.codingthearchitecture.com/2015/03/08/package_by_component_and_architecturally_aligned_testing.html

按层次划分

采用文件夹形式划分本质上是一种按层次划分,同一层中,依照限界上下文,划分不同的边界,这是一种近乎常规化的划分方式。

代码模型组织方式

按特性划分

依照垂直划分方式,将限界上下文垂直物理拆分,每个限界上下文内都是一个独立的团体。该团体内部仍然可以是分层架构的。

代码模型组织方式

按组件划分

在特性划分基础上再升华,除去UI部分,组成组件,依照限界上下文形式组合,这也更贴近考虑DDD时不要纳入UI层。如此划分后,其他的Controller可以通过组件形式访问某个限界上下文中的数据。

代码模型组织方式

结构划分迷雾消散

给定的AspNet Boilerplate或是AspNet Zero中都是采用的按层次划分的形式,但并没有说按照组件划分不可行,毕竟在一个gitee仓库中看到过按照组件划分的形式,而且是可用的。而对于ABP VNext更推荐按组件划分的形式,主要参考是MicroserviceDemo中的格式。

所以最终迷雾也就解除了,是ABP没有规定必须要按照哪种格式去组织代码,因为对于AspNet Boilerplate来讲,模块化的设计,本身可以允许按照层次划分与按照组件划分,至于选用哪种方式,更多的是,使用者自身去选择,也从另一方面看出ApNet Boilerplate本身作为基础框架,提供了使用者更多的选择性。

AspNet Boilperlate按层次划分形式组织代码

代码模型组织方式

AspNet Boilerplate按组件划分形式组织代码

代码模型组织方式

总结

对于实际使用中来讲,如果按照层次划分,使用ABP时总有点说不出来的感觉,不知道如何去管理代码,写的爽时,直接把其他上下文中的应用服务,领域服务或是仓储直接搬到当前的限界上下文中用,这也就导致后期代码看起来很凌乱,耦合也严重。

想要通过按层次划分引入防腐层来避免直接依赖,却要遵循约束,必须强行遵守纪律,通过防腐层去访问其他限界上下文。

从这一角度考虑,也逐渐理解了为什么要限界上下文的边界要高于分层的边界,按照组件划分的形式,直接断绝了限界上下文间的直接调用,而是采用防腐层或是其他形式去做中间隔离,类似代理形式解决直接耦合问题,同时也方便往微服务方向拆分时不会拖泥带水。

2020-11-22,望技术有成后能回来看见自己的脚步


喜欢 (0)