领域驱动设计 软件核心复杂性应对之道 读书笔记

问题:

1、  何为领域驱动设计(DOMAINDriven DESIGN)?

2、  UBIQUITOUS LANGUAGE(领域通用语言)应该是如何去描述

3、

作者:Eric Evans

第二部分 模型驱动设计的构造块

 

第四章 分离模型

分层架构如图:

而主要的业务模型及在领域层。

第五章 软件中所表示的模型

模型主要包括Entity、Value Object和service

问题:

Entity、Value Object和Service是如何定义的?

它们是如何进行区分和划分的?

ENTITY

Entity模型具有标识的,模型必须定义出:“符合什么条件才算是相同的事务”。

要求:保持实体的简练、不要将注意力集中在属性或行为上,应该摆脱这些细枝末节

VALUE OBJECT

当我们只关心一个模型元素的属性时,应该将其归类到value object中。我们应该使这个模型元素表示出属性的意义,并为它提供相关功能。Value object应该是不可变的。不要为它分配任何标识,而且不要把它弄的和entity一样复杂。

在考虑到分布式环境中时:value object的两种方式应该如何适用,两个方式是复制和共享,都分别的特点是什么呢?

SERVICE

好的Service有以下三个特征:

1、  与领域概念相关的操作不是entity或value object的一个自然的部分

2、  接口是根据领域模型的其他元素定义的

3、  操作时无状态的(无状态指可以使用某个service的任何实例)。

当领域中的摸个重要的过程或转换操作不属于实体或值对象的自然职责时,应该在模型中添加一个作为独立接口的操作,并将其声明为service。定义接口时要使用模型语言,并确保操作名称是ubiquitous language中的术语。此外,应该将service定义为无状态的。

第六章 领域对象的生命周期

模式:Aggregate

每个对象模型都应该找到它的聚合根,其他仅对该模型有效的应通过聚合根来得到而不应该直接访问该对象

该模式的规则:

1、  根Entity具有全局标识,它最终负责检查固定规则

2、  根Entity具有全局标识,边界内的entity具有本地标识,这些标识只有在Aggregate内部才是唯一的

3、  Aggregate外部的对象不能饮用除根Entity之外的任何内部对象。根Entity可以把对内部Entity的引用传递给它们,但这些对象只能临时使用这些引用,而不能保持引用。

4、  作为上一条规则的推论,只有aggregate的根才能直接通过数据库查询获取。所有其他对象必须通过关联的遍历才能找到

5、  Aggregate内部的对象可以保持对其他Aggregate根的引用

6、  删除操作必须一次删除Aggregate边界内的所有对象。

7、  当提交Aggregate边界内部的任何对象修改时,整个Aggregate中的所有固定规则都必须被满足。

模式:Factory

应该将创建复杂对象的实例和聚合的职责转移给一个独立的对象,这个对象本身在领域模型中可能没人职责,但它仍是领域设计的一部分。提供一个封装所有复杂装配操作的接口,而且这个接口应该不需要客户引用要被实例化的对象的具体类。在创建Aggregate时要把它作为一个整体,并确保它满足固定规则。

好的工厂应满足两个基本需求:

1、  每个创建方法都是原子方法,而且满足被创建对象或者Aggregate的所有固定规则。

2、  Factory应该被抽象为所需的类型而不是创建出具体的类。

模式:Repository

其实Repository就相当于我们平时所说的Dao层,但在领域模型中要对其做一些限制。

为每种需要全局访问的对象类型创建一个对象,这个就对象就相当于该类型的所有对象的在内存中的一个集合的“替身”。通过一个众所周知的接口来提供访问。提供添加和删除对象的方法,用这些方法类封装在数据存储中实际插入或删除数据的操作。提供根据具体标准来挑选对象的方法,并返回属性值满足查询标准的对象获对象集合(所返回的对象是完全实例化的),从而将实际的存储和查询技术封装起来,只为那些确实需要直接访问的Aggregate根提供Repository。让客户始终聚焦于模型,而将所有对象存储和访问操作交给Repository来完成。

