领域驱动设计思路讲义ppt课件.ppt

上传人:飞****2 文档编号:69258502 上传时间:2023-01-01 格式:PPT 页数:124 大小:3.58MB
返回 下载 相关 举报
领域驱动设计思路讲义ppt课件.ppt_第1页
第1页 / 共124页
领域驱动设计思路讲义ppt课件.ppt_第2页
第2页 / 共124页
点击查看更多>>
资源描述

《领域驱动设计思路讲义ppt课件.ppt》由会员分享,可在线阅读,更多相关《领域驱动设计思路讲义ppt课件.ppt(124页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、领域驱动建模(Evans DDD)为什么使用MDD/DDDnMDD是模型驱动设计,与MDA模型驱动架构类似,体现为MDD=DDD+DSL。nMDD is faster MDD很快(真正快速开发)在MDD应用模型中能够指定一个比传统的编程语言更高的抽象层次。该模型能够自动转化为可立即运行工作的应用程序(通过UML工具),生成可解释/执行模型代码。模型中的每个元素代表了多行代码,这样使得模型在一个更高的抽象层次比相应的代码要精简得多,更能大道至简。nMDD is more cost-effective MDD更具有成本优势因为MDD快速开发所以比较快地推向市场,MDD意味更少的人员 专家,更高的质

2、量,成本只是你学习MDD的成本以及工具采购,使用MDD拓展和维护应用程序的做法也更符合成本效益。通过更高级别模型阅读,比较容易理解应用程序。MDD/DDD优点nMDDleadstoincreasedqualityMDD引导质量提高引导质量提高因为软件架构是在一个更高模型级别定义,然后通过引擎或框架因为软件架构是在一个更高模型级别定义,然后通过引擎或框架转换成代码,这样我们能够让我们最优秀的人员从事引擎和框架转换成代码,这样我们能够让我们最优秀的人员从事引擎和框架的开发,进而提高平台的质量。的开发,进而提高平台的质量。我们在项目中学习到的最佳实践我们在项目中学习到的最佳实践模式可以被导引到引擎或

3、框架代码产生器中,这样将被重用到所模式可以被导引到引擎或框架代码产生器中,这样将被重用到所有使用有使用MDD的项目中。的项目中。nMDDislesserror-proneMDD很少出错很少出错测试会浪费很多时间,因为测试会浪费很多时间,因为MDD可以确保代码的质量,这样让你可以确保代码的质量,这样让你可以专注于测试应用程序的特点功能即验收测试上,不必关注通可以专注于测试应用程序的特点功能即验收测试上,不必关注通用的一些测试项目,如基础设施相关的技术问题或安全漏洞用的一些测试项目,如基础设施相关的技术问题或安全漏洞MDD/DDD优点nMDDleadstomeaningfulvalidationM

4、DD引导有意义的校验引导有意义的校验业务验证都已经在更高级别的模型中完成,编程工具只能帮助你业务验证都已经在更高级别的模型中完成,编程工具只能帮助你验证代码语言的错误,不能验证业务上的错误。验证代码语言的错误,不能验证业务上的错误。使用使用DSL能够在设计时候就执行一下,这样,错误信息也是能够在设计时候就执行一下,这样,错误信息也是domain-specific级别的,可见级别的,可见StaticVerification:AnExternalDSLAdvantage一文。一文。MDDresultsinsoftwarebeinglesssensitiveforchangesinpersonnel

5、MDD可以不在乎人事变动可以不在乎人事变动不需要特别的技术高手或架构师就能够建立软件,节约人力成本。不需要特别的技术高手或架构师就能够建立软件,节约人力成本。此外,如果有人加入一个项目,比较容易理解高层次的软件应用此外,如果有人加入一个项目,比较容易理解高层次的软件应用模型,这比试图通过阅读理解源代码要轻松多模型,这比试图通过阅读理解源代码要轻松多)。MDD/DDD优点nMDDempowersdomainexpertsMDD授权领域专家授权领域专家业务领域专家能够注重建模,而技术专家可以专注于建立一个业务领域专家能够注重建模,而技术专家可以专注于建立一个MDD需要的框架或需要的框架或DSL等工

6、具。一个软件系统不再只是程序编制等工具。一个软件系统不再只是程序编制就可以了,领域专家可以通过符号(如文字,图形,表格)等直就可以了,领域专家可以通过符号(如文字,图形,表格)等直接表达他们对业务领域的深入理解接表达他们对业务领域的深入理解。8.MDDletadvancedprogrammersfocusonthehardstuffMDD能够让高级程序员专攻难关能够让高级程序员专攻难关在在MDD中,高级程序员的重复性工作要少得多,他们可以专注于中,高级程序员的重复性工作要少得多,他们可以专注于他们工作的创造性方面。他们可以集中精力建设他们工作的创造性方面。他们可以集中精力建设MDD的工具。他的

