大家好,我是烤鸭:
    《实现领域驱动设计》,读书笔记,贴个封面,要不不知道是哪本。

了解概念

刚开始接触DDD,肯定懵逼,很多名词,一点点看下。

领域:带有业务属性的范围,比如搞直播业务,那直播就是一个领域。领域里又分核心域和子域。

可以看个电商系统的领域图。

限界上下文:用于承接不同子域。

上下文映射图:限界上下文关系图。

六边形架构:又称端口适配器,水平的分层架构,牺牲一部分性能,更好的防止逻辑层外漏。

CQRS:Command Query Responsibility Segregation,读写分离。这个读写分离跟我们想的还有点不一样,

领域事件内的读库和写库的数据同步是基于领域事件的,比如写mysql,读的时候读es,这时候就需要领域事件触发mysql到es的同步。

章节回顾

当我们开始一个业务,需要考虑领域边界,不只是业务层面的,还有技术层面的。核心域的创建,子域的分类,实体和值对象的建立等等。

限界上下文的建模需要考虑不同子域,比如不同流程,需要的对象属性不同,上下文建模的对象就可能意义不同。(比如上面的电商系统,订单子域和发票子域、库存子域的限界上下文对象肯定是不同的)

几种架构设计:

  • 分层架构:用户接口层—>应用层—>领域层—>基础设施层。依赖倒置原则,高、低层模块都依赖于抽象。

  • 六边形架构:外界通过适配器和内部交互。

  • SOA:Service-Oriented Architecture,面向服务架构。这个服务可能是根据业务或者技术来拆分的,并不是服务越多越好,需要考虑限界上下文。技术架构不能影响业务领域模型。

  • REST: URI决定访问的资源,是无状态通信。利于解耦,需要单独涉及上下文。

  • CQRS:读写分离。查询模型和DTO的建立。写模型执行业务行为发布领域事件,事件订阅器更新查询模型。
    (比如查询在es或者redis,在收到写事件时,同时更新es或者redis)

  • 事件驱动:类似linux中的管道和过滤器,采用分治的方式解决大型问题。定义实体和领域事件(业务维度的操作),跟踪器监听长时处理过程(分布式的并行处理模式),考虑幂等,监听超时可以主动定时查询。事件源(记录领域模型的操作)和快照(对一系列事件后生成的,类似redis的AOF恢复时对命令整合)

  • 数据网织,缓存的建立和层级维护,通过客户端监听保证缓存中的查询模型更新,长时处理过程不一定是事件驱动。

实体

实体的建立,实体具有唯一标识和可变性,值对象没有。普通的数据模型(CURD模型)是不会创建出好的业务模型,数据模型需要转换为实体模型。

值对象可以用于存放实体的唯一标识。唯一标识可以由用户传递、应用生成、持久化生成或者上下文传递。

委派标识,可以做唯一索引。层超类型(通过继承的方式,隐藏主键)在聚合层可以做乐观锁。

值对象

值对象的常见例子,比如 数字、文本、日期,或者复杂的对象。

在值对象中引用实体,应该考虑不变性、表达性和方便性。否则,一旦实体改变属性,会破坏值对象的不变性。

使用值对象可以缩小集成化,简化职责假设。协作上下文中的防腐层(身份校验和参数转化)、开放主机服务(三方调用)使用相同的值对象会简单很多。

测试用例也可以使用值对象,使用断言。

值对象的备份和相等性验证。(通过copy的方式,生成新的值对象,并且验证两个相等性)。

ORM和值对象,数据库直接保存值对象,值对象的每一个属性对应一列。多个值对象ORM的情况不考虑。

领域服务

领域服务主要是处理业务逻辑的,将领域对象转换成值对象。只有在必要时建模领域服务。(遵循单一职责原则)

创建独立接口,如果使用依赖倒置或者六边形架构,有些实现类可能在领域模型之外。

领域事件

无论是外部还是内部系统,通过领域事件维护事件的一致性,可以消除两段式事务,还可以支持聚合。(最常见的就是mq)