第七章 货物运输的例子

版本1:

隔离领域:应用程序的引入

三个用户层的应用程序功能:

1、  第一个类时TrackingQuery(跟踪查询)

2、  第二个类是BookingApplication(预定应用)

3、  第三个类是IncidentLoggin Application(事件日志应用)

设计运输系统中的关联

第三部分通过重构来加深理解

深层模型能够穿过领域表象,清楚地表达出领域专家们的主要关注点以及最相关的知识。

第8章突破

第九章 将隐式概念转变为显示概念

倾听领域专家使用的语言。有没有一些术语能够简洁地表达出复杂的概念?他们有没有纠正过你的用词?当你使用某个特定短语时,他们脸上还流露出迷惑的表情吗?这些都暗示了某个概念也许可以改进模型。

模式:Specification

业务规则通常不适合作为entity或value object的职责,而且规则的变化和组合也会掩盖领域对象的基本含义。但是将规则移出领域层的结果会更糟糕,因为这样一来,领域代码就不再表达模型了。

逻辑变成提供了一种概念,即“谓词”这种可分离、可组合的规则对象,但是要把这种概念用对象完全实现是很麻烦的。同时,这种概念也非常笼统,在表达设计意图方面,它的针对性不如设计的好。

个人观点:Specification模式其实就是建立检查接口或方法,针对某个entity编写校验规则,返回为布尔类型已验证是否继续下去。

如:

第十章 柔性设计

模式:Intention-Revealing Interfaces

一些有助于获得柔性设计的模式

在命名类和操作时要描述他们的效果和目的,而不要表露它们是通过何种方式达到目的的。这样可以使客户开发人员不必去理解内部的细节。这些名称应该与Ubiquitous language保持一致,以便团队成员可以迅速推断出它们的意义。在创建一个行为之前先为它编写一个测试,这样可以促使你站在客户开发人员的角度上来思考它。

模式:Side Effect Free Function

尽可能把程序的逻辑放到函数中,因为函数是只返回结果而不产生明显副作用的操作。严格地把命令(引起明显的状态改变的方法)隔离到不返回领域信息的,非常简单的操作中。当发现了一个非常合适承担复杂逻辑职责的概念时,就可以把这个复杂逻辑移到Value Object 中,这样可以进一步控制副作用。

模式:Assertion

把操作的后置条件和类及Aggregate的固定规则表述清楚。如果在你的编程语言中不能直接编写Assertion,那么就把他们编写成自动的单元测试。还可以把他们写到文档或图中。

寻找在概念上内聚的模型,以便使开发人员更容易退出预期的Assertion,从而加快学习过程并避免代码矛盾。

模式:Conceptual contour

把设计元素(操作、接口、类和Aggregate)分解为内聚的单元,在这个过程中,你对领域中一切重要划分的直观认识也要考虑在内。在连续的重构过程中观察发生变化和保证稳定的规律性,并寻找能够解释这些变化模式的底层Conceptual contour。使模型与领域中那些一致的方面(正是这些方面使得领域成为一个有用的知识体系)相匹配。

模式:Standalone Class

在对象设计时保持低耦合是一个基本要素。把其他所有无关概念提取到对象之外。这样类就变成完全孤立的了,这就使得我们可以单独地研究和理解它。每个这样的孤立类都极大的减轻了因理解Module而带来的负担。

模式:Closure of operation

在适当的情况下,在定义操作时让它返回类型与其参数的类型相同。如果实现者的状态在计算中会被用到,那么实现者实际上就是操作的一个参数,因此参数和返回值应该与实现者有相同的类型。这样的操作就是在该类型的实例集合中的闭合操作。闭合操作提供了一个高层接口,同时又不会引入对其他感念的任何依赖性。

第十一章 分析模式的应用

第十二章 将设计模式应用与模型

模式:Strategy(也称为Policy)