7、工具。他们还可以指导初级开发或领域的专家,也可以申请领取困难攻关,们还可以指导初级开发或领域的专家,也可以申请领取困难攻关,领域专家可以专注例如模型的图形用户界面,流程和业务规则。领域专家可以专注例如模型的图形用户界面,流程和业务规则。而应用程序的集成部分(使用而应用程序的集成部分(使用webservices,API调用,数据库集调用,数据库集成等)对于领域专家来说,存在太大困难,可以由高级程序员来成等)对于领域专家来说,存在太大困难,可以由高级程序员来完成。完成。MDD/DDD优点nMDDbridgesthegapbetweenbusinessandITMDD在业务和在业务和IT之间之间架设

8、了桥梁架设了桥梁领域专家(或系统分析师)可以直接参与业务发展进程(见第领域专家(或系统分析师)可以直接参与业务发展进程(见第7点)。点)。技术专家(软件应用)可以在一个更高的层次定义尽可能和领域概念的技术专家(软件应用)可以在一个更高的层次定义尽可能和领域概念的定义声明有关模型。定义声明有关模型。通过在模型和模型实现之间定义一个重要的转换机制,就可以在业务和通过在模型和模型实现之间定义一个重要的转换机制,就可以在业务和IT技术之间建立一个桥梁,比如使用一个基于技术之间建立一个桥梁,比如使用一个基于model-drivenSOA的框架。的框架。nMDDresultsinsoftwarebeing

9、lesssensitiveforchangesinbusinessrequirementsMDD可以减少业务需求带来改变的影响面可以减少业务需求带来改变的影响面对软件开发的问题之一是业务需求经常变化速度超过了软件系统支持改对软件开发的问题之一是业务需求经常变化速度超过了软件系统支持改变,这对于企业是一个重点战略问题:能够保持足够长的时间调整其核变,这对于企业是一个重点战略问题:能够保持足够长的时间调整其核心业务与心业务与IT流程。流程。MDD使软件开发更快,它也导致更容易改变应用。如果在业务需求和软使软件开发更快,它也导致更容易改变应用。如果在业务需求和软件之间的存在一个联系,那么应用程序甚至

10、有可能自动适应部分模型的件之间的存在一个联系,那么应用程序甚至有可能自动适应部分模型的变化。变化。MDD/DDD优点nMDDresultsinsoftwarebeinglesssensitiveforchangesintechnologyMDD导致技术对变化不是太敏感导致技术对变化不是太敏感技术变化很快,技术变化很快,JavaEE,SOA/SOBA,webservices,REST,SCA,OSGi等等,甚至迁移到云计算环境,当您希望您的应用程等等,甚至迁移到云计算环境,当您希望您的应用程序迁移到其他技术时,序迁移到其他技术时,MDD可以确保你不必改变你的应用模型,。可以确保你不必改变你的应用

11、模型,。唯一需要改变的代码生成器(或唯一需要改变的代码生成器(或DSL解释器)。改变后的代码生解释器)。改变后的代码生成器(或添加额外的代码生成选项)可以帮助所有的应用程序模成器(或添加额外的代码生成选项)可以帮助所有的应用程序模型直接转换成基于新技术架构的代码。型直接转换成基于新技术架构的代码。MDDreallyenforcesarchitectureMDD增强架构增强架构当使用当使用MDD开发软件应用程序,保证符合选定架构。你可以真正开发软件应用程序,保证符合选定架构。你可以真正实现架构标准化,实现架构标准化,构建架构原则构建架构原则Constructionalarchitecturepr

12、inciples能够知道设计构建,并且能够反映在代码生成器或解释能够知道设计构建,并且能够反映在代码生成器或解释器中。器中。MDD/DDD优点nMDDcapturesdomainknowledgeMDD可以截获领域知识可以截获领域知识关于关于MDD的优点是,你不是只创建软件,但你也捕捉正式高层次的优点是,你不是只创建软件,但你也捕捉正式高层次的领域知识模型。在大多数情况下这方面的知识是不明确,见文的领域知识模型。在大多数情况下这方面的知识是不明确,见文章基于章基于DDD的的DSLMDDprovidesup-to-datedocumentationMDD提供最新的文提供最新的文档档当使用当使用M

