《领域驱动设计的原则与实践》读书笔记(一)

   Chapter 1 什么是DDD:

1、介绍领域驱动设计思想体系

和传统开发方式比起来,领域驱动是一种新的软件架构设计,它主要用来解决传统开发中代码杂乱无章,任意拼贴等最终导致程序难以维护而诞生的。

它提出软件变得复杂和难以管理的主要原因是,领域复杂性和技术复杂性混合在了一起。

2、DDD如何管理复杂性

提炼问题重点、创建模型解决问题、使用公共语言建模协作、理解上下文关系。

DDD的侧重点:核心领域、协作、与领域专家探讨、复杂域模型的上下文理解。

3、DDD常见误区

DDD是框架、DDD是灵丹妙药

   Chapter 2 提炼问题域:

1、知识提炼,领域知识的重要性

2、业务分析员,提炼知识是一个持续过程,每一次迭代,模型都会有所变化。

3、与领域专家一起获得见解

4、使用BDD专注于应用程序的行为

   Chapter 3 专注于核心领域:

1、找出核心,支撑和通用域

2、提炼有助于降低问题空间的复杂性

3、并非一个系统的所有部分都被精心设计

   Chapter 4 模型驱动设计:

1、Code First模型驱动设计

2、使用该领域的通用语言来在代码中描述,代码是表述模型的主要形式,需要使用通用语言来约束它。

3、要让团队里面领域中隐含的观念变得明确并赋予会组成共享通用语言的名称。

4、通用语言应该用于测试,类名称,和方法。

5、仅为核心领域应用模型驱动设计并创建UL才能带来变化,不要将这些实践应用到整个应用程序。

   Chapter 5 领域模型实现模式:

1、领域层:是包含领域模型的代码区域,他将领域模型的复杂性和应用程序偶发的技术复杂性隔离开来,负责确保基础架构关注的是想管理事务和持久化这样的问题,而不会掺入业务问题并却不会让领域中已经有的规则变模糊。

图1、表示领域模型代码仅构成整体代码库的一小部分

2、领域模型模式是基于没有数据库前提的,因此它可以演化并且以完全忽略持久化的方式来创建。

在设计领域模型时,不要从数据模型开始。相反要从代码模型开始(Code First),与数据驱动设计相反的模型驱动。仅当必须考虑模型持久化时,才能在设计上做出让步。模型内的领域对象成为普通老方C#对象(POCO)。这些类不再与基础架构问题有关并却完全忽略持久性。

3、事务脚本:事务脚本整个用例都是封装在单个方法中,如数据检索,持久化,事务管理,和业务逻辑。

事务脚本缺点:对于不知道面向对象的程序员来说是一种有帮助的模式,但是如果逻辑变得复杂,事务脚本会变得很难管理,事务脚本就会出现问题。

表模式:单个对象代表数据库中的一个表或视图,适合于数据库驱动设计(DB First),不适合DDD。这个模式适合于领域中由有界上下文隔离的更简单 部分以及简单数据形式来说,非常合适并且比领域模型模式更易于掌握。但是如果对象模型和数据库模型出现分歧,那么就需要朝着DDD模式的方向进行重构。

4、活动记录:类似于表模式,是一种流行的模式,每个业务对象都负责其自身的持久化一起相关的业务逻辑,类似于Repository<T>。

5、贫血领域模型:又称为反模式。违背了“只问不说”的原则,这个模式下领域服务会承担代码更具程序性风格的角色。贫血模型是DDD中一个良好开局。

   Chapter 6 使用有界上下文维护领域模型的完整性:

1、大模型容易出错,系统扩展越多,模型越复杂

2、使用有界上下文和破除大模型

3、有界上下文拥有从展现层到领域逻辑层,再到持久化,甚至到数据存储功能的垂直切片。

并非所有的有界上下文都需共享相同的架构模式,如果有界上下文包含具有低逻辑复杂性的支撑或者通用域,那么可能会更倾向于使用CRUD的开发方式。

4、架构模式是在有界上下文的级别而非应用程序级别应用的,如果有界上下文没有复杂的逻辑,则可以使用简单的CRUD架构。

5、有界上下文中使用通用语言应该自主拥有从展现到领域逻辑,再到数据库和结构的完整代码堆栈。

   Chapter 7 上下文映射:

1、上下文和上下文之间的耦合应该通过数据库来集成并共享一个模型。

2、如果业务跨越许多上下文,并越过领域的各个部分。这个时候理解有谁负责每个需要变更的上下文以及这一变化如何发生很重要。

3、防止损坏层会在另外一个上下文交互时为模型提供隔离。该层会通过提供一个上下文到另一个上下文的转译来确保不损害完整性。

4、如果有界上下文的集成成本太高且没有其他可用的非技术方法,那么应该遵循分道扬镳方式。

   Chapter 8 应用程序架构:

1、DDD架构必须支持的一项内容是保持领域逻辑的隔离性。

2、分层架构

3、依赖倒置

领域层不依赖任何层,所有依赖关系都是向内的,它通过委托给领域层来组织对用例的处理。

领域对象需要持久化,怎么才能依赖倒置呢?通常使用在应用层定义一个让领域对象能够融合切持久的接口。这个接口从应用层的角度编写的。然后基础架构层会实现并且适配这些接口。

4、领域层、应用程序服务层、基础架构层

5、关于数据库,应该有界上线文有自己的数据库,而不是集成数据库,就像在领域模型内一样。这样避免了客户端代码很容易绕过有界上下文的保护以及领域对象状态的交互。

6、应用程序服务,定义和公开能力,业务用例写作。应用程序服务表示的是用例,不是CRUD

