> 文章列表 > DDD领域驱动设计:支付系统中的应用一

DDD领域驱动设计:支付系统中的应用一

DDD领域驱动设计:支付系统中的应用一

文章目录

  • 前言
  • 一、DDD意义
    • 1 为什么需要DDD
    • 2 DDD的价值
  • 二、DDD设计流程
    • 1 战略设计
    • 2 战术设计
  • 三、DDD代码落地
  • 四、参考文献
  • 总结

前言

DDD作为一种优秀的设计思想,为复杂业务治理带来了曙光。然而又因为DDD本身难以掌握,很容易造成DDD从理论到工程落地之间出现巨大的鸿沟。就像电影里面的桥段,只谈DDD理论姿势很优美,一旦工程落地就跪了。所以DDD的项目,工程落地很重要,否则很容易变成 “懂得了很多道理,却依然过不好这一生”

DDD的学习过程好像是”大海捞针“的过程。即使能够捞到点东西,使用起来,还是会有种“东施效颦”的感觉,并不是很自然。为什么学习DDD那么困难呢?

叔孙武叔语大夫于朝曰:“子贡贤于仲尼。” 子服景伯以告子贡,子贡曰:“譬之宫墙,赐之墙也及肩,窥见室家之好;夫子之墙数仞,不得其门而入,不见宗庙之美、百官之富。得其门者或寡矣,夫子之云不亦宜乎!”

正如要感受到孔子达到的境界,自己的学问也需要有一定的积累。我们要感受到DDD的力量,自己本身就要成长到一定程度,如:经历了一些成功或者失败的设计,有自己的经验或者教训,才能形成共鸣和认同。

本篇将讲解DDD领域驱动设计代码的落地环节,并以支付系统中组合支付为例进行代码讲解,适合已经了解领域驱动基本概念,但是又苦于没有实际企业级别项目的同学。
DDD领域驱动设计:支付系统中的应用一
希望最终结果不是跪了的…


一、DDD意义

无论做业务,还是做平台、中台,大家常常会被交错复杂的业务逻辑、晦涩耦合的业务代码搞得心力交瘁。我想,大家对DDD的追求,也是对轻松支撑业务发展的诉求,在探寻有没有合适的理论可以改善现状。在软件开发中如何降低系统复杂度是一个永恒的挑战。

1 为什么需要DDD

  • 复杂系统设计: 系统多,业务逻辑复杂,概念不清晰,有什么合适的方法帮助我们理清楚边界,逻辑和概念。
  • 多团队协同: 边界不清晰,系统依赖复杂,语言不统一导致沟通和理解困难。有没有一种方式把业务和技术概念统一,大家用一种语言沟通。
  • 设计与实现一致性: PRD,详细设计和代码实现天差万别。有什么方法可以把业务需求快速转换为设计,同时还要保持设计与代码的一致性?
  • 架构统一,可复用资产和扩展性: 当前取决于开发的同学具备很好的抽象能力和高编程的技能。有什么好的方法指导我们做抽象和实现。

2 DDD的价值

  • 解决微服务拆分困境:DDD 对业务分析时,首先会使用「聚合」把关联性强的业务概念划分在一个边界下,并限定「聚合」和「聚合」之间只能通过「聚合根」来访问,这是第一层边界。其次,在「聚合」基础之上根据「业务相关性」、「业务变化频率」、「组织结构」等约束条件来定义「限界上下文」,这是第二层边界。有了这两层边界作为约束和限制,微服务的边界也就清晰了,拆分微服务也就变得简单了。
  • 应对系统复杂性:DDD 的核心思想就是要避免业务逻辑的复杂度与技术实现的复杂度混淆在一起,确定业务逻辑与技术实现的边界,从而隔离各自的复杂度,业务逻辑并不关心技术是如何实现的。无论采用何种技术,只要业务需求不变,业务规则就不会变化。

二、DDD设计流程

DDD领域驱动设计:支付系统中的应用一
在DDD中,软件的核心是其为客户解决领域相关的问题的能力。这里的领域,就是指软件系统要解决的实际问题相关的东西的集合。为了分解问题域的复杂度,问题域又会被拆解为多个子域,每个子域都要明确待解决的业务问题和业务流程,以及通过解决业务问题为企业带来了什么样的业务价值。

在清晰的定义子域后,我们就可以建立通用语言来提取该子域的领域知识,并基于通用语言为解决问题建立领域模型。领域模型是关于某个特定业务领域的软件模型。通常,领域模型通过对象模型来实现,这些对象同时包含了数据和行为,并且表达了准确的业务含义。

DDD领域驱动设计通常会包含战略设计和战术设计两部分:

1 战略设计

战略设计也叫战略建模,通过DDD的理论,对业务需求进行拆解分析,划分子域,梳理限界上下文,通过领域语言从战略层面进行领域划分以及构建领域模型。并且在在构建领域模型的过程中梳理出业务对应的聚合、实体、以及值对象。
DDD领域驱动设计:支付系统中的应用一

2 战术设计

战术设计也称为战术建模,以领域模型基础,通过限界上下文作为服务划分的边界进行微服务拆分,在每个微服务中进行领域分层,实现领域服务,从而实现领域模型对于代码映射目的,最终实现DDD的落地实施。
DDD领域驱动设计:支付系统中的应用一