13、DD,您不会遭遇不完整或过时的文件,因为该模型使用,您不会遭遇不完整或过时的文件,因为该模型使用正确的抽象,可以让领域专家和客户都能看懂。正确的抽象,可以让领域专家和客户都能看懂。MDDenablestofocusonbusinessproblemsinsteadoftechnologyMDD能够关注业务而不是技术能够关注业务而不是技术停止讨论使用停止讨论使用WS-*或者或者REST,MDD能够让你专注于业务问题如能够让你专注于业务问题如何解决,而不是着眼于如何解决这些问题的技术支撑。何解决,而不是着眼于如何解决这些问题的技术支撑。Evans DDDn2004年Eric Evans 发表Dom

14、ain-Driven Design Tackling Complexity in the Heart of Software(领域驱动设计)简称Evans DDDn领域建模是一种艺术的技术,它是用来解决复杂软件快速应付变化的解决之道 Evans DDD领域模型重要性n没有领域模型,只是靠代码编写完成一个又一个功能,复杂的领域需求会使得他们无法交流讨论,使工作陷入泥沼。n有少许领域模型,但是没有维护好模型与代码直接的联系,两者产生差异,无法实现。DDD优点分析设计发展的三个阶段n第一阶段:围绕数据库的驱动设计,新项目总是从设计数据库及其字段开始。n第二层次:面向对象的分析设计方法诞生后,有了专门

15、的分析和设计阶段之分,分析阶段和设计阶段是断裂的。n第三阶段:融合了分析阶段和设计阶段的领域驱动设计(Evans:DDD)。第一阶段:传统的数据库方式n过去软件系统分析设计总是从数据库开始,这种围绕数据库分析设计的缺点非常明显:n1.分析方面:不能迅速有效全面分析需求。n2.设计方面:导致过程化设计编程,丧失了面向对象设计的优点。n2.运行方面:导致软件运行时负载集中在数据库端,系统性能难于扩展,闲置了中间件J2EE服务器处理性能。n对象和关系数据库存在阻抗,本身是矛盾竞争的。第二阶段:分析和设计分裂n第二阶段比第一阶段进步很多,开始采取面向对象的方法来分析设计需求。n分析人员的职责:是负责从

16、需求领域中收集基本概念。面向需求。n设计人员的职责:必须指明一组能北项目中适应编程工具构造的组件,这些组件必须能够在目标环境中有效执行,并能够正确解决应用程序出现的问题 n两个阶段目标不一致,导致分裂,项目失败。分析模型n分析模型会有知识不断消化的过程,但在编码时这些知识会被遗弃。n开发人员被迫为设计进行新的抽象,那么分析人员嵌入模型中知识不能保留和重新发现。n分析模型很多重要发现更改往往出现在设计实现过程,预先的模型可能深入研究无关主题,忽视重要主题。问题n一个印在大纸张上的完整类图,整面墙都被它覆盖,花几个月分析开发的领域模型,模型大多数对象都与其中三四个对象有错综复杂的关系,且关系网几乎

17、没有自然边界。分析人员是忠于领域需求本质。n问题:开发人员开始实现应用程序时,彼此纠缠的关系根本无法转换成可存储 可检索的实现。n是不是基于概念的模型类图不能成为程序设计的基础?DDD领域模型特点n统一领域模型:同时满足分析原型和软件设计统一领域模型:同时满足分析原型和软件设计,如果一个模型实现时不实用,重新寻找新模,如果一个模型实现时不实用,重新寻找新模型。如果模型没有忠实表达领域关键概念时,型。如果模型没有忠实表达领域关键概念时,也必须重新寻找新的模型。也必须重新寻找新的模型。n统一语言:一个无处不在统一语言:一个无处不在(ubiquitous)的语的语言,项目中所有人统一交流的语言。减少

18、沟通言,项目中所有人统一交流的语言。减少沟通疑惑,减少传达走样。使得软件更加适合需求。疑惑,减少传达走样。使得软件更加适合需求。n建模和设计成为单个迭代循环。将领域模型和建模和设计成为单个迭代循环。将领域模型和设计紧密联系。因此,建模专家必须懂设计。设计紧密联系。因此,建模专家必须懂设计。什么是DDD?什么是领域模型 Domain Model?n只有业务(真实世界的概念),没有技术。n领域模型只表达需求真实世界模型,和软件架构技术无关。n通过分层,将领域模型层突出,其他为辅助层。机器人机器人的领域模型分层领域n将领域概念和其他软件技术相关概念分离,避免混淆,在系统庞大中失去对领域的把握。n表现

