关于ddd:快速理解DDD领域驱动设计架构思想基础篇-京东物流技术团队

33次阅读

共计 4447 个字符,预计需要花费 12 分钟才能阅读完成。

1 前言

本文与大家一起学习并介绍畛域驱动设计(Domain Drive Design) 简称 DDD,以及为什么咱们须要畛域驱动设计,它有哪些优缺点,尽量用一些通俗易懂文字来形容解说畛域驱动设计,本篇并不会从深层大阐述解说落地实现,这些大家能够在理解入门后再去深层次学习探讨或在后续进阶和高级篇理解,心愿通过本文介绍,能够让大家疾速理解 DDD 并有一个根底的认知,DDD 自身就是实践的汇合,很难在不积攒实践状况下来无效的施行 DDD,仅仅看一些代码案例后就开搞, 最终进去货色也是东施效颦,莫要好高骛远。最初冀望大家在工作中能多思考,如你所负责我的项目如果用 DDD 如何设计、以及会面临哪些挑战。

学习理解 DDD 之前,冀望大家可在温顾下以往咱们所理解把握一些常识,致力让本人所学所把握的内容积淀下来,举荐浏览系列。

  • Head First 设计模式: 根底面向对象概念和重要的设计模式;
  • UML 面向对象建模根底: 从需要到剖析,从剖析到设计,从设计到编码,UML 都有用武之地
  • 实现畛域驱动设计:很厚,更加求实,举荐浏览
  • 畛域驱动设计:张逸 -DDD 开山之作,挺玄幻的,多读几遍受益匪浅;

2 定义与概念

畛域驱动设计 (DDD) 提出是从零碎的剖析到软件建模的一套方法论。将业务概念和业务规定转换成软件系统中的概念和规定,从而升高或暗藏业务复杂性,使零碎具备更好的扩展性,以应答复杂多变的事实业务问题。总结它是一套残缺而零碎的设计办法、是一种设计思维、一种方法论,并不是 ” 零碎架构 ”,一种架构设计准则、思维。

2.1、为什么要应用 ” 畛域驱动设计 ”, 或者说其用处, 利用场景式什么?

  1. 长于解决高简单业务的产品研发、可帮忙咱们提炼稳固的产品内核(畛域模型中称为外围域);
  2. 通过建模可进步建模高内聚、升高模型间的耦合度,进步零碎的可扩展性与稳定性;
  3. 强调团队与领域专家的单干沟通,有助于建设一个沟通良好的团队组织;
  4. 对立设计思维与设计规范,有助于进步团队成员的架构设计能力和面向对象设计能力;
  5. 现有的微服务建构都是遵循畛域驱动设计的架构准则;
  6. 如果你负责的软件系统并不简单,那么,你的确不须要学习畛域驱动设计!

2.2、畛域驱动设计跟时下风行的架构思维最大的区别是什么?

畛域驱动设计的思维是:对象 + 行为 + 服务,所有的设计围围绕着对象、行为、服务开展;

时下风行架构设计思维是:基于 MVC 分层架构进行纵向扩大,分业务模块进行产品横向扩大;

2.2.1. 传统的计划

三层利用架构:数据 - 利用(业务逻辑层)- 展示,通常是以数据位为终点进行数据库剖析设计。

  1. 服务层过重,数据模型失血,没货色;
  2. 面条式编程或者面向数据库编程,服务层围绕数据库作业实现业务逻辑,常常一条线撸到底;
  3. 代码一整块一整块的过重,很难扩大复用;
  4. 数据库模型只是数据库映射,没有相干的行为撑持,行为都被上一层 Service 给实现等了,因而是失血 的畛域模型;
2.2.2. 畛域驱动计划