通过领域服务创建事件,添加到资源库,通过消息设施进行发布,需要有唯一标识,可以做幂等。

基于 发布-订阅,可以解耦,允许短暂的数据不一致,最终一致。同时作为消费方,在单个事务中只修改单个聚合实例。

事件可以用队列存储,利于检查历史记录,聚合操作。(需要关注事件顺序)

以rest方式发布事件(多个消费方拉取同一个URI时),需要考虑顺序和对发布事件的跟踪(存档日志)。

消息的重复发送需要做幂等处理。

模块

maven项目中的module,设计的要和领域概念保持一致,松耦合,杜绝循环依赖。

模块名的命名规范,比如 com.saasovation.agilepm.domain.service/model

优先考虑组织结构,而不是松耦合性。先考虑模块,后考虑限界上下文。

聚合

实体和值对象在边界内组成聚合。CQS查询将大聚合分为几个小聚合。

聚合边界内一套不变的业务规则维持一致性,类似持久化机制中的事务。

小聚合在性能和可伸缩性上有好处,还能减少事务的提交冲突。

通过唯一标识引用其他聚合。不能在同一事务中修改多个聚合,需要考虑事务失败的情况。

如果聚合特别多,在web层处理复杂,需要考虑聚合中的标识引用或者实体引用。

发布-订阅或者观察者模式,事务非原子性,通过聚合达到一致性。(分布式场景需要考虑并发)

创建具有唯一标识的根实体,优先使用值对象。

使用"迪米特法则"(强调"最小知识"原则)和"告诉而非询问法则(一个对象不应该被告知如何执行操作)。

数据库层面加版本号的乐观锁方式限制并发。

避免将资源库和领域服务注入到聚合层。

工厂

工厂相关的设计模式有抽象工厂、工厂方法、建造者。

领域模型中的工厂只负责创建对象,没有其他权责。

聚合根中的工厂方法用于创建聚合对象,减轻客户端创建聚合实例时的负担,确保所有实例都在正确的状态。

领域服务中的工厂主要集中在防腐层、发布语言和开放主机服务的集成上。限界上下文的交互中,将领域内的对象转换为上下文中的对象。这里的领域服务其实扮演的是工厂的角色。

资源库

资源库是对聚合实例的一种持久化,代替DTO。

以集合资源库为例,需要考虑顺序和幂等。资源库和数据库层面数据一致性,采用双写保险。

资源库的正确用法,要么只读,要么读取是为了修改。

使用Nosql对资源库进行持久化,需要考虑数据结构。

有时候需要返回大聚合对象中的子聚合,可以考虑直接从资源库中获取,返回值对象。如果用例优化查询,还是需要多个查询方法,可能是边界划分错误,考虑使用CQRS。

领域层不考虑事务,事务加在业务层,不要过多的在领域模型上使用事务。测试环境测试没问题,生产环境有可能会有并发问题。

使用单个资源库保存和获取层级中不同的聚合类型,客户端无需知道他们使用的实际类型,体现了里氏替换原则。

资源库和DAO不同。DAO是从数据库表角度来看待问题,提供CURD操作。可以将资源库当做DAO来看,不过设计资源库时,应该面向集合,而不是面向数据。

集成限界上下文

多种方式,一种是:soap、http(xml)、rpc,另一种是消息队列(发布—订阅),第三种是 restful。

分布式系统本身是有风险的,两个系统间的数据交互还需要考虑版本更新,数据结构改变等等。比如消息消费方的端口适配器应该将自己内部的领域模型和外部的领域模型隔离开,同时传入的数据必须遵循本地限界上下文的类型定义。

无论那种方式(http、rpc) 部署接口/类,还是定义媒体类型契约(mq),看业务场景和项目阶段。但从产品角度,使用低耦合的媒体类型更好。

开放主机服务:当一个限界上下文以URI的方式提供了大量REST资源时,可称其为开放主机服务。

比如下面这个Rest的URI,判断某个用户角色,返回200就是有该角色,其他的就没有。

/tenants/{tenantId}/users/{username}/inRole/{role}