19、层:负责显示,解析用户命令n应用层:指挥领域对象实现功能,必须保持简练,不是核心。n领域层:核心 业务概念n基础层:与软件技术相关。航运程序航运程序任务分解n表现层:接受用户输入(屏幕绘制)n 向用户显示信息(显示结果)n领域层:执行业务逻辑(查询所有城市 城市和货物关联)n基础层:访问数据库(查询数据库 提交数据库更改网络通信)n不要将UI 数据库和其他支持代码直接写到业务对象中,虽然简单容易,但是拓展困难,难于自动化测试。分层 优点n每个层都是内聚的,并且只依赖它的下层,为了实现各层的最大解耦,IOC/DI容器是当前Java业务层的最好选择。n将所有与需求领域有关的代码集中在领域层,并与用

20、户UI层 应用层和基础层分离。领域对象就可以重点关注表达领域模型,不关心自己的显示 存储和管理应用任务等事情。n适合分布式部署,提升性能,高可伸缩性。核心领域n大型系统中,有很多有用的组件,他们非常复杂,都是软件成功不可或缺的,这样组件实在太多,以至于领域模型的精髓部分变得不明显甚至被忽视。n不可能所有部分都进行提炼,分清轻重缓急,让领域模型真正成为资产。n核心模型必须足够灵活和充分平衡来创建应用程序功能,不要倾向于使用技术基础结构如数据库来解决问题。n无需专业业务知识容易能理解能引起程序员的兴趣,他们认为只有解决这些问题才能积累自己专业知识,同时为自己简历增光添彩,这对于公司是浪费。不注重核

21、心领域的案例n银团贷款系统:大多数技术天才和技术高手都对数据库映射层和消息接口津津乐道,而业务模型却交给一些刚刚涉足面向对象技术的新手们打理。n尽管为持久领域对象提供详细注解文字说明,能够反映设计思路,也设计了友好的用户界面。n这些特性都是外围,当这个软件最终交付用户使用时,差劲程序员二次开发拓展时却依然搞得一塌糊涂,整个项目差点失败。浓缩模型n找出核心模型,提供一种方法让我们很容易地从众多支持模型中将它区分出来,将最有价值 最体现专门知识的概念凸显出来,核心变小。n让最好的程序员来处理核心模型,根据需要调整人员的配备,尽力找出核心的深层模型,对于其他部分投入必须经过考虑,是否能为提炼出来的核

22、心提供支持。通用子域n提炼核心领域,就必须剔除反面通用子域。n不同行业运输业 银行业 制造业都需要某种形式组织结构图。组织结构图就是通用子域。n许多应用跟踪应收帐款 费用分类和其他帐务信息,这些信息都可以使用通用的会计财务系统来处理。n有两个项目处理带时区功能的日期和时间组件,花费最好的程序员数周时间,虽然必须做,但不是系统核心。n考虑现有解决方案或开源公开模型来替代通用子域。n考虑外包,将通用子域外包,自己掌握核心领域。内聚机制n算法或计算非常复杂,导致设计受到了冲击,模型中的概念变成了用“怎么做”来解释,而不是用“是什么”表达。n设计中产生了一大堆用来实现算法 解决问题的方法,而描述这个问

23、题的方法变得模糊不清。怎么做的方法在模型中泛滥成灾,表明模型存在某种问题。n计算机制本身存在内聚性,我们计算方法不可能把所有功能都包含进来,我们需要的也不是一种万能计算机制。n使用策略模式等框架把这些内聚计算分离出来,用一个明确接口来说明这个框架的功能,将怎么做复杂细节交给框架去完成。n权限设计属于内聚机制,不是核心领域。使用RBAC隔离核心n确定一个核心子域n把相关类转移到一个新的模块,并为模块指定一个与其概念相符的名称。n重构代码,把那些不能直接表示该概念的数据和功能分开,并转移到其他模块。n重构核心模块,使关联关系和交互作用更简单易懂。同时减少和其他模块的关系。n对其他核心子域重复上面的

24、步骤,直至得到隔离核心。领域模型切割n1.将复杂大的领域分割成子领域。n2.抓住子领域的核心,建立核心模型。n3.对核心模型实现灵活性细节设计旁门左道的快速开发n没有分层架构的快速开发基本是旁门左道,不如返回Foxpro和Delphi/VB两层时代。n将本属于业务层的逻辑交由表现层来处理的快速UI方式也是一种旁门左道。n快速开发必须基于良好的质量,虽然良好的分层架构带来开发效率的降低,但是这些也是可以有方法解决。模型元素n实体(Entity)n A thread of continuity and identity.n在时间上一系列连续性(continuity)和标识(identityID)来

