如何为那些不明显的概念建模?
面向对象范式会引导我们去寻找和创造特定类型的概念。所有的事务及其操作行为是大部分对象模型的主要部分。它就是面向对象设计入门书籍所讲到的“名称和动词”。但是,其他重要类别的概念也可以在模型中显示地表达出来。
1.显示的约束
约束是模型概念中非常重要的类别。它们通常是隐含的,将它们显示地表现出来可以极大地提高设计质量。
有时,约束很自然地存在于对象或方法中。如果约束很简单,使用简单的代码也很容易理解。但如果约束较复杂的话,简单维护就很容易像隐式概念一样被淹没。这时将约束条件提取到其自己的方法中,这样就可以通过方法名来表达约束的含义,从而在设计中显示的表达出这种约束。在讨论时就可以用它的名字进行讨论。这种方式也为约束的扩展提供了空间。
有时候,约束条件是无法用单独的方法来轻松表达,或者即使方法自身能够保持它的简单性,但它可能会调用一些信息,但对于对象的主要职责而言,这些信息毫无用处,这种约束可能就不适合放到现有对象中。
下面是一些警告信息,表明约束的存在正在扰乱其“宿主对象”的设计
1.计算约束所需的数据从定义上看并不属于这个对象;
2.相关约束在多个对象中出现,造成了代码重复或导致不属于同一族的对象之间产生了继承关系;
3.很多设计和需求讨论都是围绕这些约束进行的,而在代码实现中,它们却隐藏在过程代码中。
如果约束的存在掩盖了对象的基本职责,或者如果约束在领域中非常的突出但在模型中却不明显,那么就可以将其提取到一个显示的对象中,甚至可以把它建模为一个对象和关系的集合。
2.将过程建模为领域对象
首先要说明的是,我们都不希望过程变成模型的主要部分,对象是用来封装过程的,这样我们只需要考虑对象的业务目的或意图就行了。
在这里,我们讨论的是存在领域中的过程,我们必须在模型中把这些过程表示出来,否则当这些过程显露出来时,往往会使对象变得笨拙。
如何判断过程应该是显示出来还是隐藏起来?
区分的方法很简单,它是经常被领域专家提起的呢?还是仅仅当做计算机程序机制的一部分呢?经常被领域专家提起的就显示的表示出来。
约束和过程是两大类模型概念,当我们用面向对象语言编程时,不会立刻想到它们,然而它们一旦被我们视为模型元素,就真的可以让我们的设计更为清晰。
3.模式:规格(specifiction)
可以测试任何对象以验证他们是否满足指定的标准;因此,为特殊目的创建谓词形式的显式的VALUE OBJECT。SPECIFICATION就是一个谓词,可用来确定对象是否满足某些标准。
SPECIFICATION最有价值的地方在于它可以将看起来完全不同的应用功能统一起来。出于以下 3个目的中的一个或多个,我们可能需要指定对象的状态。
(1) 验证对象,检查它是否能满足某些需求或者是否已经为实现某个目标做好了准备。
(2) 从集合中选择一个对象(如上述例子中的查询过期发票)。
(3) 指定在创建新对象时必须满足某种需求。
这3种用法(验证、选择和根据要求来创建)从概念层面上来讲是相同的,如果没有诸如SPECIFICATION这样的模式,相同的规则可能会表现为不同的形式,甚至有可能是相互矛盾的形式。这样就会丧失概念上的统一性。通过应用SPECIFICATION模式,我们可以使用一致的模型,尽管在实现时可能需要分开处理。
业务规则通常不适合作为ENTITY或VALUE OBJECT的职责,而且规则的变化和组合也会掩盖领域对象的基本含义。但是将规则移出领域层的结果会更糟糕,因为这样一来,领域代码就不再 表达模型了。
逻辑编程提供了一种概念,即“谓词”这种可分离、可组合的规则对象,但是要把这种概念 用对象完全实现是很麻烦的。同时,这种概念过于通用,在表达设计意图方面,它的针对性不如专门的设计那么好。
不好的处理
1.开发人员通常会将规则计算代码重构到应用层中。当领域规则从领域层中分离出来,留下的就是一个纯粹的数据对象,它将不再表达本来应该在业务模型中表示的规则。这些规则需要保留在领域层中,但是把它们放到被其约束的对象里又不合适。此外,计算规则的方法中到处都是条件代码, 这也使得规则变得复杂难懂。
如何解决:那些使用逻辑编程范式的开发人员会用一种不同的方式来处理这种情况。这种规则被称为谓词。谓词是指计算结果为“真”或“假”的函数,并且可以使用操作符(如AND和OR)把它们连接起来以表达更复杂的规则。通过谓词,我们可以显式地声明规则并在对象中使用这些规则。 但前提是必须使用逻辑范式。