温州做网店的网站,网站优化的好处,微信上做任务让你注册彩票网站,如何选择建网站公司同名读书笔记#xff0c;对于一些自觉重要的点进行记录。 扩展资源#xff1a;github.com/evancyz/ddd-learning UML中类图的一些基本知识 - jack_Meng - 博客园 最后的第四部分暂时没看 Part Two 模型驱动设计的构造块
Chapter 5 软件中所表示的模型
5.2 模式#xff1a;… 同名读书笔记对于一些自觉重要的点进行记录。 扩展资源github.com/evancyz/ddd-learning UML中类图的一些基本知识 - jack_Meng - 博客园 最后的第四部分暂时没看 Part Two 模型驱动设计的构造块
Chapter 5 软件中所表示的模型
5.2 模式EntityReference Object
一个对象主要不是由他们的属性定义而是有一个“标识”但又不是如Java自带的标识的形式而是业务上的如银行结算单和交易记录簿进行对账时就是具备相同标识的交易。Entity最基本的职责是确保连续性以便其行为更清楚且可预测。与标识有关的属性尽量留在Entity内。当然实际上这种标识仍是由属性来实现。
5.3 模式Value Object
eg. 画画时很容易区分出画Entity是谁画的但有两只一样的笔我们不会记住某个线条是其中哪只笔VO画的。
VO用来描述领域的某个方面而本身没有概念标识的对象。我们只关心它们是什么而不关心它们是谁。
但同一个对象在不同的场景下可能是Entity也可能是VO要具体分析。也不一定是Entity has VO也可能是VO has Entity。如果说Entity之间的双向关联很难维护那么两个VO之间的双向关联则完全没有意义。
VO应该是不可变的不需要分配标识VO所包含的属性应该形成一个概念整体。
5.4 模式Service
有时候对象不是一个事物。有些重要的领域操作无法放到Entity或VO中因为这些操作本质上是一些活动或动作而非事物。
Service不具有封装的状态它强调的是与其他对象的关系。Servie的特征
与领域概念相关的操作不是Entity或VO的一个自然组成部分。接口是根据领域模型的其他元素定义的。操作是无状态的。任何客户都可以使用某个Service的任何实例
定义接口时要使用模型预言并确保操作名称是UBIQUITOUS LANGUAGE中的术语。
可根据是否包含专业业务规则将Service分为“应用Service”和“领域Service”。
5.5 模式Module 模块或Package
Module之间应该是低耦合的Module内部则是高内聚的。
打包时注意对象的一个基本概念时将数据和操作这些数据的逻辑封装到一起。
除非真正有必要将代码分布到不同的服务器上否则就把实现单一概念对象的所有代码放在同一个模块中。
5.6 建模范式
对象范式
混合范式
Chapter 6 领域对象的生命周期
6.1 模式Aggregate
eg. 当删除一个用户时我们如何处理地址呢可能还有其他人住在同一个地址删除的话其他用户变为引用空对象。保留的话垃圾地址会积累其他。——在具有复杂关联的模型中要想保证对象更改的一致性是很困难的。
首先需要一组抽象来封装模型中的引用。Aggregate就是一组相关对象的集合我们把它作为数据修改的单元。每个Aggregate都有一个根root和一个边界boundary。外部对象只可以引用根而边界内部的对象之间可以互相引用。
Aggregate内部的对象可以保持对其他Aggregate根的引用。删除操作必须一次删除Aggregate边界之内的所有对象。…
参考P85示例。
6.2 模式Factory
对象的功能主要体现在其复杂的内部配置以及关联方面。我们应该一直对对象进行提炼直到所有与其意义或在交互中的角色无关的内容被完全剔除为止。
eg. 汽车只有在被生产时才需要装配工在我们驾驶时并不需要由于汽车的装配和驾驶永远不会同时发生将这两种功能合并到同一个机制中毫无价值。——将创建复杂对象的实例和Aggregate的职责转移给单独的对象即Factory。
接口的设计。当设计Factory的方法签名时需要注意
每个操作都必须是原子的。必须确定创建失败时的操作。Factory将与其参数发生耦合。若只是将参数插入依赖度是适中的若是选出一部分在构造对象时使用耦合将更为紧密。
由于Entity需要“标识”Entity Factory和VO Factory有所不同。
重建已存储的对象时也需要注意。
6.3 模式Repository
无论对象执行什么操作都需要保持对它的引用那么如何获得这个引用呢采用关系型数据库使得人民自然而然地使用基于对象的属性来获取引用。——执行查询来找到对象然后重建它。
从概念上讲对象检索发生在Entity生命周期的中间我们把用已存储的数据创建实例的过程称为重建。
大多数对象都不应该通过全局搜索来访问。——随意的数据库查询会破坏领域对象的封装和Aggregate。技术基础设施的和数据库访问机制的暴露会增加客户的复杂度并妨碍模型驱动的设计。
Repository解除了客户的巨大负担使客户只需要与一个简单的、易于理解的接口进行对话。它们使得应用程序和领域设计与持久化技术解耦。
Factory与Repository
Factory负责处理对象生命周期的开始而Repository帮助管理生命周期的中间和结束。Factory负责制造新对象而Repository负责查找已有对象。 引申《DAO还是Repository,傻傻的分不清?》 关于 Dao 和 Repository 在技术上假设如果不用区分的那么细。但在语义上就很重要了因为当我看到 repository 的时候想到的设计聚合而 dao 会第一个想到是一个贫血Entity。这也是 模式 的一个重要作用 进一步可以参考《阿里技术专家详解DDD系列 第三讲 - Repository模式》 传统Data MapperDAO属于“固件”和底层实现DB、Cache、文件系统等强绑定如果直接使用会导致代码“固化”。所以为了在Repository的设计上体现出“软件”的特性主要需要注意以下三点 接口名称不应该使用底层实现的语法出参入参不应该使用底层数据格式需要记得的是Repository操作的是Entity对象实际上应该是Aggregate Root而不应该直接操作底层的DO。更近一步Repository接口实际上应该存在于Domain层根本看不到DO的实现。这个也是为了避免底层实现逻辑渗透到业务代码中的强保障。应该避免所谓的“通用”Repository模式 Chapter 7 使用语言一个扩展的示例
系统设计过程
模型设计UML类图隔离领域引入应用层区分Entity和VO依次考虑每个对象看看这个对象是必须被跟踪的实体还是仅表示一个基本值。或思考两个完全相同的对象是否需要区分开设计领域类间的关联关系引用关系。若存在循环引用需要考虑数据库设计的问题。划分Aggregate边界。选择Repository 上一步有多少Entity是Aggregate的根则选择存储库的时候只需要考虑这几个实体其他对象都不能有Repository。回看需求重新确定这些实体确实需要Repository。 场景走查对象的创建思考是否需要为其中重要的类创建Factory方法。重构 并发问题考虑某项修改操作的使用频率是否会带来对应Aggregate的并发问题。是否可以使用其他技术来替代该操作eg. 用查询来替代维护一个集合。又涉及到Repository的问题。 划分Module我们应该寻找紧密关联的概念并弄清楚我们打算向项目中的其他人员传递什么信息。引入新特性功能 链接两个系统与已有的另一个系统对接进一步完善模型划分业务。可能需要添加中间类来与其他系统的接口对接。性能优化。eg. 上述的中间类可以添加缓存功能来提升性能。 小结对于Enterprise Segment的获取正确的做法是让那些知道划分规则的对象来承担获取这个值的职责而不是把这个职责施加给包含具体数据那些规则就作用于这些数据上的对象。
Part Three 通过重构来加深理解
深层模型深层模型能够穿透表象清楚地表达出领域专家们的主要关注点以及最相关的知识。
Chapter 8 通过重构来加深理解
实际上是特定领域模型的理解加深或实际需求增多/复杂化来驱动的重构。而重构的过程本身又会进一步加深对模型的理解。
Chapter 9 将隐式概念转变为显式概念
深层建模的第一步就是要设法在模型中表达出领域的基本概念。开发人员在消化知识或重构的过程中识别出某个隐含的概念并将其显式地表达出来。
概念挖掘与领域专家不断交流。
模式Specification举得例子实际就是 调用链模式 Chapter 10 柔性设计
10.1 模式Intention-revealing interfaces释义接口 如果开发人员为了使用一个组件而必须要去研究它的实现那么就失去了封装的价值。在命名类和操作时要描述他们的效果和目的而不要表露他们是通过何种方式达到目的的。整个子领域可以被划分到独立的模块中并用一个表达了其用途的接口把他们封装起来。 10.2 模式Side-Effect-Free Function无副作用方法 我们可以宽泛地把操作分为两个大的类别命令和查询P.S. 相当于读和写多个规则的相互作用或计算结果的组合所产生的结果是很难预测的。开发人员在调用一个操作时为了预测操作的结果必须理解它的实现以及它所调用的其他方法的实现。如果开发人员不得不“揭开接口的面纱”那么接口的抽象作用就收到了限制。尽可能把程序的逻辑放到函数中因为函数是只返回结果而不产生明显副作用的操作。严格地把命令引起明显的状态改变的方法隔离到不返回领域信息的、非常简单的操作中。当发现了一个非常适合承担复杂逻辑职责的概念时就可以把这个复杂逻辑移到Value Object中这样可以进一步控制副作用。 P. S. 实际上例子是对于两个类A1和A2将原设计中类A中被改变地部分属性抽出来类BVO类即A1、A2分别带有B1、B2而A1、A2操作时不改变自己的B1、B2而是生成B3返回。 10.3 模式Assertion断言 如果操作的副作用仅仅是由他们的实现隐式定义的那么在一个具有大量相互调用关系的系统中起因和结果会变得一团糟。理解程序的唯一方式就是沿着分支路径来跟踪程序的执行。封装完全失去了价值。跟踪具体的执行也使抽象失去了意义。把操作的后置条件和类及Aggregate的固定规则表述清楚如果在你的编程语言中不能直接编写Assertion那么就把他们编写成自动的单元测试。还可以把他们写到文档或图中如果符合项目开发风格的话 P.S. 书中的例子是编写了单元测试。回想一下深度学习Python框架倒是常用assert检查矩阵维度。 10.4 模式Conceptual Contour概念轮廓 如果把模型或设计的所有元素都放在一个整体的大结构中那么他们的功能就会发生重复。而另一方面把类和方法分解开可能也是毫无意义的这会使客户更复杂迫使客户对象去理解各个细微部分是如何组合在一起的。通过反复重构最终会实现柔性设计。寻找在概念上有意义的功能单元这样可以使得设计既灵活又易懂。例如如果领域中对两个对象的“相加”是一个连贯的整体操作那么就把它作为整体来实现。不要把add()拆分成两个独立步骤。把设计元素操作、接口、类和Aggregate分解为内聚的单元在这个过程中你对领域中一切重要划分的直观认识也要考虑在内。在连续的重构过程中观察发生变化和保证稳定的规律性并寻找能够解释这些变化模式的底层Conceptual Contour。使模型与领域中那些一致的方面正是这些方面使得领域称为一个有用的知识体系相匹配。 10.5 模式Standalone Class独立的类 互相依赖使模型和设计变得难以理解、测试和维护。Module和Aggregate的目的都是为了限制互相依赖的关系网。低耦合是对象设计的一个基本要素。尽一切可能保持低耦合。把其他所有无关概念提取到对象之外。这样类就变得完全独立了这就使得我们可以单独研究和理解它。 10.6 模式Closure Of Operation闭合操作 在适当的情况下在定义操作时让它的返回类型和与其参数的类型相同。如果实现者implementer的状态在计算中会被用到那么实现者实际上就是操作的一个参数因此参数和返回值应该与实现者有相同的类型。这样的操作就是在该类型的实例集合中的闭合操作。闭合操作提供了一个高层接口同时又不会引入对其他概念的任何依赖。 eg. 从Collection中选择元素子集需要使用Iterator但是是否有必要使用Iterator这个额外概念以及其带来的额外复杂性呢 10.7 声明式设计 通常指一种编程方式——把程序或程序的一部分写成一种可执行的规格specification。使用声明式设计时软件实际上是由一些非常精确的属性描述来控制的。如可以通过反射机制来实现或在编译时通过代码生成来实现根据生命来自动生成传统代码。这种方法使其他开发人员能够根据字面意义来使用声明。它是一种绝对的保证。问题把软件束缚在一个由自动部分构成的框架之代码生成技术破坏了迭代循环把生成的代码合并到手写的代码中。声明式设计发挥的最大价值时用一个范围非常窄的框架来自动处理设计中某个特别单调且易出错的方面如持久化和对象关系映射。 10.8 声明式设计风格 一旦你的设计中有了Intention-revealing interfaces释义接口、Side-Effect-Free Function无副作用方法和Assertion断言就具备了使用声明式设计的条件。 在之前的Chapter 9 的 Specification中实际使用了调用链但是调用链只能作为串行的条件过滤使用如其中所说的为化学品安排容器但是也应该尽量安排成本低的容器所以要扩展and、or、not的接口现在将这几种操作也分别封装成一个类继承同一个抽象类。 10.9 切入问题的角度 eg. 经过改造贷款相关业务代码改造为了 复杂的逻辑通过Side-Effect-Free Function被封装到了专门的Value Object中修改状态的操作很简单而且是用Assertion来描述的。模型概念除了耦合操作只涉及最少的其他类型。 Chapter 11 应用分析模式
分析模式的最大作用是借鉴其他项目的经验把那些项目中有关设计方向和实现结果的广泛讨论与当前模型的理解结合起来。 关联了Martin Fowler的《分析模式》一书 Chapter 12 将设计模式应用于模型
12.1 模式StrategyPolicy策略模式12.2 模式Composite 组合模式 定义一个把Composite的所有成员都包含在内的抽象类型。在容器上实现那些查询信息的方法时这些方法返回由容器内容所汇总的信息。而“叶”节点则给予它们自己的值来实现这些方法。客户只需使用抽象类型而无需区分“叶”和容器。 组合设计模式 Chapter 13 通过重构得到更深层的理解
重构的时机
设计没有表达出团队对领域的最新理解重要的概念被隐藏在设计中了而且你已经发现了把他们呈现出来的方法发现了一个能令某个重要的设计部分变得更灵活的机会