25、定义。n值对象(Value Object):n如果一个对象代表了领域的某种描述性特征,且没有概念性的标识。Description原型。n服务(Service):行为接口。实体n实体就是在客观世界中有实体内容的物体对象。经过时间延续一直保持其特点不变。n软件实际是客观世界的拷贝或镜子,实体就是镜子中那个实物。n必须拥有自己的唯一ID,主键,如果没有一个ID标识,为每个实例加上一个具有唯一性ID,可能是内部使用。n由于对象主观认定性,在特殊情况下,我们可能会主观划分一些实体。n 实体建模n实体最基本职责是保证连续性,以便使之有清晰 可预见的行为。n关注重点不是它们的属性或行为,而是找出固有的特征,

26、提出其他细节。n这个固有特征包括:可以唯一标识对象的 特征;经常用来查找或匹配对象的特征。n只留下和特征相关的行为和属性,其他则转移到与该实体相关联的其他对象。n目的:保持实体高度精简。特征核心实体标识n一个实体对应一个标识,处于分布式系统内存中,或保存在磁盘中,标识必须在整个系统唯一性。n一个对象从数据库检索出来 生成一个新的对象实例,失去上次标识;通过网络传来一个对象实例,丢失原来的标识;同一个对象存在多个不同副本,比如分布式缓存,标识混乱。n怎样判断两个对象在概念上代表同一个实体呢?实体如何标识n为每一个实例加上一个ID(一个数字或一个字符串)标记。n标识具有不变性,与实体同生共死。对象

27、实例被保存到数据库中时,ID值也要保存起来。nID可以由系统自动产生,ID产生算法必须保证系统中值的唯一性。标识性质n隐式ID:软件用户通过人名查找客户,系统必须使用内部ID分辨两个姓名相同的联系人,用户可能看不到。n显式ID:包裹传递服务,运输公司软件产生跟踪号码,预订机票酒店,产生确认码订单号。n跨系统ID:两家医院的计算机系统对同一个患者生成不同的ID,使用公共机构如社保卡号n用户自定义ID:支票对账提供ID匹配,用用户来决定是否真的对应。值对象n许多对象没有标识,只是事物的某些性质描述。n四色原型中的蓝色des直接对应值对象。n将所有对象都加上标识,会影响系统的性能,增加复杂性,使所有

28、对象看上去都是一个模式,混乱。n只关心what,不关心who 或 which,只关心对象是什么?如果有多个这样对象排列在一起,我们不用去分辨它们。n只关心what:有两只相同颜色和粗细的笔,随便拿一个都可以画画。地址值对象n邮购软件中的地址是值对象:用地址作为发货目的地。如果住在一起多个室友邮购,不影响邮递,有名字作为标识。n邮政软件中的地址是实体:将地区分层次结构,区 城市 街道 邮编 个人地址。n电力运营软件中地址是实体:如果住在一起多个室友申请电力服务,电力公司必须区分。值对象和实体是整体值对象设计n由于不关心软件运行时使用的是值对象的哪个实例,没有了分辨拘束,可提升性能和优化。n值对象

29、复制性:两个人具有相同名字,表示名字的值对象可以互换复制,不会使他们成为一个人。n值对象共享性:两个Person对象不需要自己各自的Name值对象,可以共用一个Name值对象。n值对象不变性:值对象属于实体,当实体把它的值对象传递给其他对象时,如果其他对象对这个传过来的值对象修改不当,就会破坏其所有者的不变性约束,从而破坏它的所有者实体对象。值对象共享n值对象非常巨大,每个电源插座都是一个值对象,一个房子有上百个插座对象,由于值对象可以互换 共享,只使用一个插座实例就可以。nFlyweight模式:避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类)。n不适用于实体。值对象

30、复制nPrototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节。nJava的clone也是一种复制。n复制产生大量对象会阻塞系统,但适合在分布式系统中,相反,使用共享,会降低性能;n高并发系统中,复制减少锁处理,共享需要精妙的锁处理技巧。实体和值对象区分n区分实体和值对象有助于我们在分析需求时抓住重点(实体),有主次之分,纲举目张。n由于关注重点不同,就会对值对象定义不同。n消费拿起一瓶牛奶喝,这时我们关注的是他喝牛奶之外一些重点,至于选择哪个牛奶瓶不是我们关注重点,随便哪一个都行,这是值对象。n对于牛奶生产商而言,每瓶牛奶都很重要,生产日期有效期等等,因此