我们需要把过程中的易变部分提取到模型的一个单独的“策略”对象中。将规则与它所控制的行为区分开。按照strategy设计模式来实现规则或可替换的过程。策略对象的多个版本表示了完成过程的不同方式。

模式:ComPosite

定义一个把composite的所有成员都包含在内的抽象类型,在容器上实现一些用来查询信息的方法,这些方法可用来收集与容器内容有关的信息。“叶”节点基于它们自己的值来实现这些方法,客户只需使用抽象类型,而无需区分“叶”和容器。

第十三章 通过重构得到更深层的理解

第十四章 保存模型的完整性

模式:Bounded Context

明确地定义模型所应用的上下文。根据团队的组织、软件形同的各个部分的用法以及物理表现(代码和数据库模式等)来设计模型的边界。在这些边界中严格模型的一致性,而不要受到边界以外问题的干扰和混淆。

模式:Continuous integration

建立一个经常把所有代码和其他实现2工件合并到一起的过程,并通过自动测试来快速查明模型的分裂问题。严格坚持使用Ubiquitous Language,以便在不同人的头脑中演变出不同的概念时,使所有者对模型都能达成一个共识。

模式:Context Map

识别每个模型在项目中的作用,并定义其Bounded Context。这包括非面向对象子系统的隐含模型。为每个BoundedContext命名,并把名称添加到Ubiquitous language中。

描述模型之间的接触点,明确每次交流所需的转换,并突出任何共享的内容。

从领域模型中选出两个团队都同意共享的一个子集。当然,除了模型的这个子集以外,这还包括与该模型部分相关的代码子集,或数据库设计的子集。这部分明确共享的内容具有特殊的状态,而且一个团队在没与另一个团队商量的情况下不应该擅自更改它。

模式:Customer/Supplier Development team

在两个团队之间建立一种明确的客户/供应商关系。在计划会议中,下游团队相当于上游团队的客户。根据下游团队的需求来协商需要执行的任务并为这些任务做预算,以便每个人都知道双方的约定和进度

两个团队一起开发自动验收测试,用来验证预期的接口。把这些测试添加到上游团队的测试套件中,以便作为持续集成的一部分运行。这些测试使上游团队在作出修改时不必担心对下游团队产生副作用。

模式:Conformist

通过严格遵从上游团队的模型,可以消除在Bounded context之间进行转换的复杂性。尽管这会限制下游设计人员的风格,而且可能不会得到理想的应用程序模型,但选择conformity模式可以极大的简化集成。此外,这样还可以与供应商团队共享一种ubiquitous language。供应商处于驾驶者的位置上,引擎最好使他们能够容易沟通。他们从利他主义的角度出发,会与你分享信息。

模式:Anticorruption layer

创建一个隔离层,以便根据客户资金的领域模型来为客户提供相关的功能。这个层通过其现有接口与另一个系统进行对话,而只需对那个系统做出很少的修改,甚至无需修改。在内部,这个层在两个模型直接进行必要的双向转换。

模型:Open host service

定义一个协议,把你的子系统作为一组service供其他系统访问。开放这个协议,以便所有需要与你的子系统集成的人都可以使用它。当有新的集成需求时,就增强并扩展这个协议,但个别团队的特殊需求除外。满足这种特殊需求的方法是使用一次性的转换器来扩充协议,以便使公事协议简单并内聚。

模式:Published language

把一个良好文档化、能够表达出所需领域信息的共享语言作为公共的通信媒介,必要时在其他的信息与该语言之间进行转换。

第十五章 精炼

模式:core domain

对模型进行提炼。找到Core domain 并提供一种易于区分的方法把它与那些辅助作用的模型和代码分开。最有价值和最专业的概念要轮廓分明。尽量压缩Core DOMAIN。

模式:Generic SubDomain

把内聚的子领域(他们不是项目的动机)识别出来。把这些子领域的通用模型提取出来,并放到单独的MODULE中。任何专有的东西都不应放到这些模块中。

模型:Domain vision statement