上面这个内部实现是六边形架构的适配器,再调用应用服务和领域服务。

防腐层是上下文协作交互的方式,数据转换的作用,防腐层通常有一个特定的适配器。

利用消息队列传递上下文需要考虑顺序和幂等,最小化或者消除不同限界上下文之间的信息复制。

长时处理过程指的是完全走完一个流程,比如发布两个对象,经过了哪些过滤器。其中有跟踪器,目的是监听哪些过期,哪些可以重试。

跟踪器放到本地上下文,而不是协作上下文。

针对MQ超时重试,使用否定应答和消息重发结合的方式。

消息集群宕机恢复后,服务监听器可以自动重连。

应用程序

应用程序通过用户界面向外界展示领域模型的概念,并且允许用户在模型上执行各种操作。

DTO(Data Transfer Object) 数据传输对象,将包含需要的所有属性值,从资源库获取再映射。缺点是DTO 可能暴露领域内部数据结构,应该考虑解耦。

调停者模式,即双分派和回调。客户端实现调停者接口,把对象引用传给聚合,聚合通过调停者发布自身状态。

DPO(Domain Payload Object) 领域负载对象,包含了整个聚合实例的引用,而不是单独属性。也使用调停者解耦,避免延迟加载的问题,强制手动访问所有延迟加载的属性。

VO(View Object) 客户端展示层,通过适配器将DTO转换。

优化资源库查询,可以直接返回值对象。

应用服务不等于领域服务,所有的业务领域逻辑放到领域模型,不管是聚合、值对象或者领域服务,应用服务是很薄的一层,只使用他们协调对模型的任务操作。

一种方式是多应用层,每个用户界面组件都提供所有的应用层,此时用户界面组件将向领域模型靠近。结果有点像贫血领域对象。

领域模型需要考虑模块包的命名,比如:

com.consumerhive.productreviews.domain.model.product

基础设施的职责是为应用程序的其他部分提供技术支持。(比如自己初始化bean,注入spring容器)

总结

尽管尽量减少章节回顾的内容,还是有很多不好理解的点。

DDD的概念推出很久了,不过感觉用的人不多,会用的人就更少了。

大家一直强调微服务,模块、实体、nosql、mq,这些跟DDD都有交集,不过建模真的考虑过DDD么,是贫血领域对象还是应用服务当做领域服务。

领域模型的建立必须是懂得业务的人参与,纯技术是没办法建模的。

下一篇想结合实战,写一下DDD在实际业务中的使用。

