前言

笔者于2021年入职了杭州一家做水务系统的公司,按照部门经理要求,新人需要做一次个人分享(主题随意)。 当时笔者对DDD充满了浓厚的兴趣,之前也牛刀小试过,于是就决定班门弄斧Show一下。后来在公司的新项目中,笔者也是大胆启用了DDD,带领团队和DDD来了一场亲密拥抱。尽管该项目最后被无情抛弃,笔者却未留下任何遗憾。今天拿来记录,权当是本人对DDD的一次追忆吧!

正题

领域驱动设计(Domain Drive Design)的概念,以下简称“DDD”,来源于2003年著名建模专家Eric Evans发表的他最具影响力的书籍《领域驱动设计--软件核心复杂性应对之道》。DDD是一种设计方法,围绕业务概念构建领域模型,并通过分离技术实现的复杂度,从而控制软件演化的复杂度。

什么是领域

领域(Domain)是指一种特定的范围或区域。领域是有范围的,可以根据范围的不同来定义边界。DDD的领域指的就是这个边界内要解决的业务问题域。

什么是子域

领域可细分为多个子领域,即子域(Sub Domain)。每个子领对应一个更小的问题域。子域可根据自身重要性和功能属性划分为三类子域:
核心子域:决定产品和公司核心竞争力的子域,是业务成功的主要因素和公司的核心竞争力。
通用子域:没有太多个性化需求,同时被多个子域使用的通用功能子域。比如: 认证、权限等。
支撑子域:既不包含决定产品和公司核心竞争力的功能,也不包含通用功能的子域,但又是必需的子域。具有企业特性,但不具通用性。

什么是战略设计和战术设计

DDD分为战略部分和战术部分,两者相辅相成。战略部分用于理解、梳理业务,找到核心业务,更好地划分系统(这也是DDD为什么可用于指导微服务设计的原因)。战术部分用于落地到代码上,用代码来清晰地表示业务,代码如何分层、如何设计都有一套成熟的指导方案。

什么是通用语言

通用语言(Ubiquitous Language) 是通过团队交流达成共识的能够简单、清晰、准确传递业务规则的语言。通用语言往往跟领域中的名词术语和用例场景有关。名词一般可以给领域对象命名,如:客户、订单等,它们对应领域模型中的实体对象。动词则表示一个动作或领域事件,如:商品已下单、订单支付等,它们对应领域模型中的领域事件或者命令。

什么是限界上下文

限界上下文(Bounded Context) 可以拆分为两个词:限界和上下文。限界是指一个边界,某一个范围。上下文:即语义环境。限界上下文就是在限定的上下文环境内,用来封装通用语言和领域对象,保证领域内的一些术语、领域对象等有一个确切的含义,没有语义二义性的一个业务边界。

什么是领域模型

领域模型(Domain Model)是关于某个特定业务领域的软件模型。通常,领域模型通过对象模型来实现,这些对象同时包含了数据和行为,并且表达了准确的业务含义。

什么是实体

在DDD的领域模型中有这样一类对象,它们拥有唯一标识符,并且它们的标识符在经历各种状态变更后仍能保持一致。对于这些对象而言,重要的不是属性,而是其延续性和标识。我们把这样的领域对象称为实体(Entity)。

什么是值对象

值对象(Value Object) 是通过对象属性值来识别的对象,它将多个相关的属性组合成一个概念整体,用于描述领域的某个特定方面,是一个没有标识符的对象。值对象是没有生命周期的,且数据不可变。

什么是聚合和聚合根

聚合(Aggregate)定义了一组具有内聚关系的相关对象的集合,我们把聚合看作是一个修改数据的单元。每个聚合都含有一个根实体,叫做聚合根(Aggregate Root)。

1. 每个聚合有一个根和一个边界,边界定义了一个聚合内部有哪些实体或值对象,根是聚合内的某个实体。
2. 聚合内部的对象之间可以相互引用,但是聚合外部要访问聚合内部的对象时,必须通过聚合根才行。
3. 聚合内除根以外的其他实体的唯一标识都是本地标识,也就是只要在聚合内部保持唯一即可,因为它们总是从属于这个聚合的。
4. 聚合根负责与外部其他对象打交道并维护自己内部的业务。
5. 基于聚合的以上概念,我们可以推论出从数据库查询时的单元也是以聚合为一个单元,也就是说我们不能直接查询聚合内部的某个非根的对象。
6. 聚合内部的对象可以保持对其他聚合根的引用。
7. 删除一个聚合根时,必须同时删除该聚合内的所有相关对象。因为它们都同属于一个聚合,是一个完整的概念。

什么是仓储