写一份Core domain的简短描述以及它将会创造的价值,也就是“价值主张”。那些不能讲你的领域模型与其他领域模型区分来的方面就不要写。展示出领域模型是如何实现和均衡各方利益的。这份描述要尽量精简。

模型:Highlighted core

模型:Cohesive mechanism

把概念上的Cohesive Mechanism(内聚机制)分离到一个单独的轻量级框架中。要特别注意公司算法或那些有完备文档的算法。用一个Intention revealing interface来公开这个框架的功能。现在,领域中的其他元素就可以只专注与如何表达问题(做什么)了,而把解决方案的复杂细节(如何做)转移给了框架。

模式:Segregated core

对模型进行重构,把核心概念从支持性元素(包括定义得不清楚的那些元素)中分离出来,并增强Core的内聚性,同时减少它与其他代码的耦合。把所有通用元素或支持性元素提取到其他对象中,并把这些对象放到其他的包中-即使这会把一些紧密耦合的元素分开。

模式:Abstract core

把模型中最基本的概念识别出来,并分离到不同的类、抽象类或接口中。设计这个抽象模型,使之能够表达出重要组件之间的大部分交互。把这个完整的抽象模型放到它自己的module中,而专用的、详细的实现类则留在由子领域定义的Module中。

第十六章 大比例结构

大比例结构什么意思????

模式:Evolving order

模式:system metaphor

模式:responsibility layer

模式:Knowledge level

模式:Pluggable component framework

时间: 2024-10-08 10:40:55

领域驱动设计 软件核心复杂性应对之道 读书笔记的相关文章

《领域驱动设计 软件核心复杂性应对之道》 - 书摘精要

(序) 领域模型的最大价值是它提供了一种通用语言,这种语言是将领域专家和技术人员联系在一起的纽带: (P2) 模型是一种知识形式,他对知识进行有选择的简化和有目的的结构化: (P33) 面向对象编程之所以功能强大,是因为它基于建模范式,并且为模型构造提供了实现方式: (P48) 领域驱动设计只有应用在大型项目上才能产生最大的收益,而这也确实需要高超的技巧: (P70) 在大型系统中,中等粒度的.无状态的 Service 更容易被重用,因为它们在一个简单的接口背后封装了重要的功能: 细粒度的对象可

领域驱动设计:软件核心复杂性应对之道-2

2015-06-29 第二章 语言的交流和使用 模式: UBIQUITOUS LANGUAGE(通用语言) 开发在于领域专家沟通时,需要建立一个通用语言,来减少沟通的成本 基于业务,开发和业务达成共识,用双方都能理解的黑话来讨论序曲 强调了专业术语的差异,带来沟通和理解的成本,为了降低成本,必须使用一种共同的术语来建模. 这个术语更偏重于业务,而不是开发,但开发对于术语所代表的意义和业务要达成共识. 领域语言在描述业务场景或者是构建领域模型时,如果有歧义,则需要领域专家向开发人员澄清,清除歧义,

读书笔记--领域驱动设计:软件核心复杂性应对之道-1

2015–6-28 第一章 消化知识 有效建模的要素 1. 模型和实现的绑定 模型要基于现实的业务,不能和用户现实的业务脱节 2. 获得一种基于模型的语言 通过一种统一的语言(业务人员和开发人员都能理解的)去描述所建立的模型,如UML图,基于业务的术语,无奇异的,作者的意思是业务人员和开发人员建立基于模型一个沟通的桥梁. 3.开发一个蕴含丰富知识的模型 灵活的,适应变化的的模型,模型不能简单等同于类图,而是解决复杂业务问题的方案.包含各种类型的知识 4. 提炼模型 对业务的描述要抽象,从场景的分

解构领域驱动设计(二):领域驱动设计的核心之分层架构