31、,这里牛奶瓶就成了实体。帖子的值对象nMessage是一个实体,有一个明显标识,每次都要区分是哪个帖子。n帖子中标题 内容等是每个帖子都有的Description,属于值描述,因此有必要将标题 内容抽象出来作为值对象。思考n论坛系统中,每个论坛有很多帖子,每个帖子后面有很多回复贴。n两个主要类模型Forum和Messag。类似订单有两个Order和Product模型。n是不是将Forum和Messag直接发生关联?n根据关联精炼限制原则,其实回复贴Message和Forum关联不是很紧,回复贴的聚合根应该是根贴(整体部分关系),存在精简余地。n两个问题:哪个是实体和值对象?关联是否是聚合?模型

32、关联的实现n模型中关联在软件中都有一种机制对应。n关联1.*和0.*Java 使用某种集合类,1.*”多重性,Java程序必须确保集合至少包含一项内容 聚合代表一个类是另一个类的一部份这种关系。全体-部分 箭头由表示whole的类指向表示part的类 模型之间关联尽可能使用聚合表达关联要点n关联要反映最本质的关系。如学生 课程 车和马达。关联不是手头任务本质或不能反映模型对象基本含义,完全取消它。n现实世界中存在大量双向多对多关联关系,双向关联和实现和维护带来很大困难,双向关联极少将联系本质体现出来,少用双向关联。n尽可能约束关联,通过指定导航方向,减少不必要关联。n模型中关联越少、越简单越好

33、。指定导航限定导航 1:N 1:1关联精炼 1:N关联精炼后的1:1关联高内聚低关联n高内聚低关联是设计基本原则。是重构的准则。n找出关联是细分模型的一种方式,从而更恰当地定义模型边界。n关联不是手头任务本质或不能反映模型对象基本含义,完全取消它。n少用双向关联,除非技术性能要求。n模型中关联越少、越简单越好。n完全摆脱数据库影子,SQL语句作为规则封装在模型中。再思考nForum直接和Message发生关联不够精细,回复贴就和Forum没有聚合,不是整体部分关系,它的整体聚合根是根贴,根贴可直接和Message发生关联。n将Message使用抽象继承建模,落实为两个子类:根贴和回复贴。nFo

34、rum不能直接和Message继承模型耦合,否则继承模型一旦变动,影响Forum。n引入集合容器概念Thread,一个根贴和它一系列回帖组成一个Thread。增加ThreadThread是实体还是值对象?n实体和值对象主要区别是否有标识ID,这个ID不是数据表ID,而是一个更高抽象概念,代表是否需要分辨它的意思。n区分实体和值对象主要作用是主次之分,如果你认为它很重要,它可以从此要的值对象上升为实体。n用户找到Forum后,是否需要根据Thread再找Message?如果是,Thread应该是实体;如果不是,Thread可以隐藏在根贴Message后面做值对象。鸡头 or 凤尾?n由于当初引入

35、Thread的目的是让Forum不直接和Message复杂内部树形结构发生耦合,所以,Thread必须发挥这个中间者的作用。nThread应该被看成实体。n如果Thread是值对象,Thread作为帖子集合容器与外界松耦合的作用就失去,同理可以推广到:Order-OrderLine-Product领域对象生命周期重视生命周期n对一个对象修改操作,是否会引发对象关联网中其他对象的变化?n多个客户端并发访问一个对象,必须提供保护如锁操作,防止相互依赖的对象被同时修改。如果保护范围错了,后果很严重。n如何在性能和事务上做到平衡,最好解决方式是对领域理解深刻,了解某些类的实例修改频率如何?让它远离高并

36、发访问,串行化与并行计算。n数据库事务ACID事务棘手实际是我们的模型不清晰。聚合Aggregaten一个聚合是一簇相关联的对象,出于数据变化的目的,将这些对象视为一个单元。n每个聚合都有一个根和一个边界。n边界定义了聚合中应该包含什么。n根是包含在聚合中的单个特定实体。n根是聚合中唯一允许被外部引用的元素,在聚合边界内,对象之间可以相互引用。n实际就是整体和部分的关系。轿车根聚合中的不变性n不变性Invariants定义:无论何时数据发生变化,都必须满足所有一致变化的规则,俗话:同生死。n聚合内部的不变量必须在每次事务完成时满足。这可有仓储来实现。n一些依赖关系只能在某些特定的时刻 通过事件