仓储(Repository)是一个协调领域模型和数据映射层的组件,使用类似集合的接口访问领域对象。

1. 仓储是介于领域层和基础层之间薄薄的一层,为了解耦领域逻辑和数据处理逻辑。
2. 仓储模式包含仓储接口和仓储实现。仓储接口定义在领域层,而仓储实现在基础层(依赖倒置)。
3. 仓储是为聚合服务的,一个聚合会对应一个仓储,统一由仓储来完成聚合数据的持久化。

什么是领域服务

当一块业务逻辑无法融入任何现有聚合,而聚合又无法通过重新设计适应操作时,就要考虑使用领域服务(Domain Service)了。为了实现业务操作,领域服务负责协调聚合和仓储的活动。同时领域服务使用的名字严格遵循统一语言。

DDD如何分层

DDD将系统分为四层:基础设施层、领域层、应用程序层和表现层。

基础设施层:该层为其它各层提供技术有关的任何东西,它不会涉及任何业务知识。比如:对数据库的访问,因为数据的读写与业务无关。

领域层:包含了业务所涉及的领域对象、领域服务以及它们之间的关系。这部分内容的具体表现形式就是领域模型。DDD提倡富领域模型,即尽量将业务逻辑归属到领域对象上,实在无法归属的部分则以领域服务的形式进行定义。

应用程序层:该层不包含任何领域逻辑,但它会对任务进行编排,并可以维护应用程序的状态。因此,它更注重流程性的东西。该层是针对特定应用程序的。

表现层:负责提供用来完成任务的用户界面。它是一组屏幕,每个屏幕都包含了一组数据以及从这个屏幕发送另一组具有明确定义的数据的操作。

为什么需要DDD

即使我们的软件中没有bug,也不能表示我们设计的软件模型本身就是好的。使用DDD能够让我们的软件设计更加合理,但不止于此。对一个业务复杂的系统而言,使用DDD有如下好处:

1. 开发者和熟悉业务的人一起工作,加强团队间不同角色的合作。
2. 能够帮助业务人员和开发人员梳理清楚复杂的业务规则。
3. 开发出来的软件是能够准确表达业务规则的,设计就是代码,代码就是设计。

结尾

以上就是笔者那次PPT分享文字,差不多一个多小时的阐述,也只能让大家对DDD有个浅显的认识。 笔者第一次接触DDD的时候也是一头雾水、不知所云,觉得这东西太高大上。后来通过拜读园子里大佬的关于DDD的文章,再加上自己的反复推敲和琢磨,才有了一丝入门的感觉。事实上,光有理论知识还不够,你还等有一把神兵利器来为你的DDD项目保驾护航。没错,笔者正是在项目中借助了ABP这套框架,才有了足够的开发底气。 最后用一句话总结就是:纸上得来终觉浅,绝知此事要躬行。

记一次公司内部技术分享—DDD的更多相关文章

  1. 公司内部技术分享之Vue.js和前端工程化

    今天主要的核心话题是Vue.js和前端工程化.我将结合我这两年多的工作学习经历来谈谈这个,主要侧重点是前端工程化,Vue.js侧重点相对前端工程化,比重不是特别大. Vue.js Vue.js和Rea ...

  2. 内部技术分享的 PPT

    本文的基础是搞了一次内部的技术分享,在此也分享一下本次的PPT的一些内容.先列一下大概内容吧. EF-Code First API(WCF.WebAPI) Xaml MVVM AOP Xamarin. ...

  3. 全景VR视频游戏外包公司:技术分享使用U3D+CB制作VR游戏

    随着Oculus宣布1月6日开启预售,2016年很可能成为VR游戏元年,但很多的调研显示,手游设备才是市场增长的关键,SuperData发布的报告显示,2016年全球VR游戏市场规模预计在51亿美元左 ...

  4. 【转】子弹短信内部技术分享:Redis

    原理 Redis 是一个内存型「数据库」,除存储之外,它还有许多强大的命令,使之远远超出了数据库的定义,所以官方称之为「data structure store」,数据结构存储系统. 通过 Redis ...

  5. 2018.09.22 上海大学技术分享 - An Introduction To Go Programming Language

    老实说笔者学习 Go 的时间并不长,积淀也不深厚,这次因缘巧合,同组的同事以前是上海大学的开源社区推动者之一,同时我们也抱着部分宣传公司和技术分享的意图,更进一步的,也是对所学做一个总结,所以拟定了这 ...

  6. 技术分享之AQS——内容提要

    1. 背景 最近团队内部技术分享,我做了个关于AQS的分享.ppt中涵盖的部分要点内容,现在整理到博客上. 关于AQS本身的源码解读,可以参考我之前的博文. 2. 要点梳理 下面是一些技术分享的要点梳 ...

  7. 公司内部培训SQL Server传统索引结构PPT分享

    公司内部培训SQL Server传统索引结构PPT分享 下载地址 http://files.cnblogs.com/files/lyhabc/SQLServer%E4%BC%A0%E7%BB%9F%E ...

  8. 公司内部培训AlwaysOn PPT分享

    公司内部培训AlwaysOn PPT分享 下载地址: http://files.cnblogs.com/files/lyhabc/alwayson.ppt

  9. 前端知识概述----公司内部的一次分享 分类: JavaScript HTML+CSS 2015-04-16 21:24 2593人阅读 评论(2) 收藏

    因为公司内部一个纯后端团队要做一些适合自己团队的web页面,所以就有了这次分享.知识都是很基础,有的知识也只是做了解简单介绍.主要是想让大家对前端有一个基本的了解.现在做一个总结.欢迎大家拍砖. 知识 ...

  10. DNS域名解析之搭建公司内部域--技术流ken

    什么是DNS DNS( Domain Name System)是“域名系统”的英文缩写,是一种组织成域层次结构的计算机和网络服务命名系统,它用于TCP/IP网络,它所提供的服务是用来将主机名和域名转换 ...