架构四层在 DDD 分层构造中将三层中业务逻辑拆解为应用层和畛域层,外围业务逻辑体现下沉到畛域层去实现,以业务畛域模型为外围建模(面向对象建模),更能体现对事实世界的形象,其长处如下

  1. 轻服务层 + 充血的畛域模型;
  2. 畛域模型封装和实现各自应有的行为,能够认为是一个高内聚、低耦合的组件;
  3. 因为模型集数据与行为于一身,是一种自解释的对象,代码复用性高,业务逻辑清晰明确;
  • 用户界面层:主要职责是通过用户界面向用户显示数据信息,同时解释用户的命令,并把用户的申请发送到应用层。
  • 应用层:通过调用根底设置和畛域层实现数据资源操作及业务流程编排,相当于 BS 层;
  • 畛域层:将业务逻辑高度内聚到畛域层,所以畛域层是整个零碎的外围,它只与理论业务相干,不关怀任何技术细节,尽可能做到与长久化无关;
  • 基础设施层:蕴含了任何类型的框架、数据库拜访代码或者公共的办法等,纯技术的一层;

2.3、如何学习畛域驱动设计

没有谁可能做到畛域驱动设计的欲速不达,所谓 ” 实践联系实际 ”,在刚开始接触或学习设计畛域驱动时,总会有一种诉求心愿能给出公式般的设计准则或标准,仿佛软件设计就像拼积木个别,只有遵循图示给出的拼搭过程,不经思考就能拼出期待的模型,这仿佛不切实际的空想,要把握畛域驱动设计,首先要理解把握一些概念以常识实践,在此基础之上思考这些概念背地蕴含的原理,设计准则,思考限界上下文 (Bounded Context) 边界的划分,理论还是围绕 ” 高内聚、低耦合 ” 准则的体现,只是咱们思考什么内容才是高内聚,如何形象能力做到低耦合,在分层架构中,各层之间该如何合作?呈现了依赖如何解耦,依然须要从重用与变动的角度去思考设计决策。

3 畛域驱动设计

畛域驱动设计强调以 ” 畛域 ” 为外围驱动力,通过模型驱动设计来保障畛域模型与程序设计的统一, 畛域模型不应该蕴含任何技术实现因素,模型中的对象实在的表白了畛域概念,却不受技术实现的束缚,畛域模型自身和技术无关,畛域驱动从设计上划分为策略设计和战术设计。

  • 一个畛域是由一个或多个模型组成;
  • 从定义上讲模型是畛域的形象;
  • 从了解上将模型能够认为是一个高内聚、低耦合的组件、模块,也能够称为一个子畛域;
  • 模型重在建模过程,建模过程会形象出一系列畛域对象和畛域服务;
  • 在 DDD 中,定义一系列的规范 ” 畛域元素 ” 用于领域建模;如战术设计元模型

3.1. 策略设计

强调业务策略上的重点,如何按重要性调配工作,以及如何进行最佳,遵循量大准则:

  1. 必须领导设计决策,以便缩小各个局部之间的相互依赖,在应用设计用意更为清晰的同时而又不失去要害的互操作性和系统性;
  2. 必须把模型的重点放在捕捉零碎概念外围,也就是零碎的 ” 近景 ” 上。
3.1.1 子域划分

整个业务畛域的一部分,关注与宏观业务,通过对大畛域进行划小在业务间划分出概念上分界线,便于在零碎策划阶段决策如何分配资源(人、钱)。

  1. 外围子域:畛域中最有价值和最外围的局部,产品成败的要害,外围竞争力, 在 DDD 开发中,次要关注核 心域,给予最高优先级;
  2. 撑持子域:我的项目中对外围子域起着撑持作用的相干性能,专一于业务的某个背面;
  3. 通用子域:与我的项目用意无关的内聚子畛域,解决一些通用问题,任何专有的业务都不应该放在通用子域;
3.1.2. 策略建模