37、借助有事务支持的服务来完成,或通过线程安全模式实现原子操作。如何做到不变性n根实体具有全局标识,并最终负责对不变量的检查。n根实体有全局标识,而边界之内实体有本地标识,这些标识仅在聚合内部是唯一的。n聚合边界外任何对象除了可以引用根实体,不能持有任何对其内部对象的引用。根实体可以把内部其他实体引用传递给其他对象,只能临时使用。n根实体可以复制内部一个值对象实例副本给外部另外一个对象,副本再也与聚合无关系了。CRUD中不变性约束n通过数据库查询直接获得的对象只有聚合的根,其他所有聚合内对象可以通过聚合关系找到,性能上可采取懒加载防止大对象。n删除必须一次性删除聚合边界内所有对象。n当在聚合边界内

38、发生的任何对象修改被提交时,整个聚合的所有不变量必须被满足,也就是统一修改。聚合根和不变性采购订单订单不变量约束n所以采购单项的金额之和不得超过采购单的最高限额。n不变量保证:当加入新子项时,PO对总金额检查,如果不对,把自己标记非法,不好。n变更管理:删除PO时,子项同时删除,但是它们关联关系何时终止,模型没有指示。不同时间修改商品价格会造成哪些影响无法评估。n并发共享:如何解决多个用户同时修改一个PO?并发锁粒度n如果多个用户同时修改一个PO,我们必须对这个PO实例锁定,以让某个时刻只能一个用户修改。n通过数据库锁机制或者使用线程锁机制实现,关键是锁PO整个实例带来问题,这种锁排他性的,就

39、无法允许其他用户也许对PO其他部分进行访问,性能差。n更改模型,根据修改频繁程度单独列出一个对象,比如Price经常修改,就成为Price对象,锁定Price这个小对象,无需锁定整个PO。新订单模型案例 找出聚合根n在初步确定了Forum Thread和Message模型类之后,我们需要对这些模型内部进行细化。n在细化类字段和关联关系时,我们要遵守找出高聚合根这个宗旨。n根贴的一系列回帖,组成聚合的边界,那么谁是聚合根实体?nRootMessage好像是聚合根,但是因为Thread是整个聚合体的实体代表,用Thread作为聚合根比RootMessage更确切,Thread类Car。案例 划出不

40、变性n在考察Forum的各个字段时,有几个字段是可能因为用户发帖而经常频繁变化,表示当前论坛状态的字段:最新贴lastPost 帖子总数ThreadCount等。nlastPost和ThreadCount不同name等其他本质固有属性,他们修改变化的周期和name等是不一致的,发一个新贴不代表就要修改论坛名称,但是要修改lastPost和ThreadCount。n创建一个ForumState类来封装变化的lastPost和ThreadCount。可变部分聚合根和不变性论坛的不变性划分不变性的实现方式n在生命周期中维护对象的完整性。避免模型由于管理生命周期的复杂性而陷入困境。n三个模式来处理:n

41、 1.聚合(Aggregate):定义清晰的所有权和边界使模型更加紧凑,避免出现盘根错节的对象关系网。聚合圈出一个范围,在这个范围中,对象无论在哪个生命周期,保持不变性。n 2.工厂(Factory)n 3.组合(Respository)n 生命周期之始,使用工厂和组合提供了访问和控制模型对象的方法生命周期边界和管理n聚合圈出一个范围如前图中红线,在这个范围中,对象无论在哪个生命周期,保持不变性。也就是子对象和父对象的生命周期是一致不变的。n建立聚合的模型,并且把工厂和组合加入设计中来,可以使我们系统地对模型对象生命周期进行管理。n生命周期之始,使用工厂和Repository提供了访问和控制模

42、型对象的方法。工厂n生命周期管理具有复杂的职责,如果让一个复杂对象来负责自身的创建工作,会由于职责过载产生问题,人不能拎着自己头发拔高,孙猴子也是从石头缝里出来的,不是从自己身体钻出来的。n复杂对象的创建和组装应该由单独工厂实现,也就是工厂模式。将对象创建和使用分离。n工厂属于领域层,工厂把聚合作为一个整体创建出来,创建方法必须是原子的,保证其不变量得到满足。对象内工厂n在一个领域对象内,如果希望向一个已有的聚合中加入元素,可以在聚合根中创建一个工厂方法,既隐把聚合内部实现向外部客户隐藏起来,聚合根保证在元素加入后的完整性。Thread内工厂n前面讨论了Thread作为一系列帖子的聚合根,那么