《实现领域驱动设计》读书笔记相关推荐

  1. 读书笔记 | 墨菲定律

    1. 有些事,你现在不做,永远也不会去做. 2. 能轻易实现的梦想都不叫梦想. 3.所有的事都会比你预计的时间长.(做事要有耐心,要经得起前期的枯燥.) 4. 当我们的才华还撑不起梦想时,更要耐下心来 ...

  2. 读书笔记 | 墨菲定律(一)

    1. 有些事,你现在不做,永远也不会去做. 2. 能轻易实现的梦想都不叫梦想. 3.所有的事都会比你预计的时间长.(做事要有耐心,要经得起前期的枯燥.) 4. 当我们的才华还撑不起梦想时,更要耐下心来 ...

  3. 洛克菲勒的38封信pdf下载_《洛克菲勒写给孩子的38封信》读书笔记

    <洛克菲勒写给孩子的38封信>读书笔记 洛克菲勒写给孩子的38封信 第1封信:起点不决定终点 人人生而平等,但这种平等是权利与法律意义上的平等,与经济和文化优势无关 第2封信:运气靠策划 ...

  4. 股神大家了解多少?深度剖析股神巴菲特

    股神巴菲特是金融界里的传奇,大家是否都对股神巴菲特感兴趣呢?大家对股神了解多少?小编最近在QR社区发现了<阿尔法狗与巴菲特>,里面记载了许多股神巴菲特的人生经历,今天小编简单说一说关于股神 ...

  5. 2014巴菲特股东大会及巴菲特创业分享

     沃伦·巴菲特,这位传奇人物.在美国,巴菲特被称为"先知".在中国,他更多的被喻为"股神",巴菲特在11岁时第一次购买股票以来,白手起家缔造了一个千亿规模的 ...

  6. 《成为沃伦·巴菲特》笔记与感想

    本文首发于微信公众帐号: 一界码农(The_hard_the_luckier) 无需授权即可转载: 甚至无需保留以上版权声明-- 沃伦·巴菲特传记的纪录片 http://www.bilibili.co ...

  7. 读书笔记002:托尼.巴赞之快速阅读

    读书笔记002:托尼.巴赞之快速阅读 托尼.巴赞是放射性思维与思维导图的提倡者.读完他的<快速阅读>之后,我们就可以可以快速提高阅读速度,保持并改善理解嗯嗯管理,通过增进了解眼睛和大脑功能 ...

  8. 读书笔记001:托尼.巴赞之开动大脑

    读书笔记001:托尼.巴赞之开动大脑 托尼.巴赞是放射性思维与思维导图的提倡者.读完他的<开动大脑>之后,我们就可以对我们的大脑有更多的了解:大脑可以进行比我们预期多得多的工作:我们可以最 ...

  9. 读书笔记003:托尼.巴赞之思维导图

    读书笔记003:托尼.巴赞之思维导图 托尼.巴赞的<思维导图>一书,详细的介绍了思维发展的新概念--放射性思维:如何利用思维导图实施你的放射性思维,实现你的创造性思维,从而给出一种深刻的智 ...

  10. 产品读书《滚雪球:巴菲特和他的财富人生》

    作者简介 艾丽斯.施罗德,曾经担任世界知名投行摩根士丹利的董事总经理,因为撰写研究报告与巴菲特相识.业务上的往来使得施罗德有更多的机会与巴菲特亲密接触,她不仅是巴菲特别的忘年交,她也是第一个向巴菲特建 ...

最新文章

  1. IT人应该具备的几种技能
  2. Splash 占位图适配 全面屏笔记
  3. ActiveMq消费端实现集群部署
  4. 【Linux】一步一步学Linux——fg命令(130)
  5. python输入一个列表的语句_python自学笔记使用if语句处理列表作业
  6. javaweb学习总结(十一):使用Cookie进行会话管理
  7. Python3.7模块之re
  8. 白帽子技术分析会话劫持实战讲解
  9. 关联规则java代码_重量挖掘关联规则挖掘方法,哪个大神可以将以下伪代码转换为Java代码?...
  10. JUnit:在参数化测试中命名单个测试用例
  11. extjs中Store和grid的刷新问题
  12. 趣文:如何成为Google软件工程师?(二)
  13. html 获取下一个兄弟节点,js jquery获取当前元素的兄弟级 上一个 下一个元素
  14. 简单制作RPM二进包实例(转)
  15. 期刊会议的论文,sci,ieee,ccf ,acm等等他们之间的关系,以及如何能看到这些高质量文章
  16. 企业私有云存储选NAS还是私有云盘?3分钟带你了解企业NAS和企业云盘的区别
  17. 赛尔号周五几点服务器维护完,赛尔号手游几点刷新游戏 | 手游网游页游攻略大全...
  18. 【J2EE】模仿天猫商城(后台篇)
  19. 关于拿鸡蛋数学题的解法
  20. Java学习之路——接口

热门文章

  1. [css] 怎样修改chrome记住密码后自动填充表单的黄色背景?
  2. [css] 如何让一个块元素绝对居中?
  3. [css] 使用css3实现一个斑马线的效果
  4. 工作332:uni-uview上传获取到对应数据
  5. 前端学习(2041)vue之电商管理系统电商系统之只是在发布阶段生效
  6. 前端学习(1363):学生档案信息管理5
  7. 不学好css模型的怎么入山门?师傅与徒弟的真实独白
  8. spring mvc学习(1):spring jar包
  9. 计算机操作系统(2):OS的发展过程
  10. 一个USB HUB电路分享