作为实现详情的领域层,领域服务方法可以揭示是否真的需要一个领域模型,如果发现所有业务都是CRUD,那么可以肯定,该领域缺乏所有真实的逻辑并且能通过使用事务脚本或者数据库封装模式来保持简化。

时间: 2024-10-14 21:38:33

《领域驱动设计的原则与实践》读书笔记(一)的相关文章

高性能javascript读书笔记(三.DOM 编程1)

第三章DOM Script DOM编程 读书笔记 访问和修改DOM元素 浏览器通常要求DOM实现和JavaScript保持相互独立. <!-- 例如IE中,被称为JScript的JavaScript实现位于库文件jscript.dll中,而DOM实现位于另一个库mshtml.dll(内 部代号Trident).这种分离技术允许其他技术和语言,如VBScript,受益于Trident所提供的DOM功能和渲染功能.Safari使用Webkit的WebCore处理DOM和渲染,具有一个分离的JavaS

数据访问---高性能JavaScript读书笔记(2)

对于任何一种编程语言来说,数据存储的位置关系到访问速度! 在JavaScript中的直接量包括字符串string.数字number.布尔值boolean.对象object.数组array.函数function.正则表达式regular expression.空值null.未定义数组undefined.而数组项则需要通过数组的数字索引来访问,对象通过字符串进行索引来访问其成员(这里顺便提一句因为数组项是通过数字进行索引.对象成员是通过字符串进行索引,所以这也就是为什么访问对象成员比访问数组项更慢的

加载和运行---高性能JavaScript读书笔记(1)

众所周知大多数浏览器是使用单进程处理UI更新和JavaScript运行等多个任务的,而同一时间只能有一个任务被执行,如此说来,JavaScript运行了多长时间就意味着用户得等待浏览器响应需要花多久时间. 从认知上来说,解析器解析一个界面的时候都是从上至下依次解析的,这就是说界面上出现多少个<script>标签(不管是内联还是外部文件),页面下载和解析必须停止等待脚本下载完成并运行完成(注意这里包括运行),这个过程当中,页面解析和用户交互是被完全阻塞的. Javascript第一条定律:将脚本

DOM访问---高性能JavaScript读书笔记(3)

在JavaScript高级程序设计第一章当中就把JavaScript分成三大部分 所以事实上DOM和BOM是两在独立的部分,它们之间的通信是通过相互之间的功能接口来实现的,这样说来两个独立的部分以功能接口必定会带来性能损耗.这也就是为什么大家一致都说尽量少去访问和修改DOM元素(注意我这里说的是访问和修改,为什么包括访问,请继续往下看  哈哈). 下面用一张图来说明它们各自的作用. 1.在修改DOM元素的时候,我们应该尽量使用innerHTML而不是CreateElement再AppendChi

高性能javascript读书笔记(三.DOM 编程2)

重绘和重排版 浏览器下载完所有的HTML标记,Javascript,CSS,图片之后,它解析文件并创建两个内部数据结构 DOM树 表示页面结构渲染树 表示DOM节点如何显示 渲染树中为每个需要显示的DOM树木=节点存放至少一个节点(隐藏DOM元素在选桉树中没有对应节点)渲染树上的节点称为"框"或者"盒",符合CSS模型的定义,将页面元素看作一个具有填充,边距,边框和位置的盒.一 旦DOM树和渲染树构造完毕,浏览器就可以显示(绘制)页面上的元素了. 当DOM改变影响到

Javascript读书笔记:函数定义和函数调用

定义函数 使用function关键字来定义函数,分为两种形式: 声明式函数定义: function add(m,n) { alert(m+n); } 这种方式等同于构造一个Function类的实例的方式: var add = new Function("m", "n", "alert(m+n);"); Function类构造方法的最后一个参数为函数体:"alert(m+n);",前面的都是函数的形参,参数必须是字符串形式的:&

Javascript读书笔记:字符串常用方法

concat() 连接多个字符串,返回合并后的字符串. 1 var s1="a"; 2 var s2="b"; 3 var s3="c"; 4 5 console.log(s1.concat(s2,s3));//abc 数组中的concat():将参数添加为数组的元素,返回新的数组. 1 var arr = [1, 2, 3]; 2 console.log(arr.concat(4, 5));//[1,2,3,4,5] indexOf() 查找子

高性能javascript学习笔记系列(1) -js的加载和执行

这篇笔记的内容主要涉及js的脚本位置,如何加载js脚本和脚本文件执行的问题,按照自己的理解结合高性能JavaScript整理出来的 javascript是解释性代码,解释性代码需要经历转化成计算机指令的过程,这个过程就会带来一定的性能损耗,所以在js中做性能的优化是必须的 javascript的阻塞特性:浏览器在执行js代码的时候,不能做其他的任何事情,因为浏览器使用单一的进程来处理用户界面的刷新和javascript的脚本执行,也就是说什么时候执行js脚本影响着用户对页面的使用体验(之所以js

高性能javascript学习笔记系列(6) -ajax

参考 高性能javascript javascript高级程序设计 ajax基础  ajax技术的核心是XMLHttpRequest对象(XHR),通过XHR我们就可以实现无需刷新页面就能从服务器端读取数据 var xhr = new XMLHttpRequest(); //只支持IE7以及更高的版本 xhr.onreadystatechange = function() { if(xhr.readyState == 4) { if( (xhr.status >= 200 && xh

高性能javascript学习笔记系列(5) -快速响应的用户界面

参考高性能javascript 理解浏览器UI线程  用于执行javascript和更新用户界面的进程通常被称为浏览器UI线程  UI线程的工作机制可以理解为一个简单的队列系统,队列中的任务按顺序执行 <button onclick="handleClick()">click</button> <script type="text/javascript"> function handleClick() { var div = do