随机推荐

  1. 猿人学内部js练习平台习题记录

    猿人学内部js练习平台习题记录 根据课程更新 当前先完成第7题和第10题 第7题 骚操作 请求规律检测1 - post 1)通过fiddler抓包,看看请求头和请求体有什么骚操作的地方,如果没有反爬就 ...

  2. 2022-08-06:给定一个数组arr,长度为N,arr中所有的值都在1~K范围上, 你可以删除数字,目的是让arr的最长递增子序列长度小于K。 返回至少删除几个数字能达到目的。 N <= 10^4

    2022-08-06:给定一个数组arr,长度为N,arr中所有的值都在1~K范围上, 你可以删除数字,目的是让arr的最长递增子序列长度小于K. 返回至少删除几个数字能达到目的. N <= 1 ...

  3. 2022-06-30:以下golang代码输出什么?A:0;B:2;C:运行错误。 package main import “fmt“ func main() { ints := make

    2022-06-30:以下golang代码输出什么?A:0:B:2:C:运行错误. package main import "fmt" func main() { ints := ...

  4. 2022-04-11:给定一个正数数组arr,其中每个值代表砖块长度, 所有砖块等高等宽,只有长度有区别, 每一层可以用1块或者2块砖来摆, 要求每一层的长度一样, 要求必须使用所有的砖块, 请问最多

    2022-04-11:给定一个正数数组arr,其中每个值代表砖块长度, 所有砖块等高等宽,只有长度有区别, 每一层可以用1块或者2块砖来摆, 要求每一层的长度一样, 要求必须使用所有的砖块, 请问最多 ...

  5. 【工作随手记】并发之synchronized

    synchronized对于java同学肯定都是耳熟能详的必修课了.但是不管对于新手还是老手都有一些容易搞错的点.这里权做一点记录. 锁的是代码还是对象? 同步块一般有两种写法. 1是直接加以方法体上 ...

  6. rt下降40%?程序并行优化六步法

    1 背景 性能优化是我们日常工作中很重要的一部分,主要有以下原因: 降低服务器和带宽等硬件成本:用更少的资源处理更多的请求 提高现实世界的运行效率:人机处理效率存在数量级的偏差,同样机器世界的效率提升 ...

  7. java解决中文乱码的几种写法

    工作中总会遇到中文乱码问题,以导出文件,文件名称是中文的话,下载下来的文件名称会乱码问题,总结了几种解决文件名乱码的写法,仅供参考. 首先定义一个汉语字符串 String zhName = " ...

  8. 近期SQL优化实战分享

    分享一下本周SQL优化的两个场景. 如果能对读者有一定的启发,共同探讨,不胜荣幸. 版本信息:mysql,5.7.19 引擎: innodb 场景1 我们有一张常口表,里面的数据由各种数据源合并而来, ...

  9. CIO视角|平台工程带来的优势与机遇

    在当今高速发展的技术环境中,企业越来越依赖技术作为创新和竞争优势的战略驱动力.首席信息官(CIO)在企业中负责监督信息和计算机技术的管理和实施,以交付预期的业务成果.在技术是业务核心的公司中,CIO ...

  10. 大家都说Java有三种创建线程的方式!并发编程中的惊天骗局!

    在Java中,创建线程是一项非常重要的任务.线程是一种轻量级的子进程,可以并行执行,使得程序的执行效率得到提高.Java提供了多种方式来创建线程,但许多人都认为Java有三种创建线程的方式,它们分别是 ...