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

news2024/11/25 23:52:28

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)  代码一整块一整块的过重,很难扩展复用;

  1. 数据库模型只是数据库映射,没有相关的行为支撑,行为都被上一层Service给完成等了,因此是失血 的领域模型;

2.2.2. 领域驱动方案

架构四层在DDD分层结构中将三层中业务逻辑拆解为应用层和领域层,核心业务逻辑表现下沉到领域层去实现,以业务领域模型为核心建模(面向对象建模),更能体现对现实世界的抽象,其优点如下

1)  轻服务层+充血的领域模型;

  1. 领域模型封装和实现各自应有的行为,可以认为是一个高内聚、低耦合的组件;

  2. 由于模型集数据与行为于一身,是一种自解释的对象,代码复用性高,业务逻辑清晰明确;

  • 用户界面层:主要职责是通过用户界面向用户显示数据信息,同时解释用户的命令,并把用户的请求发送到应用层。
  • 应用层:通过调用基础设置和领域层完成数据资源操作及业务流程编排,相当于BS层;
  • 领域层:将业务逻辑高度内聚到领域层,所以领域层是整个系统的核心,它只与实际业务相关,不关心任何技术细节,尽可能做到与持久化无关;
  • 基础设施层:包含了任何类型的框架、数据库访问代码或者公共的方法等,纯技术的一层;

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

没有谁能够做到领域驱动设计的一蹴而就,所谓"理论联系实际",在刚开始接触或学习设计领域驱动时,总会有一种诉求希望能给出公式般的设计准则或规范,似乎软件设计就像拼积木一般,只要遵循图示给出的拼搭过程,不经思考就能拼出期待的模型,这似乎不切实际的幻想,要掌握领域驱动设计,首先要了解掌握一些概念以知识理论,在此基础之上思考这些概念背后蕴含的原理,设计原则,思考限界上下文(Bounded Context)边界的划分,实际还是围绕"高内聚、低耦合"原则的体现,只是我们考虑什么内容才是高内聚,如何抽象才能做到低耦合,在分层架构中,各层之间该如何协作?出现了依赖如何解耦,仍然需要从重用与变化的角度去思考设计决策。

3 领域驱动设计

领域驱动设计强调以"领域"为核心驱动力,通过模型驱动设计来保障领域模型与程序设计的一致,领域模型不应该包含任何技术实现因素,模型中的对象真实的表达了领域概念,却不受技术实现的约束,领域模型本身和技术无关,领域驱动从设计上划分为战略设计和战术设计。

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

3.1. 战略设计

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

  1. 必须指导设计决策,以便减少各个部分之间的相互依赖,在使用设计意图更为清晰的同时而又不失去关键的互操作性和系统性;

  2. 必须把模型的重点放在捕获系统概念核心,也就是系统的"远景"上。

3.1.1 子域划分

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

1)  核心子域:领域中最有价值和最核心的部分,产品成败的关键,核心竞争力,在DDD开发中,主要关注核 心域,给予最高优先级;

  1. 支撑子域:项目中对核心子域起着支撑作用的相关功能,专注于业务的某个反面;

  2. 通用子域:与项目意图无关的内聚子领域,解决一些通用问题,任何专有的业务都不应该放在通用子域;

3.1.2. 战略建模

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

