Tech&Wk_Architecture_Module_Design_DDD

领域驱动设计 Module 设计


DDD中,模型中的模块表示了一个命名的容器,用于存放领域中内聚在一起的类.

模块应该包含一组具有高内聚性的概念集合,在不同的模块之间实现松耦合。模块名应该反映出它们在领域中的概念。

设计模块的简单原则:

  • 模块应该和领域概念保持一致:通常,对于一个或一组聚合来说,相应地创建一个模块
  • 根据通用语言来命名模块:DDD的目标
  • 不要机械式地根据通用组件类型和模式来命名模块:如果我们将所有的 聚合 放在一起, 将所有的 领域服务 放在一个模块,将所有的 工厂 放在另一个模块。这是有悖于 DDD 设计原则,会限制我们创建 富含行为的 领域模型。此时,我们的关注点不是在领域上, 而是在 组件 和 模式 上。
  • 设计松耦合的模块: 模块间的松耦合性与 类级别的松耦合有相似的好处,有利于我们维护和重构一些模块层面上的概念,如 OSGi 和 Jigsaw.
  • 当同层模块(Peer Module)间出现耦合时,我们应该杜绝循环依赖(同层模块 即位于相同层次的模块,或者是在设计时有相似权重的模块)。
  • 父模块和子模块之间放松原则:避免循环依赖。
  • 不要将模块设计成一个静态的概念,而是要与模型中的对象一起进行建模:如果模型概念将随时间而改变,往往意味着对应的模块也应该随之改变。当你发现概念名和模块名不再匹配时,你应该对模块进行重构。

更高层次的模块化,将那些松耦合的,但是具有逻辑内聚性的软件分成具有版本号的部署单元。

JAR 这种文件格式,希望将版本号也加入,必如OSGi bundle 或者 Jigsaw 模块。众多的高层模块,它们的版本号和依赖关系都可以通过捆绑包/模块予以管理。和DDD中的模块稍有不同,但它们之间是可以互补的。

根据DDD中的模块划分将 领域模型中 存在松耦合关系的各个部分 封装到不同的捆绑包中有好处的。


领域模型的命名规范:

  1. 模块名中加入限界上下文的名称。
  2. 向模块名添加另一层,该层用于定位领域中某个特定的模块。这种命名规范与传统的分层架构/和六边形架构式兼容的。分层系统常用到六边形架构的依赖注入的风格,六边形架构,应用程序包含一个“内在"的部分,其中包含了领域模型
    1. com.saasvoation.identityaccess.domain
    2. com.saasvoation.collaboration.domain
    3. com.saasvoation.agilepm.domain
  3. 以上"domain" 部分可能并不直接包含实际的 接口/类,而是作为更低层模块的容器。所示,在该层中定义模型中的类,接口类和抽象类也在其中。
    1. com.saasvoation.identityaccess.domain.model
    2. com.saasvoation.collaboration.domain.model  
    3. 该模块中放入一些通用的接口,必如那些用于发布事件的类,还有实体和值对象的抽象基类。
    4. DomainEvent, DomainEventPublisher, DomainEventSubscriber, DomainRegistry, Entity, IdentifiedDomainObject,IdentifiedValueObject,ConcurrencySafeEntity
    5. 如果喜欢将领域服务放在 domain.model之外,可创建一个与model同层的模块:
    6. com.saasvoation.identityaccess.domain.service   将领域服务放在该模块中并不是必须的,看成是位于模型之上的一个迷你层,或是环绕模型的一层。可能会导致贫血领域模型。
    7. 我们并不是开发一个领域, 领域 表示的是我们所工作的一个范围。 事实上我们开发的是一个领域中的模型。因此,domain.model 是必须的。

 


存在双向依赖,但是属于父子模块,应该优先考虑模块的组织结构,而不是松耦性,没有必须要再次撕开聚合边界。

其他层中的模块:

 

 

一个典型的分层架构中,分为:用户界面层,应用层,领域层和基础设施层。

1. 用户界面层和其中的 REST资源。 REST 资源通过XML, JSON, 和HTML 等数据展现形式向GUI 和系统客户端提供服务。

REST 是不会为GUI 创建展现布局的,只是创建一些数据标记格式(XML, HTML),创建一些序列化的数据格式 XML,JSON 和协议缓存.

在客户端,用于图形布局的数据可能通过另外的渠道获得,至少需要两个模块:

2.应用层,一种服务对应一个个模块,只有在需要的时候才为应用层划分子模块。

 

应通过 通用语言的需求来划分模型边界,限界上下文不是用来代替模块的。

使用模块的目的在于组织那些内聚在一起的领域对象,对于那些内聚性不强或者没有内聚性的领域对象来说,应该将它们划分在不同的模块中。

 

posted @ 2021-01-03 21:01  君子之行  阅读(15)  评论(0)    收藏  举报