2004年Eric Evans 发表Domain-Driven Design –Tackling Complexity in the Heart of Software (领域驱动设计),简称Evans DDD。领域驱动设计分为两个阶段:

以一种领域专家、设计人员、开发人员都能理解的通用语言作为相互交流的工具,在交流的过程中发现领域概念,然后将这些概念设计成一个领域模型;

由领域模型驱动软件设计,用代码来实现该领域模型;领域驱动设计的核心是建立正确的领域模型。

领域驱动设计的经典分层架构

用户界面/展现层

负责向用户展现信息以及解释用户命令。更细的方面来讲就是:

请求应用层以获取用户所需要展现的数据;

发送命令给应用层要求其执行某个用户命令;

应用层

很薄的一层,定义软件要完成的所有任务。对外为展现层提供各种应用功能(包括查询或命令),对内调用领域层(领域对象或领域服务)完成各种业务逻辑,应用层不包含业务逻辑。

领域层

负责表达业务概念,业务状态信息以及业务规则,领域模型处于这一层,是业务软件的核心。

基础设施层

本层为其他层提供通用的技术能力;提供了层间的通信;为领域层实现持久化机制;总之,基础设施层可以通过架构和框架来支持其他层的技术需求;

领域驱动设计过程中使用的模式

关联的设计

关联本身不是一个模式,但它在领域建模的过程中非常重要,所以需要在探讨各种模式之前,先讨论一下对象之间的关联该如何设计。我觉得对象的关联的设计可以遵循如下的一些原则:

关联尽量少,对象之间的复杂的关联容易形成对象的关系网,这样对于我们理解和维护单个对象很不利,同时也很难划分对象与对象之间的边界;另外,同时减少关联有助于简化对象之间的遍历;

对多的关联也许在业务上是很自然的,通常我们会用一个集合来表示1对多的关系。但我们往往也需要考虑到性能问题,尤其是当集合内元素非常多的时候,此时往往需要通过单独查询来获取关联的集合信息;

关联尽量保持单向的关联;

在建立关联时,我们需要深入去挖掘是否存在关联的限制条件,如果存在,那么最好把这个限制条件加到这个关联上;往往这样的限制条件能将关联化繁为简,即可以将多对多简化为1对多,或将1对多简化为1对1;

实体(Entity)

实体就是领域中需要唯一标识的领域概念。因为我们有时需要区分是哪个实体。有两个实体,如果唯一标识不一样,那么即便实体的其他所有属性都一样,我们也认为他们两个不同的实体;因为实体有生命周期,实体从被创建后可能会被持久化到数据库,然后某个时候又会被取出来。所以,如果我们不为实体定义一种可以唯一区分的标识,那我们就无法区分到底是这个实体还是哪个实体。另外,不应该给实体定义太多的属性或行为,而应该寻找关联,发现其他一些实体或值对象,将属性或行为转移到其他关联的实体或值对象上。比如Customer实体,他有一些地址信息,由于地址信息是一个完整的有业务含义的概念,所以,我们可以定义一个Address对象,然后把Customer的地址相关的信息转移到Address对象上。如果没有Address对象,而把这些地址信息直接放在Customer对象上,并且如果对于一些其他的类似Address的信息也都直接放在Customer上,会导致Customer对象很混乱,结构不清晰,最终导致它难以维护和理解;

值对象(Value Object)

在领域中,并不是没一个事物都必须有一个唯一标识,也就是说我们不关心对象是哪个,而只关心对象是什么。就以上面的地址对象Address为例,如果有两个Customer的地址信息是一样的,我们就会认为这两个Customer的地址是同一个。也就是说只要地址信息一样,我们就认为是同一个地址。用程序的方式来表达就是,如果两个对象的所有的属性的值都相同我们会认为它们是同一个对象的话,那么我们就可以把这种对象设计为值对象。因此,值对象没有唯一标识,这是它和实体的最大不同。另外值对象在判断是否是同一个对象时是通过它们的所有属性是否相同,如果相同则认为是同一个值对象;而我们在区分是否是同一个实体时,只看实体的唯一标识是否相同,而不管实体的属性是否相同;值对象另外一个明显的特征是不可变,即所有属性都是只读的。因为属性是只读的,所以可以被安全的共享;当共享值对象时,一般有复制和共享两种做法,具体采用哪种做法还要根据实际情况而定;另外,我们应该给值对象设计的尽量简单,不要让它引用很多其他的对象,因为他只是一个值,就像int a = 3;那么”3”就是一个我们传统意义上所说的值,而值对象其实也可以和这里的”3”一样理解,也是一个值,只不过是用对象来表示。所以,当我们在C#语言中比较两个值对象是否相等时,会重写GetHashCode和Equals这两个方法,目的就是为了比较对象的值;值对象虽然是只读的,但是可以被整个替换掉。就像你把a的值修改为”4”(a = 4;)一样,直接把”3”这个值替换为”4”了。值对象也是一样,当你要修改Customer的Address对象引用时,不是通过Customer.Address.Street这样的方式来实现,因为值对象是只读的,它是一个完整的不可分割的整体。我们可以这样做:Customer.Address = new Address(…);