三、DDD代码落地

Talk is cheap,show me the code。

案例背景
某消费金融支付系统中主动还款中网关签约中支付+优惠券的组合支付为案例进行代码实现落地。

1.业务架构
DDD领域驱动设计:支付系统中的应用一
2.应用架构
DDD领域驱动设计:支付系统中的应用一
通过DDD思想重构后的应用架构图:(后期有机会讲解下演进过程)
DDD领域驱动设计:支付系统中的应用一

3.服务分层
服务集群中各应用系统结构参考DDD四层架构进行分层,作者提出的四层是逻辑分层,当然在实际项目中可以分成四层,也可以拆分,如笔者原来是这么分层的,如下图,API层对应用户接口层,Service层对应应用层,Domain对应领域层,基础设施层对应了Common(通用工具类、常量等)、Dal(数据持久层)、Integration(融合层用于服务间调用和缓存)、Main(启动类和配置类)。
DDD领域驱动设计:支付系统中的应用一

在《实现领域驱动设计》一书中,DDD 分层架构有一个重要的原则:每层只能与位于其下方的层发生耦合。而架构根据耦合的紧密程度又可以分为两种:严格分层架构松散分层架构

在严格分层架构中,领域服务只能被应用服务调用,而应用服务只能被用户接口层调用,服务是逐层对外封装或组合的,依赖关系清晰。

而在松散分层架构中,领域服务可以同时被应用层或用户接口层调用,服务的依赖关系比较复杂且难管理,甚至容易使核心业务逻辑外泄。

在实际开发中如果是初次上手的话还是建议采用松散分层架构,毕竟是要给自己留个后路么,耍不好就退化成三层么。本人项目中也是采用的松散架构,还是建议组内多做培训免得新人没搞清楚整个架构设计就上手搞业务代码,把整个项目给污染了。
DDD领域驱动设计:支付系统中的应用一

下面大概介绍下各个层的工作内容:

  • 接口层{interfaces}

    • 接口服务位于用户接口层,用于处理用户发送的Restful请求和解析用户输入的配置文件等,并将信息传递给应用层。
  • 应用层{application}

    • 应用服务位于应用层。用来表述应用和用户行为,负责服务的组合、编排和转发,负责处理业务用例的执行顺序以及结果的拼装。
    • 应用服务可对微服务内的领域服务以及微服务外的应用服务进行组合和编排,或者对基础层如文件、缓存等数据直接操作形成应用服务,对外提供粗粒度的服务。
    • 领域事件服务包括两类:领域事件的发布和订阅。通过事件总线和消息队列实现异步数据传输,实现微服务之间的解耦。
  • 领域层{domain}

    • 领域服务位于领域层,为完成领域中跨实体或值对象的操作转换而封装的服务,领域服务以与实体和值对象相同的方式参与实施过程。
    • 领域服务对同一个实体的一个或多个方法进行组合和封装,或对多个不同实体的操作进行组合或编排,对外暴露成领域服务。领域服务封装了核心的业务逻辑。实体自身的行为在实体类内部实现,向上封装成领域服务暴露。
    • 为隐藏领域层的业务逻辑实现,所有领域方法和服务等均须通过领域服务对外暴露。
  • 基础层{infrastructrue}

    • 基础服务位于基础层。为各层提供资源服务(如数据库、缓存等),实现各层的解耦,降低外部资源变化对业务逻辑的影响。
    • 基础服务主要为仓储服务,领域服务和应用服务调用仓储服务接口,利用仓储实现持久化数据对象或直接访问基础资源。

4.应用分析
为了增加复用、缩短业务的落地时间,就需要很多通用的能力、产品。在我们的交付过程中,主要有两个层次:
DDD领域驱动设计:支付系统中的应用一

基础能力:相对原子的能力是基础(域)能力,这个可以较好地支持业务定制。由于比较基础,表达的产品能力范围也是很大的。
payGw系统作为基础能力系统:

1.统一支付出口,提供丰富的支付工具原子能力(代扣、批扣、代付、批付、快捷支付、网关支付、鉴权、银行卡签约等)
2.与业务场景解耦,业务场景的多变特点不会体现在Paygw系统中

平台产品:基础能力的通用性,意味着缺少对场景的理解,缺少了进一步提升生产效率的“基因”。所以在交付的时候,会基于一些高频场景进行抽象,形成平台的产品能力,争取做到“拆箱即用”。业务基于“平台产品”这层进行定制的时候,理解成本会大大减少。
payCore系统作为平台产品系统:

  1. 为公司各业务线提供丰富的且涵盖公司特有业务(如:快捷转代扣,轮询扣款,轮询鉴权)的支付工具
  2. 封装paygw的各原子交易接口,降低业务线对接支付的难度

4.开发框架

5.代码示例
DDD领域驱动设计:支付系统中的应用一

四、参考文献

华为云《跨越DDD从理论到工程落地的鸿沟》
华为云《初识领域驱动设计DDD落地》


总结

未完待续,大概是要跪了… …明天看能不能挽救下