|
最新发布的 Entity Framework 4.1 和新的 Code First 开发模式打破了服务器程序开发的基本规则:如果数据库没有准备就绪,不要轻举妄动(Don’t take a single step)。Code First 允许开发人员重点关注业务领域并根据“类”(class)来为该领域建模。在某种程度上, Code First 模式鼓励在 .NET 环境中应用“领域驱动设计 (DDD) ”原则。业务领域由相互关联的实体构成,这些实体通过属性对外公开自己的数据,通过方法和事件对外公开自己的行为。更重要的是,每个实体都可能处于某一状态,并且与一组动态的验证规则相绑定。
为实际应用场景编写对象模型会面临一些在演示程序和教程中没有涉及的问题。在本文中,我将挑战这些问题,并讨论如何构建 Customer 类,我会就此简要介绍一些设计模式和设计实践,例如Party模式、聚合根(aggregate roots)、工厂(factories)以及代码协定(Code Contracts)和企业库验证应用程序块 (VAB) 等技术。
有一个开源项目可以作为参考,这里讨论的代码就是其中的一小部分。 它就是由 Andrea Saltarello 创建的 Northwind Starter Kit 项目 (nsk.codeplex.com) ,该项目旨在介绍构建多层解决方案的有效实践。
对象模型(Object Model) vs. 领域模型(Domain Model)
争论是使用对象模型还是领域模型似乎没有意义,在大多数情况下,这只是一个术语表述问题(terminology)。 但准确地使用术语是确保团队所有成员在使用特定术语时始终遵循同一概念的重要因素。
对于软件行业的几乎每个人而言,对象模型是一个具有共性的并且可能相关的对象的集合。领域模型有何不同? 域模型归根结底仍然是一个对象模型,因此,交替使用这两个术语可能不会产生严重的错误。但在专门强调使用“领域模型”一词时,它可能会使大家对所构建的对象的形态(shape)产生某些期望。
领域模型的这种用法与 Martin Fowler 给出的以下定义相关:
由行为和数据组合而成的领域的对象模型。相应地,这些行为用于表达业务规则和特定的业务逻辑(请参阅 P of EAA page 116)。
An object model of the domain that incorporates both behavior and data. In turn, the behavior expresses both rules and specific logic.
DDD 向领域模型中添加了一些实用的规则。从这个角度看,领域模型不同于对象模型,它更多推荐使用值对象(value objects)而不是基元类型(primitive types)。例如在对象模型中,一个整数可能具有多种含义,它可能表示温度、金额、大小或数量。而在领域模型中,针对各种不同的场景会使用特定的值对象类型。
此外,领域模型需要识别出聚合根。聚合根是一个通过组合其他实体而得到的实体。聚合根中的对象与外部没有直接的关联,也就是不存在这样的用例——不经过根对象而直接使用这些对象。比如,Order 实体就是一个典型的聚合根。 Order 包含聚合的 OrderItem,而不包含 Product。 难以想象您使用一个OrderItem 而它并不来自 Order(即使这只是由specs决定的,译者注:也就是通过规约查询直接得到相应的OderItem)。另一方面,您很可能具有这样一些用例,您在其中使用不涉及订单的 Product 实体。聚合根负责维护处于有效状态的子对象并持久化这些对象。
最后,某些领域模型类(class)可以提供用于创建新实例的公共工厂方法,而不是构造函数。如果模型类通常是独立的并且实际上不是层次结构的一部分,或者用于创建该类的步骤只是与客户端相关,则可以使用普通的构造函数。但是,在使用聚合根这样的复杂对象时,您还需要实例化之外的其他抽象级别。 DDD 引入了工厂对象(简单一些的话,可以使用类中的工厂方法)方式,这种方式可将客户端的需求与内部的对象及其关系和规则分离开来。可以在 An Introduction to Domain Driven Design 中找到有关 DDD 的清晰简要的介绍。
Party模式
让我们重点分析一下 Customer 类。 根据上文所述,此处是可能的签名:
public class Customer : Organization, IAggregateRoot
{
...
}
NET技术:Dino Esposito: 一个领域模型的设计,转载需保留来源!
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。