领域服务(Domain Service)

领域中的一些概念不太适合建模为对象,即归类到实体对象或值对象,因为它们本质上就是一些操作,一些动作,而不是事物。这些操作或动作往往会涉及到多个领域对象,并且需要协调这些领域对象共同完成这个操作或动作。如果强行将这些操作职责分配给任何一个对象,则被分配的对象就是承担一些不该承担的职责,从而会导致对象的职责不明确很混乱。但是基于类的面向对象语言规定任何属性或行为都必须放在对象里面。所以我们需要寻找一种新的模式来表示这种跨多个对象的操作,DDD认为服务是一个很自然的范式用来对应这种跨多个对象的操作,所以就有了领域服务这个模式。和领域对象不同,领域服务是以动词开头来命名的,比如资金转帐服务可以命名为MoneyTransferService。当然,你也可以把服务理解为一个对象,但这和一般意义上的对象有些区别。因为一般的领域对象都是有状态和行为的,而领域服务没有状态只有行为。需要强调的是领域服务是无状态的,它存在的意义就是协调领域对象共完成某个操作,所有的状态还是都保存在相应的领域对象中。我觉得模型(实体)与服务(场景)是对领域的一种划分,模型关注领域的个体行为,场景关注领域的群体行为,模型关注领域的静态结构,场景关注领域的动态功能。这也符合了现实中出现的各种现象,有动有静,有独立有协作。

领域服务还有一个很重要的功能就是可以避免领域逻辑泄露到应用层。因为如果没有领域服务,那么应用层会直接调用领域对象完成本该是属于领域服务该做的操作,这样一来,领域层可能会把一部分领域知识泄露到应用层。因为应用层需要了解每个领域对象的业务功能,具有哪些信息,以及它可能会与哪些其他领域对象交互,怎么交互等一系列领域知识。因此,引入领域服务可以有效的防治领域层的逻辑泄露到应用层。对于应用层来说,从可理解的角度来讲,通过调用领域服务提供的简单易懂但意义明确的接口肯定也要比直接操纵领域对象容易的多。这里似乎也看到了领域服务具有Façade的功能,呵呵。

说到领域服务,还需要提一下软件中一般有三种服务:应用层服务、领域服务、基础服务。

应用层服务

获取输入(如一个XML请求);

发送消息给领域层服务,要求其实现转帐的业务逻辑;

领域层服务处理成功,则调用基础层服务发送Email通知;

领域层服务

获取源帐号和目标帐号,分别通知源帐号和目标帐号进行扣除金额和增加金额的操作;

提供返回结果给应用层;

基础层服务

按照应用层的请求,发送Email通知;

所以,从上面的例子中可以清晰的看出,每种服务的职责;

聚合及聚合根(Aggregate,Aggregate Root)

聚合,它通过定义对象之间清晰的所属关系和边界来实现领域模型的内聚,并避免了错综复杂的难以维护的对象关系网的形成。聚合定义了一组具有内聚关系的相关对象的集合,我们把聚合看作是一个修改数据的单元。