反映业务规则的代码是整个软件的核心,但是它一般只占很小的一部分,在传统的基于贫血模型的分层软件架构中,业务规则可能分散到各个层.各个代码段,从而使得通过代码来还原业务规则或者保证代码与业务规则一致将变得非常困难.DDD分层架构的核心思想就是将所有业务规则的代码抽取到领域层,保证领域层的编码与领域模型是完全一致的. 下图是DDD的分层架构.?我将通过代码来演示这个新的分层架构. 1 应用层 应用层在这里非常的简单清晰,它仅仅是将基础设施层.领域层提供的功能装配起来完成任务,这一层的代码逻辑非常简单

我的“第一次”,就这样没了:DDD(领域驱动设计)理论结合实践

写在前面 插一句:本人超爱落网-<平凡的世界>这一期,分享给大家. 阅读目录: 关于DDD 前期分析 框架搭建 代码实现 开源-发布 后记 第一次听你,清风吹送,田野短笛:第一次看你,半弯新湖,鱼跃翠堤:第一次念你,燕飞巢冷,释怀记忆:第一次梦你,云翔海岛,轮渡迤逦:第一次认你,怨江别续,草桥知己:第一次怕你,命悬一线,遗憾禁忌:第一次悟你,千年菩提,生死一起. 人生有很多的第一次:小时候第一次牙牙学语.第一次学蹒跚学步...长大后第一次上课.第一次逃课.第一次骑自行车.第一次懂事.第一次和喜

.NET领域驱动设计—实践(穿过迷雾走向光明)

阅读目录 开篇介绍 1.1示例介绍 (OnlineExamination在线考试系统介绍) 1.2分析.建模 (对真实业务进行分析.模型化) 1.2.1 用例分析 (提取系统的所有功能需求) 1.3系统设计.建模 (技术化业务模型) 1.3.1 枚举类型的使用 (别让枚举类型成为数值型对象) 1.3.2 基础数据.业务数据 (显示实体和隐式过程) 1.3.3 模型在数据库中的主外键关联问题 (面向对象模型与关系模型的天然抗阻) 1.3.4 角色.类型 (区分类型与面向对象概念) 1.3.5 名词

Re:从零开始的领域驱动设计

领域驱动的火爆程度不用我赘述,但是即便其如此得耳熟能详,但大多数人对其的认识,还只是停留在知道它的缩写是DDD,知道它是一种软件思想,或者知道它和微服务有千丝万缕的关系.Eric Evans对DDD的诠释是那么地惜字如金,而我所认识的领域驱动设计的专家又都是行业中的资深前辈,他们擅长于对软件设计进行高屋建瓴的论述,如果没有丰富的互联网从业经验,是不能从他们的分享中获取太多的营养的,可以用曲高和寡来形容.1000个互联网从业者,100个懂微服务,10个人懂领域驱动设计. 可能有很多和我一样的读者,

领域驱动设计和实践

软件系统面向对象的设计思想可谓历史悠久,20世纪70年代的Smalltalk可以说是面向对象语言的经典,直到今天我们依然将这门语言视为面向对象语言的基础.随着编程语言和技术的发展,各种语言特性层出不穷,面向对象是大部分语言的一个基本特性,像C++.Java.C#这样的静态语言,Ruby.Python这样的动态语言都是面向对象的语言. 但是面向对象语言并不是银弹,如果开发人员认为使用面向对象语言写出来的程序本身就是面向对象的,那就大错特错了,实际开发中,大量的业务逻辑堆积在一个巨型类中的例子屡见不

领域驱动设计(DDD)实现之路

2004年,当Eric Evans的那本<领域驱动设计——软件核心复杂性应对之道>(后文简称<领域驱动设计>)出版时,我还在念高中,接触到领域驱动设计(DDD)已经是8年后的事情了.那时,我正打算在软件开发之路上更进一步,经同事介绍,我开始接触DDD. 我想,多数有经验的程序开发者都应该听说过DDD,并且尝试过将其应用在自己的项目中.不知你是否遇到过这样的场景:你创建了一个资源库(Repository),但一段时间之后发现这个资源库和传统的DAO越来越像了,你开始反思自己的实现方式