vlambda博客
学习文章列表

领域驱动设计(二)模型驱动设计的构造块

上一篇我们聊了如何在项目中开始运用领域模型,我们回顾下运用领域模型的核心其实就是是建立基于模型的通用语言(UBIQUITOUT LANAGUAGE)。本篇的标题是模型驱动设计的构造块,这也是《领域驱动设计-软件核心复杂性应对之道》这本书的第二部分的主题。那到底是什么意思呢,看完了第二部分,我的理解就是如何用一套可复制的方法或标准去协助我们构造驱动模型。如下图就是核心构造块,我们分别来具体说说。

分离领域

其实我理解的分离领域是在一个庞大的系统中,如何去进行职责划分,将不同的业务逻辑分出清晰的边界来。不过书中所讲的分离领域更多的是从软件架构层面去考虑的,指的是将领域实现从软件的其他部分里面分离出来,这样可以专注于领域的设计,而不用被其他的边界外的内容干扰而扰乱整个系统的设计。所以在书中谈到了领域驱动设计实现中的架构模式:LAYERED ARCHITECTURE也就是分层架构。对于分层架构,想必不用多做解释,搞开发的童鞋都非常熟悉。那么领域驱动设计的分层架构有什么不同呢?我们来看一下。

如上图,在领域设计的项目中,我们常常会把整个系统分为4层,那么领域层是核心。我们要重点说的也就是领域层的设计实现。在设计领域层的时候,我们应该忽略其他层,假设其他层的能力都已经具备。那么领域层要如何设计和构造呢?

软件中所表示的模型(领域常用模式)

之所以是软件中的模型,是因为这部分要讲的领域常用模式构造块其实在一般软件中都是适用的,领域模型建立的范式是符合软件设计的基本原则的。

ENTITY:我们在开发中常常也会用ENTITY这个名词,那你理解的ENTITY是什么呢?最初我的理解所有关系数据库的表映射的对象类,我都称之为实体ENTITY。那么在领域模型设计中,ENTITY指的是具体的实例,每个实例都是唯一的,ENTITY必须有唯一标识。比如:人力资源系统中的员工就是ENTITY。

VALUE OBJECT:用于描述领域的某个方面而本身没有概念标识的对象称为VALUE OBJECT(值对象)。VALUE OBJECT被实例化之后用来表示一些设计元素,对于这些设计元素,我们只关心它们是什么,而不关心它们是谁。比如:企业所在区域,调色程序的颜色都是VELUE OBJECT。

SERVICE:有时,对象不是一个事物。在某些情况下,最清楚、最实用的设计会包含一些特殊的操作,这些操作从概念上讲不属于 任何对象。与其把它们强制地归于哪一类,不如顺其自然地在模型中引入一种新的元素,这就是 SERVICE(服务)。

MODULE:如果说模型讲述了一个故事,那么MODULE就是这个故事的各个章节。模块的名称表达了其意义。这些名称应该被添加到UBIQUITOUS LANGUAGE中。但是要注意模块的划分不能过于离散,比如说不要从操作或者分类的不同就划分不同的MODULE。除非真正有必要将代码分布到不同的服务器上,否则就把实现单一概念对象的所有代码放在同一个模块中(如果不能放在同一个对象中的话)。

领域对象的生命周期

由于领域对象的设计常用的范式就是面向对象设计,所以在对象类的设计上和面向对象的概念和思想基本是一致的。对象的生命周期就说到关于的对象的创建到删除,这里我就简单说一下概念,不做具体的阐述了。

AGGREGATE:AGGREGATE就是一组相关对象的集合,我们把它作为数据修改的单元。每个AGGREGATE都有一个根(root)和一个边界(boundary)。边界定义了AGGREGATE的内部都有什么。根则是AGGREGATE所包含的一个特定ENTITY。对AGGREGATE 而言,外部对象只可以引用根,而边界内部的对象之间则可以互相引用。除根以外的其他ENTITY 都有本地标识,但这些标识只在AGGREGATE内部才需要加以区别,因为外部对象除了根ENTITY之 外看不到其他对象。所以我对AGGREGATE就是聚合单元。

FACTORY:有接触过设计模式的童鞋都知道FACTORY,FACTORY是负责创建对象,实例化对象的。在这里FACTORY的作用是一样的。

REPOSITORY:REPOSITORY将某种类型的所有对象表示为一个概念集合(通常是模拟的)。它的行为类似于集合(collection),只是具有更复杂的查询功能。在添加或删除相应类型的对象时,REPOSITORY的后台机制负责将对象添加到数据库中,或从数据库中删除对象。这个定义将一组紧密相关的职责集中在一起,这些职责提供了对AGGREGATE根的整个生命周期的全程访问。对于REPOSITORY,我们通常是用来统一实现对象到数据库的存储与读取。要注意的是对于一个AGGREGATE使用一个REPOSITORY。因为在我之前的项目中有过滥用REPOSITORY的现象,对每一个对象都建立了与之对应的REPOSITORY,然后对于同一个聚合内的关系查询和存储会发现不知道将代码写在哪,感觉放哪都行,于是时间一长,你会发现冗余代码越来越多了起来。

构造示例

下面是书中的一个示例,帮助我们理解和消化上面的知识。

领域模型描述语言:

“一个Cargo(货物)涉及多个Customer(客户),每个Customer承担不同的角色。” “Cargo的运送目标已指定。” “由一系列满足Specification(规格)的Carrier Movement(运输动作)来完成运送目标。”

上图包含了我们前面说到的概念模式知识,从你的角度理解一下,如果有不明白欢迎留言提问~ 


本文中讲述的概念和示例均摘自《领域驱动设计-软件复杂性应对之道》