python领域驱动_DDD领域驱动设计学习初探相关推荐

  1. 领域驱动设计学习之路—DDD的原则与实践

    本文是我学习Scott Millett & Nick Tune编著的<领域驱动设计模式.原理与实践>一书的学习笔记,一共会分为4个部分如下,此文为第1部分: 领域驱动设计的原则与实 ...

  2. 领域驱动设计学习心得

    领域驱动设计(Domain Driven Design,简称 DDD),是设计方法之一,可以针对开发领域,当然也可能用于其他领域. 领域驱动设计的过程,就是建立起通用语言和识别模型的过程. 但我只看懂 ...

  3. 架构之路_DDD领域驱动设计总结

    推荐书籍:领域驱动设计 - 软件核心复杂性应对之道 - Eric Evans. 视频教程:DDD 微服务落地实战视频教程 一.DDD基础名词概念 领域驱动设计(DDD),它是针对复杂系统设计的一套整软 ...

  4. 《领域驱动设计》:从领域视角深入仓储的设计和实现

    一 前言 " DDD设计的目标是关注领域模型而并非技术来创建更好的软件,假设开发人员构建了一个SQL,并将它传递给基础设施层中的某个查询服务然后根据表数据的结构集取出所需信息,最后将这些信息 ...

  5. 领域驱动系列五模型驱动设计的构造块

    一.简介 为了保证软件实现的简洁性,并且与模型保持一致,不管实际情况有多复杂,必须使用建模和设计的最佳实践,即让通过我们的编程技术(设计模型.指责驱动.契约式设计)充分地体现领域模型,并保持模型地健壮 ...

  6. 领域驱动设计(DDD)实践之路(四):领域驱动在微服务设计中的应用

    这是"领域驱动设计实践之路"系列的第四篇文章,从单体架构的弊端引入微服务,结合领域驱动的概念介绍了如何做微服务划分.设计领域模型并展示了整体的微服务化的系统架构设计.结合分层架构. ...

  7. 如何正确入门Windows系统下驱动开发领域?

    [作者] 猪头三 作者网站: http://www.x86asm.com 原文链接: http://blog.csdn.net/Code_GodFather/...0/5975901.aspx [贡献 ...

  8. 食品机械广泛应用于橡胶纳米技术驱动的领域 - 纳米,食品机械,橡胶 -

    食品机械广泛应用于橡胶纳米技术驱动的领域 - 纳米,食品机械,橡胶 - 纳米技术基因工程变得更加可控,可以根据自己的需要,创造一个品种繁多,容易纳米生物吸收,"产品",农,林,牧, ...

  9. 《预训练周刊》第25期:HyperCLOVA:数十亿级韩语生成式预训练变换器、GPT-3在生物医学领域不是好的小样本学习器...

    No.25 智源社区 预训练组 预 训 练 研究 观点 资源 活动 关于周刊 超大规模预训练模型是当前人工智能领域研究的热点,为了帮助研究与工程人员了解这一领域的进展和资讯,智源社区整理了第25期&l ...

  10. 下一个AI领域的高薪方向:强化学习与智能决策研究班2023年春季招生启事

     世界繁花盛开 我们不必在同一个地方反复死磕  强化学习是最近5年来人工智能最令人激动的研究领域.如下图Google的搜索指数可以看到,强化学习的搜索指数最近一些年明显呈现增长趋势,而NLP(自然语言 ...

最新文章

  1. 深度图像分割 -- Fully Convolutional Networks for Semantic Segmentation
  2. ES6新特性(函数默认参数,箭头函数)
  3. Asp.net HttpClient Proxy(Fiddler)
  4. 云信小课堂|5分钟快速实现安卓端PK连麦场景
  5. 每天学一点flash(70)弹出和关闭窗口
  6. 虚拟机usb无线上网同时主机本地上网或无线无线上网
  7. 理解Angular的Reactive Form
  8. UcOS-II 和linux比较
  9. 实现百战铁路售票系统临时车次的添加功能
  10. win7怎么在计算机找文件夹选项,解决WIN7工具菜单没有文件夹选项/文件夹和搜索选项变灰色...
  11. 俄罗斯一法院对谷歌处以72亿卢布罚款
  12. 如何解决oracle中文乱码问题,oracle中解决中文乱码问题
  13. 硬盘数据丢失如何恢复?
  14. 【这很AI】谷歌再推AI应用“名画匹配”:与博物馆7万幅历史名画匹配,结果可能是梵高
  15. 小程序云开发,CMS内容管理系统
  16. NOIP 2018 滚粗记(bushi)
  17. Linux Ubuntu18.04系统 USB转串口驱动安装,查看串口号
  18. 趣店季报图解:营收环比降14% 大白汽车收入近6亿
  19. Oracle的冷备份与热备份
  20. 转 | 禁忌搜索算法(Tabu Search)求解带时间窗的车辆路径规划问题详解(附Java代码)

热门文章

  1. 孙玄:构建企业级业务高可用的延时消息中台
  2. cs61b-Java数据结构(一)autograder配置
  3. Springboot 整合CXF框架
  4. FPGA的软件下载(百度盘~)
  5. 微型计算机原理与接口技术(慕课版),微机原理与接口技术
  6. 数据挖掘算法之Apriori算法应用实例
  7. 单片机技术与c语言编程教学大纲,单片机原理及应用课程教学大纲
  8. ISO-9001质量管理体系认证经验分享
  9. 实现WEB打印的几种方法
  10. VS2010 下载与安装