zoukankan      html  css  js  c++  java
  • 从零开始学领域驱动设计(二)

    如何识别聚合?

    我觉得这个需要从业务的角度深入分析哪些对象它们的关系是内聚的,即我们会把他们看成是一个整体来考虑的;然后这些对象我们就可以把它们放在一个聚合内。所谓关系是内聚的,是指这些对象之间必须保持一个固定规则,固定规则是指在数据变化时必须保持不变的一致性规则。当我们在修改一个聚合时,我们必须在事务级别确保整个聚合内的所有对象满足这个固定规则。作为一条建议,聚合尽量不要太大,否则即便能够做到在事务级别保持聚合的业务规则完整性,也可能会带来一定的性能问题。有分析报告显示,通常在大部分领域模型中,有70%的聚合通常只有一个实体,即聚合根,该实体内部没有包含其他实体,只包含一些值对象;另外30%的聚合中,基本上也只包含两到三个实体。这意味着大部分的聚合都只是一个实体,该实体同时也是聚合根。

    如何识别聚合根?

    如果一个聚合只有一个实体,那么这个实体就是聚合根;如果有多个实体,那么我们可以思考聚合内哪个对象有独立存在的意义并且可以和外部直接进行交互

    CQRS架构

    核心思想是将应用程序的查询部分和命令部分完全分离,这两部分可以用完全不同的模型和技术去实现。比如命令部分可以通过领域驱动设计来实现;查询部分可以直接用最快的非面向对象的方式去实现,比如用SQL。这样的思想有很多好处:

    1. 实现命令部分的领域模型不用经常为了领域对象可能会被如何查询而做一些折中处理;
    2. 由于命令和查询是完全分离的,所以这两部分可以用不同的技术架构实现,包括数据库设计都可以分开设计,每一部分可以充分发挥其长处;
    3. 高性能,命令端因为没有返回值,可以像消息队列一样接受命令,放在队列中,慢慢处理;处理完后,可以通过异步的方式通知查询端,这样查询端可以做数据同步的处理;

    Event Sourcing(事件溯源)

    对于DDD中的聚合,不保存聚合的当前状态,而是保存对象上所发生的每个事件。当要重建一个聚合对象时,可以通过回溯这些事件(即让这些事件重新发生)来让对象恢复到某个特定的状态;因为有时一个聚合可能会发生很多事件,所以如果每次要在重建对象时都从头回溯事件,会导致性能低下,所以我们会在一定时候为聚合创建一个快照。这样,我们就可以基于某个快照开始创建聚合对象了。

    DCI架构

    DCI架构强调,软件应该真实的模拟现实生活中对象的交互方式,代码应该准确朴实的反映用户的心智模型。在DCI中有:数据模型、角色模型、以及上下文这三个概念。数据模型表示程序的结构,目前我们所理解的DDD中的领域模型可以很好的表示数据模型;角色模型表示数据如何交互,一个角色定义了某个“身份”所具有的交互行为;上下文对应业务场景,用于实现业务用例,注意是业务用例而不是系统用例,业务用例只与业务相关;软件运行时,根据用户的操作,系统创建相应的场景,并把相关的数据对象作为场景参与者传递给场景,然后场景知道该为每个对象赋予什么角色,当对象被赋予某个角色后就真正成为有交互能力的对象,然后与其他对象进行交互;这个过程与现实生活中我们所理解的对象是一致的;

    DCI的这种思想与DDD中的领域服务所做的事情是一样的,但实现的角度有些不同。DDD中的领域服务被创建的出发点是当一些职责不太适合放在任何一个领域对象上时,这个职责往往对应领域中的某个活动或转换过程,此时我们应该考虑将其放在一个服务中。比如资金转帐的例子,我们应该提供一个资金转帐的服务,用来对应领域中的资金转帐这个领域概念。但是领域服务内部做的事情是协调多个领域对象完成一件事情。因此,在DDD中的领域服务在协调领域对象做事情时,领域对象往往是处于一个被动的地位,领域服务通知每个对象要求其做自己能做的事情,这样就行了。这个过程中我们似乎看不到对象之间交互的意思,因为整个过程都是由领域服务以面向过程的思维去实现了。而DCI则通用引入角色,赋予角色以交互能力,然后让角色之间进行交互,从而可以让我们看到对象与对象之间交互的过程。但前提是,对象之间确实是在交互。因为现实生活中并不是所有的对象在做交互,比如有A、B、C三个对象,A通知B做事情,A通知C做事情,此时可以认为A和B,A和C之间是在交互,但是B和C之间没有交互。所以我们需要分清这种情况。资金转帐的例子,A相当于转帐服务,B相当于帐号1,C相当于帐号2。因此,资金转帐这个业务场景,用领域服务比较自然。有人认为DCI可以替换DDD中的领域服务,我持怀疑态度。

    四色原型分析模式

    时刻-时间段原型(Moment-Interval Archetype)

    表示在某个时刻或某一段时间内发生的某个活动。使用粉红色表示,简写为MI。

    参与方-地点-物品原型(Part-Place-Thing Archetype)

    表示参与某个活动的人或物,地点则是活动的发生地。使用绿色表示。简写为PPT。

    描述原型(Description Archetype)

    表示对PPT的本质描述。它不是PPT的分类!Description是从PPT抽象出来的不变的共性的属性的集合。使用蓝色表示,简写为DESC。

    举个例子,有一个人叫张三,如果某个外星人问你张三是什么?你会怎么说?可能会说,张三是个人,但是外星人不知道“人”是什么。然后你会怎么办?你就会说:张三是个由一个头、两只手、两只脚,以及一个身体组成的客观存在。虽然这时外星人仍然不知道人是什么,但我已经可以借用这个例子向大家说明什么是“Description”了。在这个例子中,张三就是一个PPT,而“由一个头、两只手、两只脚,以及一个身体组成的客观存在”就是对张三的Description,头、手、脚、身体则是人的本质的不变的共性的属性的集合。但我们人类比较聪明,很会抽象总结和命名,已经把这个Description用一个字来代替了,那就是“人”。所以就有所谓的张三是人的说法。

    角色原型(Role Archetype)

    角色就是我们平时所理解的“身份”。使用黄色表示,简写为Role。为什么会有角色这个概念?因为有些活动,只允许具有特定角色(身份)的PPT(参与者)才能参与该活动。比如一个人只有具有教师的角色才能上课(一种活动);一个人只有是一个合法公民才能参与选举和被选举;但是有些活动也是不需要角色的,比如一个人不需要具备任何角色就可以睡觉(一种活动)。当然,其实说人不需要角色就能睡觉也是错误的,错在哪里?因为我们可以这样理解:一个客观存在只要具有“人”的角色就能睡觉,其实这时候,我们已经把DESC当作角色来看待了。所以,其实角色这个概念是非常广的,不能用我们平时所理解的狭义的“身份”来理解,因为“教师”、“合法公民”、“人”都可以被作为角色来看待。因此,应该这样说:任何一个活动,都需要具有一定角色的参与者才能参与。

    用一句话来概括四色原型就是:一个什么什么样的人或组织或物品以某种角色在某个时刻或某段时间内参与某个活动。 其中“什么什么样的”就是DESC,“人或组织或物品”就是PPT,“角色”就是Role,而”某个时刻或某段时间内的某个活动"就是MI。

    以上这些东西如果在学习了DDD之后再去学习会对DDD有更深入的了解,但我觉得DDD相对比较基础,如果我们在已经了解了DDD的基础之上再去学习这些东西会更加有效和容易掌握。

  • 相关阅读:
    ABAP开发常见任务
    sap smartform 打印乱码问题
    根据T-Code查看用户出口的代码
    java 调用SAP RFC函数错误信息
    代码单行超过72个字符的一个异常
    SAP 权限层次
    标准屏幕字段描述修改
    [转]SAP一句话入门SD模块
    Python3.7,os模块
    Python3,逻辑运算符
  • 原文地址:https://www.cnblogs.com/zhangfengshi/p/10000447.html
Copyright © 2011-2022 走看看