关注点在于零碎物理划分,依据你对畛域的宰割后果及公司或部门的组织构造决策如何划分子系统,比方分出几个,零碎间如何交互,该层面往往暂不会波及够多技术细节。

  1. 限界上下文(Bounded Context): 艰深讲指零碎中模块,微服务架构中的子服务、单体中 ” 包(Java)” 或名称空间(C#),对系统的一个物理划分,限定了畛域模型的边界,在更深层次介绍深挖,这货色得分成两个词:限界、上下文,能够了解成零碎设计之初,你须要画一个圈设置一个范畴,保障畛域模型限度在这个圈内不可串场,这个‘圈’即为限界上下文。
  2. 通用语言: 用于对立领域专家、产品、研发、测试大家在应用的语言,避免出现需要了解不统一,设计与需要不统一,沟通不顺畅等问题,简略来说大家在一起聊某个货色的时候都能明确彼此所致的是什么,场景不同,同一个词就会有着不同含意。
  3. 上下文映射图:用图的形式,表白出限界上下文之间关联, 后续会独自在具体介绍上下文映射图,如 单干关系、防腐层、大泥球等;

3.2. 战术设计

依赖于畛域模型和通用预言,通过技术模式将畛域模型和通用预言中的概念映射到代码实现中。随着模型的进化,代码实现也会进行重构,以更好的体现模型概念。

  • 次要包含:
  1. 代表畛域中的概念,如实体、值对象、畛域服务、模块等;
  2. 用于治理对象的生命周期。如聚合、工厂、仓库等;
  3. 用于集成或跟踪,如畛域事件等;

3.3. 名词解释

  1. 畛域 / 子域:什么畛域?从狭义上将,畛域即是一个组织所做的事件以及所蕴含的所有,畛域可大可小有界线,不是无限大,如电商畛域,交易畛域,购物畛域等,比方咱们常听客户说“咱们有这样几块业务”一般来说这里所谓 ” 几块儿 ” 就是指子域。
  2. 实体(entity):这个词被咱们宽泛应用,甚至过分应用,实体是一个重要的概念,一个典型实体应具备 3 个因素(身份标识、属性、畛域行为),必须有惟一的身份标识,没有身份标识的畛域对象就不是实体。如:User 对象就是一个实体。
  3. 属性:实体的属性用来阐明主体的动态特色,并持有数据与状态。
@Data
public class Product{
    private String sku;
    private String name;
    private Price price;
}



  1. 畛域行为:实体领有畛域行为,能够更好地阐明其作为主体的动静特色。一个不具备动静特色的对象不属于畛域行为。
@Data
public class Product{
    private String sku;
    private String name;
    private Price price;

    // 变更状态的畛域行为
    public void changePriceTo(Price newPrice){
        // 设计产品新加个
        .......
        
    }
}




  1. 值对象(value object):比拟形象,通常作为实体的属性,区分值对象与实体的区别在于,值对象是不可变的,并且没有惟一标识,仅由其属性的值定义,参加则对它的判断是根据值还是根据身份标识,前者是值对象,后者是实体;

举个小例子:订单项和订单的关系:多对一,一个订单里有多条订单项,一个订单项,只会呈现在一个订单里,组合关系,局部不能脱离主体独自存在

public class Order {
    int id;
    User user;
}

public class OrderItem {
    private int id;
    private Product product;
    private int num;
    private Order order;
}



6)  聚合根:聚合中须要指定一个实体作为聚合根来作为整个聚合的对外触电,也就是说内部只能通过聚合根实现对外部对象的拜访,这样的限度能够对外部对象实现最大化的爱护。

4 价值是什么

简直所有我的项目的倒退都有这样一个法则:初期需要简略,中后期业务激增零碎复杂度降级,导致最后的设计理念须要大刀阔斧的改革,所以,零碎越简单、代码规模越大,DDD 的劣势就越显著。

  • 单干沟通:强调团队与领域专家的单干沟通,有助于建设一个沟通良好的团队组织;
  • 对立思维:对立设计思维与设计规范,有助于进步团队成员的架构设计能力和面向对象设计能力;
  • 零碎灵便:通过建模可进步模型的高内聚,升高模型建的耦合度,进步零碎的可扩展性与稳定性;
  • 产品内核:长于解决高复杂度业务产品研发,可帮忙咱们提炼稳固的产品内核;
  • 业务积淀:畛域模型是零碎的外围,是畛域内业务的间接积淀,具备十分大的业务价值。

5 根底篇结束语

微服务划分的一个重要实践根底就是畛域驱动设计,但因为 DDD 门槛高、概念多,体系宏大又形象,再加上实践经验和案例短少,很多开发人员对 DDD 存在不少纳闷,或只停留在平时依附检索或身边共事谈及耳闻理解 DDD,通过本篇初步意识了畛域驱动设计、后期咱们先暂短介绍这里,后续会将从代码层面动手分享 DDD 实现落地。

作者:京东物流 边雷

起源:京东云开发者社区 自猿其说 Tech 转载请注明起源

正文完
 0