1)  限界上下文(Bounded Context):通俗讲指系统中模块,微服务架构中的子服务、单体中"包(Java)"或名称空间(C#),对系统的一个物理划分,限定了领域模型的边界,在更深层次介绍深挖,这东西得分成两个词:限界、上下文,可以理解成系统设计之初,你需要画一个圈设置一个范围,保证领域模型限制在这个圈内不可串场,这个‘圈’即为限界上下文。

  1. 通用语言:用于统一领域专家、产品、研发、测试大家在使用的语言,避免出现需求理解不一致,设计与需求不一致,沟通不顺畅等问题,简单来说大家在一起聊某个东西的时候都能明白彼此所致的是什么,场景不同,同一个词就会有着不同含义。

  2. 上下文映射图:用图的方式,表达出限界上下文之间关联,后续会单独在详细介绍上下文映射图,如 合作关系、防腐层、大泥球等;

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 转载请注明来源

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/978792.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

抄底抄在半山腰?散户如何摆脱追涨杀跌的诅咒?【邢不行】

你第一次炒股的经历是不是这样的: 你有一个朋友甚至是群友,他说在XX股票上大赚了一笔,你听后是既羡慕又不服。 于是你下载了炒股软件,看了眼这只股票,有点心动。但是由于没有交易经验,股价又确实涨了不少…

【实战-06】正确设置flink参数,彻底站起来

参数宝典 如何正确设置参数flink Table模式下的参数Table 模式下参数类相关DataStream 模式下怎么设置参数?总结 如何正确设置参数 很多人在应用flink DataStream 或者是Flinksql 的时候对于一些参数设置知道的不是很清晰,本文带领大家彻底搞定这一块。…

企业微信自建应用开发流程

开发需知 1、企业微信后台管理(不是小程序管理后台):企业微信 2、企业微信开发者文档(不是小程序文档):概述 - 接口文档 - 企业微信开发者中心 3、开发应用的类型:根据开发应用类型选择文档。…

GitHub个人访问凭证在哪看

要查看 GitHub 个人访问凭证(Personal Access Token),请按照以下步骤进行操作: 登录到你的 GitHub 帐户。点击右上角的头像,然后选择 “Settings”(设置)。在左侧导航栏中,选择 “D…

【PowerQuery】PowerQuery导入JSON数据

Json数据是目前使用的最为频繁和广泛的一种数据交换格式,JSON的全称为JavaScript Object Notation。Json 主要用于在互联网的消息的数据交换信息传递,他的格式与XML有什么区别呢?为什么不用XML,用Json有啥好处呢?我们接下来讨论下Json相比XML的优势: XML传递的数据过多服…

华为云云服务器评测|前端都会的文档预览服务

嗨大家好,我是专注前端技术,热衷知识分享的小鑫同学,近期华为云云服务器焕新上线,实付0.03元拥有了一个月的云服务器使用资格,我将利用这台服务器来演示作为前端同学如何部署一个文档预览服务,拒绝将文档解…

HashMap源码分析(JDK1.8)

概述 JDK 1.8 对 HashMap 进行了比较大的优化,底层实现由之前的 “数组链表” 改为 “数组链表红黑树”,本文就 HashMap 的几个常用的重要方法和 JDK 1.8 之前的死循环问题展开学习讨论。 JDK 1.8 的 HashMap 的数据结构如下图所示,当链表节…

从零开始学习 Java:简单易懂的入门指南之泛型及set集合(二十二)

泛型及set集合扩展 1.泛型1.1泛型概述 2.Set集合2.1Set集合概述和特点【应用】2.2Set集合的使用【应用】 3.TreeSet集合3.1TreeSet集合概述和特点【应用】3.2TreeSet集合基本使用【应用】3.3自然排序Comparable的使用【应用】3.4比较器排序Comparator的使用【应用】3.5两种比较…

【PowerQuery】Excel的PowerQuery的复制

在Excel中构建符合要求的PowerQuery连接之后,所有的PowerQuery 连接已经顺利的保存在Excel 工作簿当中,但是如何去查看已经保存的PowerQuery连接呢?图6.3 显示了查看PowerQuery连接。 Excel界面->数据页签->查询与连接 如果你的Power…

java八股文面试[数据库]——InnoDB与MyISAM的区别

InnoDB和MyISAM是使用MySQL时最常用的两种引擎类型,我们重点来看下两者区别。 事务和外键 InnoDB支持事务和外键,支持回滚,具有安全性和完整性,适合大量insert或update操作 MyISAM不支持事务和外键,它提供高速存储和…

mysql表中删除重复记录,只保留一条记录的操作

mysql表中两个字段重复记录,只保留一条记录的操作 例如有一张学生表 其中name 和 class 相同的视为重复记录,需要保留一条记录,删除重复记录, 两种操作方式如下: 方法一: group by SELECT MIN(cs.id) AS id ,cs.name…

东南亚时尚用品电商平台ZALORA,用自养号测评快速提升产品的评论和销量

关注东南亚电商市场的人都听说过Lazada、Shopee等电商巨头,但很少有人知道ZALORA。实际上,每当提到东南亚的电商平台时,ZALORA都是一个不可忽视的话题。尽管电商巨头SheIn在印尼市场的表现不如本土时尚电商ZALORA。 ZALORA是由德国的创业加速…

分布式实时仿真系统-反射内存的应用

为了使分布式实时仿真系统(一个典型代表就行飞行模拟器)达到逼真的仿真效果,在系统内部,往往不仅需要对各种数据模型进行实时解算,而且需要一个延迟时间极低的确定性网络在系统之间传递数据,这样才能让各个子系统之间协调一致地工…

一文速学-让神经网络不再神秘,一天速学神经网络基础(七)-基于误差的反向传播

前言 思索了很久到底要不要出深度学习内容,毕竟在数学建模专栏里边的机器学习内容还有一大半算法没有更新,很多坑都没有填满,而且现在深度学习的文章和学习课程都十分的多,我考虑了很久决定还是得出神经网络系列文章,…

通过 SQL 实现海量 GIS 数据的轨迹关联计算,确定不了解下?

作者:于成铭 | YMatrix 解决方案与架构总监 前言 统计与分析轨迹和地理区域的关联问题,是 GIS 主要的应用类别之一。最早的 GIS 应用以桌面应用程序为主,但随着需处理应用越来越复杂,GIS 的开发框架也在逐年演进。就像复杂的数据…

adb-linux 调试桥

这里写自定义目录标题 摘要:一、简介二、adb使用参考连接 摘要: adb 可替代网络、串口等调试手段,可以方便的进行文件传输、终端登录等 一、简介 ADB的全称为Android Debug Bridge,即调试桥,方便调试设备或调试开发…

(值得收藏)境外投资备案申请指南

随着全球化的不断深入,越来越多的企业开始寻求境外投资的机会。然而,在进行境外投资前,需要进行备案手续,以确保投资的合法性和可行性。 境外投资备案条件: 具有完全民事行为能力的法人或自然人。拥有足够的资金和实力…

CK_Label-V23(Battery)System Developer‘s Manual

Query PTL Tags Information Introduction to the API: Query all PTL tags information Basic Information: Attributes 接口信息 Status Finished URL http://localhost/wms/associate/getTagsMsg Request Method GET/POST Content-Type …

Shader变体自定义组合压缩方案

前言 本篇文章不讲什么是变体,不讲shader_feature和multi_compile的区别,也不讲如何收集变体。 关于什么是变体,如何优化变体,看这篇文章 Shader:优化破解变体的“影分身”之术 - 知乎 (zhihu.com) 关于变体的收集…

自然语言处理历史史诗:NLP的范式演变与Python全实现

目录 一、引言什么是自然语言处理?语言与人类思维自然语言的复杂性NLP的历史轨迹 二、20世纪50年代末到60年代的初创期符号学派重要的研究和突破 随机学派重要的研究和突破 三、20世纪70年代到80年代的理性主义时代基于逻辑的范式重要的研究和突破 基于规则的范式重…