43、如果增加新的帖子,通过Thread内置的工厂来实现,synchronized保证原子性:npublic synchronized void addNewMessage(.)n state.addMessageCount();n state.getTreeModel().addChild(.);n state.setLastPost(forumMessageReply);n state.setModifiedDate(forumMessageReply.getModifiedDate();n forum.addNewMessage(forumMessageReply);n专门工厂创建聚合n如果聚

44、合根需要一个工厂创建,又不适合充当工厂,也就是没有一个自然地方容纳工厂,那么就创建一个专门的工厂对象或服务。实体和值对象工厂n值对象具有不变性,一旦声场创建就是最终状态,工厂必须将其完整的创建出来。n实体工厂只要求构造一个有效聚合所需要的那些本质属性即可,注意是本质固有属性,只要保证不变性就可以,其他不变性没有要求的可在以后追加。存储对象重建n内存是对象的正常活动空间,但是对象通常要保存到数据库或网络输出,会将对象压扁,需要一个复杂过程才能把压扁各个部分恢复为活的正常对象。n用工厂重建对象,标识ID必须成为输入参数。n从数据库中重建对象保持不变性难度加大。Repository由来n数据库只是对

45、象的永久保存方式,就象我们打字时经常需要存盘一样,我们不能因为要“存盘”而去关心“存盘文件格式(数据表结构)”。n我们应该更聚焦在模型这个对象,把所有对象的保存(冬眠)和调用(激活)交由Respository完成。n对象保存到数据库交由专门的Repository仓储来完成,由Repository负责如何将对象分解成数据库能够保存的格式。JiveJdon的工厂nThread和RootMessage实体模型对象的获得都是从专门的ThreadDirector和ThreadBuilder 创建出来的。(讲解具体代码)n如果使用Hibernate这样O/R Mapping框架,由Hibernate完成对

46、象创建和组合。n无论什么实现方式,从持久层输出到业务层的都必须是对象,这是OO设计基本原则,可以保证在业务层不能访问到数据表,只是对象。创建原子性n每个操作必须是原子性的,要么全部完成,要么一个都不完成。npublic ForumThread getThread()throws Exception n ForumThread forumThread=(ForumThread)forumThreadBuilder.create(threadId);n if(forumThread=null)return null;n if(forumThread.isEmbedded()/确保构建是一次性n r

47、eturn forumThread;n /开始构建方法,这里开始必须是原子性n construct(forumThread,rootForumMessage,forum);n forumThread.setEmbedded(true);n return forumThread;nn思考:如果有多余两个用户以上开始执行构建方法,如何保证他们构建出来的Thread是同一个呢?如何确保原子性n如果在构建方法这里加入synchronized,将导致构建所有Thread都只有一个线程,这不是我们本意,我们本意是构建某个Thread实例时,只能有一个线程。否则导致性能降低,多用户系统变成单用户系统。nfo

48、rumThreadBuilder.create(threadId);实际是从缓存中获取一个Thread(缓存中没有就从数据库构建),而在缓存操作某个Thread时,是一个同步操作,这样将锁粒度降低到最接近要求。Thread构建n在Thread的construct方法中,我们必须构建聚合边界元素。nThread为聚合根,其下有RootMessage以及一系列回帖,如何表达这种聚合结构呢?n帖子与回帖之间结构是一种树形结构,我们可以用树形结构来表达。n建立一个TreeModel对象,封装了帖子之间的父子结构,当然只是ID,不是完整帖子。Thread构建代码n/构建Thread自身固有本质属性 名称

49、等nforumThreadBuilder.buildProperties(forumThread);n/构建聚合边界,树形结构nforumThreadBuilder.buildTreeModel(forumThread);n/建立真正树形结构根元素根贴nforumThreadBuilder.buildRootMessage();n/建立与Forum的关联。nforumThreadBuilder.buildForum(.);n/建立Thread状态,状态是对象本质属性,有对象就有状态。nforumThreadBuilder.buildState(.);对象和数据库n数据库查询是全局的,可以直接想

50、得到想要的对象,但对象内部的聚合不变性就会被破坏。n对象网是通过对象关联来管理的,但我们不需要把所有对象连接起来。n是使用导航限制连接,然后先找出聚合根,再根据根的限制导航找出结果?还是使用查询,直接查询我们要得到的结果?nCustomer与Order,是设计为关联,还是通过CustomerId把Order从数据库中查询筛选出来?数据库编程思路n很多开发人员更喜欢使用SQL,对如何从数据库抓取他们想要的对象感兴。n业务逻辑都跑到SQL代码或客户端代码中去,而实体和值对象变成了纯粹数据容器。n大部分数据库访问计数复杂性,如数据库范式,很快使得代码陷入混乱,只好抛开领域层,模型成了摆设。n另外一个

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 教案示例

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