DDD项目实践的优劣势分析

407 阅读9分钟

1.DDD架构的核心概念

DDD即领域驱动设计,英文Domain-Driven Design的缩写。

领域驱动设计(DDD)提出是从系统的分析到软件建模的一套方法论。将业务概念和业务规则转换成软件系统中的概念和规则,从而降低或隐藏业务复杂性,使系统具有更好的扩展性,以应对复杂多变的现实业务问题。总结它是一套完整而系统的设计方法、是一种设计思维、一种方法论,并不是"系统架构"。

1.1 以下是领域驱动设计的核心概念和要点:

领域模型(Domain Model):

  • 领域模型是描述业务领域的概念和规则的对象模型。
  • 它是在软件中直接映射业务领域概念的设计模式,通过对象来表示业务实体和业务规则。

领域驱动设计的要点:

  • 领域专家(Domain Expert): 领域驱动设计鼓励开发团队与领域专家密切合作,以便更好地理解业务需求。
  • Ubiquitous Language(普遍语言): 领域驱动设计强调开发团队和领域专家使用共同的、精确的业务术语,以避免在沟通中的歧义。
  • 界限上下文(Bounded Context): 复杂的领域模型可能会分成多个边界上下文,每个上下文内部有自己的领域模型和规则,但与其他上下文进行交互时需要明确定义的接口。

DDD的基本构建块:

  • 实体(Entities): 有唯一标识的对象,其状态和行为方法在整个生命周期中都是持续变化的。

  • 值对象(Value Objects): 没有唯一标识的对象,它们是根据其属性来比较相等性的。

  • 聚合根(Aggregate Roots): 是实体的一个特殊种类,它定义了整个聚合内部的边界,外部对象只能通过聚合根来访问聚合内的其他对象。聚合根负责维护聚合内部的业务规则和约束,并负责保护聚合内的不变性。(聚合根可以写业务逻辑)

  • 仓储(Repository): 负责从持久化存储中查找和存储领域对象。

  • 领域服务(Domain Services): 处理不属于单一实体或值对象的操作,通常与多个实体或值对象协作。

  • 领域能力Ability): 可以看作是领域模型的一部分,表示领域对象所具有的能力或者行为。

2.DDD架构落地情况

在系统设计时,我们会将需求文档(PRD)当中的用户需求转换成具体的用例。有了用例之后,我们可以从中识别出领域模型(系统边界),然后再将领域模型转换成具体的程序设计和数据库设计。

2.1系统模块依赖关系

2.2四层架构设计

在当前的架构中,Facade提供服务消费方远程访问能力,适配各端接口。Facade不提供逻辑处理,仅做转发。

应用层负责对Facede转入对请求进行验参、编排(委派)DomainService层实现业务逻辑。对于查询类请求,可以不经过领域层的,直接调用ops实现数据查询

领域层负责具体的业务逻辑实现;

基础设施层(infra)实现对外部基础设施、跨领域微服务的访问。

在实现领域层时,为了摆脱平台依赖,像依赖注入等场景,可以考虑实现相关基础二方库来适配要使用的Bean管理方案。

2.3各层参数命名规则

在参数命名方面,通过细化当前的VO、Entity的命名,使得各个类指责单一化、更简单明了。

3.DDD的优劣势

优势:

  1. 更好的业务理解: DDD 通过强调领域建模,帮助开发团队更好地理解业务领域,促使开发人员与业务专家更加紧密地合作。
  2. 更好的架构设计: DDD 通过分层架构、聚合根等概念,帮助设计出更加清晰和模块化的架构,减少了系统的复杂性。
  3. 更好的可维护性: DDD 的强调领域模型和业务逻辑的设计,使得系统更容易维护和扩展,因为业务逻辑被封装在领域对象中,避免臃肿的service,带来难以接受的维护成本和二次迭代成本

  1. 更好的测试性: DDD 的聚合根和领域服务等概念使得单元测试和集成测试更容易进行,因为可以单独测试领域对象的行为。
  2. 更好的沟通: DDD 提供了一套通用的业务领域语言,帮助开发团队和业务团队之间更好地进行沟通,减少了沟通的误解。

劣势:

  1. 学习曲线: DDD 的概念和模式较多,需要团队成员具备一定的培训和学习成本,尤其是对于新手来说。
  2. 过度设计的风险: 如果不恰当地应用 DDD,可能会导致过度设计,使得系统变得过于复杂,增加了开发和维护的成本。
  3. 不适用于所有项目: DDD 最适合复杂的业务领域,对于简单的项目,可能会引入不必要的复杂性,使得开发过程变得冗余。
  4. 团队合作难度: DDD 要求开发团队与领域专家密切合作,如果业务专家不够配合或者团队沟通不畅,可能导致开发困难。
  5. 数据库映射问题: 在使用 DDD 时,与关系数据库的映射可能会变得复杂,特别是在涉及到复杂查询和性能优化时。

4.是否使用DDD

使用DDD:

  1. 复杂业务领域: DDD 特别适用于复杂的业务领域,当业务规则和流程相对复杂时,DDD能够帮助团队更好地理解和处理这些复杂性。
  2. 团队经验和培训: 如果团队成员对DDD有经验,并且接受过培训,那么在适当的项目中使用DDD可能会更容易。
  3. 业务专家参与度: 如果业务专家能够积极参与领域建模和规则制定,DDD将会更为有效。这样可以确保开发团队对业务领域的理解是准确的。
  4. 需要强调领域模型: 如果项目的核心是领域模型,例如金融领域的交易处理系统、医疗健康领域的病例管理系统等,DDD可以帮助建立清晰的领域模型。

不使用DDD:

  1. 简单业务领域: 对于简单的业务,DDD可能会引入不必要的复杂性,不值得为了简单的需求而过度使用DDD。
  2. 团队经验不足: 如果团队成员缺乏DDD经验,可能会在应用DDD时犯一些常见的错误,影响项目进度和质量。
  3. 项目时间紧迫: 如果项目有非常紧急的上线时间,DDD可能需要更多的时间用于领域建模和设计,这时可能需要权衡时间和质量。
  4. 业务专家不可用: 如果业务专家无法参与领域建模和验证,那么DDD可能无法发挥其优势。

5.DDD 在项目的各个阶段如何开展

项目前期(需求分析和设计阶段):

  • 领域专家合作: 在这个阶段,开发团队应该与业务专家密切合作,共同探讨和理解业务领域,识别领域模型中的关键概念和业务规则。
  • 领域建模: 开发团队可以开始进行领域建模,使用聚合、实体、值对象等DDD概念来表达领域模型。这个过程可能包括绘制领域模型图、编写领域事件Storming等活动。

开发阶段:

  • 实现领域模型: 在开发阶段,开发团队根据领域建模的结果实现领域模型。领域对象、聚合根和领域服务等概念可以被直接映射到代码中。
  • 领域服务的使用: 使用领域服务来处理那些不属于任何特定实体或值对象的领域逻辑。领域服务可以被用来协调不同的领域对象之间的交互。

测试阶段:

  • 单元测试和集成测试: 使用单元测试来测试领域对象的行为。测试领域服务的时候,可以使用模拟对象(Mock)来模拟领域对象的行为。

维护和演进阶段:

  • 持续改进: 随着项目的推进,不断地与领域专家合作,根据业务变化和需求变化对领域模型进行调整和演进。领域事件Storming等方法可以在这个阶段再次使用。
  • 解决领域模型的复杂性: 随着项目的发展,可能会发现领域模型变得越来越复杂。在这种情况下,可以使用战术设计模式(如聚合重构、领域服务分解等)来简化领域模型。
  • 技术演进: 随着技术的发展,可能会出现新的工具和框架,可以帮助团队更好地实施DDD。团队应该持续关注领域驱动设计社区和行业趋势,不断学习和改进。

在整个项目周期中,持续的与业务专家合作、保持开发团队的灵活性和适应性,以及不断的反馈和改进,是DDD成功应用的关键。不同项目可能在不同的阶段使用DDD的方法和概念,具体的应用方式会因项目需求、团队经验和技术栈等因素而异。

6.结语:

DDD并非适用于所有项目。在决定使用DDD之前,团队应该充分了解项目的特点、需求和团队的能力,权衡DDD的优势和劣势,选择最适合项目的开发方法和架构。在应用DDD时,团队需要时刻保持与业务专家的紧密合作,持续改进和学习,以确保DDD的有效应用。