引言
领域模型可以视为所构建系统的概念模型。此模型描述系统中的实体及其关系。领域模型用于建立系统的边界和概念。领域模型还帮助标识这些实体的属性和重要方法。
将面向对象的编程 (OOP) 原理应用到领域模型时,就与处理对象时有些类似。 Martin Fowler 将领域模型定义为包括行为和数据的领域的对象模型。这是实现领域模型的一种方法,但不一定是唯一的方法。
大部分传统 OO 系统和程序都包括对领域数据对象的层次结构进行操作的业务对象。这些数据对象通常为表格中的业务数据的瘦包装,提供数据访问和关系导航方法。它们从数据库捕获核心数据模型以及应用于这些数据的业务规则。此模式的一个典型示例是 Java™ EE 会话 Bean 和实体 Bean ,其中会话 Bean 是业务对象,而实体 Bean 是数据对象。无论如何,这个做法有时候被称为贫血领域模型 (Anemic Domain model) 。
面向对象的领域模型具有自己的用例,在封闭系统(如赌博系统)中能够正常工作。我不会在此重复 OO 系统的好处。另一方面,对象领域模型还有自己的局限,特别在 SOA 环境中更是如此;在 SOA 环境中,跨越多个层次和系统的灵活性和解决方案是最为重要的。接下来让我们对这些局限进行一下分析,并讨论其他一些可能的领域模型。
对象领域模型的问题
任何曾经接触过对象领域模型的人都可以证明,要构建基于对象领域模型的系统,编码工作的很大部分都是围绕应用程序业务数据创建对象包装。假定您有一个简单的银行应用程序领域模型,如下所示:
图 1. 银行应用程序的简单领域模型
在对象领域模型方法中,所做的第一件事情是为 Customer 、 Account 和 Transaction 创建独立的瘦包装类。这些包装对象将需要定义属性,以保存业务相关数据。而且,必须对这些包装对象进行充实,并实现以下行为方法:
持久性方法:从持久存储加载数据和将数据保存到持久存储。
验证方法:验证数据是否符合业务规则。
关系方法:在对象之间进行相容关系导航。
尽管先进的语言可能会提供一些框架和代码生成工具(如 Toplink 或 Hibernate )来实现部分工作的自动化,但仍然需要编写和维护大量代码。
对象关系映射
可以采用简单的对象领域模型(与关系数据库模式模型非常相似),也可以采用复杂的富领域模型(可能与数据库设计相差很大)。无论采取哪种方式,都必须编写或生成代码来进行对象关系映射。
自动化对象关系映射可能在最开始看起来很容易,但将会随着时间的流逝而变得更为复杂。这是一个非常严峻的问题,因为这是尝试在两个完全不同的领域之间建立联系:关系数据存储的设计方式与对象系统的设计方式有着非常微妙(但同时也非常重要)的区别。
解决方案?放弃对象!在某些情况下,面向对象的方法利大于弊,而 ROI 并不能说明创建富领域模型的成本合理,更不用说花费大量的资金和人力在模型和关系数据库之间进行映射了。
关系导航
对象层次结构间的简单导航是数据对象模型中固有的,但对象层次结构中的高级搜索和导航功能必须针对每个搜索标准实现(例如,针对上面的场景的 findTransactionsByCustomer )。要实现这种类型的查询,您将需要熟悉关于数据库模式的知识,而最终得到的是一个相当复杂的逻辑实现。
验证逻辑
对象没有固有的约束,因此要实现数据验证,必须进行显式编码。
通过上面可以看出,数据对象包装组成了应用程序代码的主要部分。在任何项目实现期间,您都会发现自己花费了大量的精力管理数据对象,而不是进行业务逻辑的实现。您需要开发和维护更多的代码,从而导致应用程序开发周期变长,出现的错误也越多,而成本也就越高。而且,如果任何数据模式发生变更,还需要对整个数据层次结构进行修改。如果使用第三方映射工具进行映射,则应用程序将绑定到该工具,从而在领域层和数据库层之间形成了紧密耦合。
SOA 领域中的影响因素
面向服务的体系结构( Service-oriented architecture , SOA )是一种体系结构风格,其目标是实现交互软件代理之间的松散耦合。它是分布式计算和模块化编程的发展。 SOA 使用软件原子服务组装应用程序,而软件原子服务是可重用的组件,但其粒度较粗。尽管服务的样式不同, SOAP 服务和 REST 服务各自采用不同的方式描述服务;但都使用 XML 编写服务消息,均受到 W3C 的 XML 模式之类的语言编写的模式的制约。我们可以将 XML 称为 SOA 的 “ 货币 ” 。最近的一些发展会进一步促进将 XML 作为 SOA 解决方案中的首选领域模型加以采用的过程。
业务驱动的开发
为了实现企业的灵活性和提高响应能力,务必通过业务目标和需求驱动 IT 开发项目。 SOA 在行业中获得了大量支持,因为它将企业解决方案视为服务的联合,这些服务通过定义其服务接口和数据格式的明确指定的契约进行连接。在 SOA 领域中,领域对象不是由程序员使用特定的语言以编程方式创建,而是越来越多地由业务分析人员(或行业标准)使用 XSD 以声明的方式采用某种语言独立创建。这就是 “ 模式优先 ”Web 服务的理论 —— 或 “ 接口优先 ” 的 SOA 编程。
XQuery 和 XPath
随着 XQuery 1.0 和 XPath 2.0 的发布,现在可以使用更为强大和高效的工具了。这些工作结合起来可让 XML 用户查找和查询普通 XML 文档,并能在此类文档的树形结构表示形式中进行导航,以进行系统端到端处理。 XQuery 处理查询,而 XPath 处理导航,节约了 XML 数据操作的时间,而且减少了所需的代码。
数据库中的 XML 支持
较新版本的数据库(如 IBM DB2® v9 )支持将 XML 数据作为首要类型使用。 DB2 经过了扩展,现包括以下技术:
新存储技术,帮助有效管理 XML 文档固有的层次结构。
新索引技术,加快 XML 文档之间及其内部的搜索速度。
新查询语言支持(针对 Xquery )、新图形查询构建程序(针对 Xquery )和新查询优化技术。
添加了基于用户提供的模式验证 XML 数据的支持。
新管理功能,包括关键数据库实用工具的扩展。
与流行应用程序编程接口( Application Programming Interface , API )参考本机支持集成。
DB2 允许客户机应用程序通过 SQL (包括具有 XML 扩展的 SQL ,即经常所说的 SQL/XML )或 Xquery 使用表格和 XML 数据结构。因此,即使您的数据仍然存储在关系表格中,仍然可以在应用程序层将其作为 XML 流发布和查询。
图 2. XML 与关系功能的集成
XML 和对象映射
在 SOA 领域,我们知道与此对应的就是 XML Web 服务。但由于使用我们最喜欢的面向对象的语言(如 Java 或 C# ),我们习惯于创建和使用对象代理来发送和接收 Web 服务,希望由基础 Web 服务引擎工具集自动将 XML 消息绑定到对象。可以这样说, XML 到对象的映射比表格到对象的映射更好。最简单的方式将始终有效,但如果涉及到行业标准 XML 语言(如 OAGIS 、 HL7 、 ACORD 、 IFX 或 OTA ),您的工具集代码生成器可能就无法处理 XSD 的复杂性了。即使您的工具集能够完成其任务,创建和维护所生成的大量对象也会让人觉得是负担,缺乏灵活性。模式中的任何更改都需要完全重新生成代码。而且,对这些生成的基于 XML 的对象进行导航根本不具有直观性。
将 XML 作为首选类编程模型
如果:
业务应用程序主要关注业务数据的创建、操作、存储和表示,
业务数据越来越多地建模为 XML ,
数据库已经提供了本机 XML 支持,
而且较新版本的 XPath 和 XQuery 允许我们更为有效地导航和操作 XML ,
那么,考虑到我们在使用对象关系或 OX 映射的过程中发现的种种问题,为什么我们不能使用 XML 作为首选数据与编程模型呢?
在此模型中,应用程序代码可以使用 DOM 、 JDOM 、 SDO (等等) API 来执行业务逻辑。通过使用 XPath 进行导航,可说明所操作数据之间的关系,从而提高应用程序代码的可读性。理想的情况下,数据应该作为纯 XML 在数据库中存储,但即使数据存储在关系表中,在很多情况下将其首先转换为 XML (以便在应用程序中进行操作)的做法仍然非常合理。
减少代码编写量
由于 XML 会自然地维护数据结构之间的关系,则没有必要创建独立对象层次结构来捕获各个数据结构间的关系。此外, XML 已经有了标准对象模型,名为文档对象模型( Document Object Model , DOM )。此模型的实现处理 XML 数据的构造、修改和序列化。在业务应用程序中加载、修改和保存 XML 数据相当方便。另外,还不需要再硬编码验证逻辑,因为约束检查和模式验证均已内置到 XML 模型中。所有这些都可帮助减少代码(这始终是一件好事),出现错误的几率就越小,维护工作量也减少了。
导航方便,灵活性高
业务逻辑代码易读性高,因为 XPath 可准确地说明数据的本质及其与业务结构的关系。 XPath 2.0 还提供进行搜索和导航的额外功能。而且, XPath 表达式可以方便地外部化,从而能够在不更改代码的情况下形成表达式,甚至在 XML 结构变化时也不受影响。这正是所需的灵活性,尤其在 SOA 环境中特别重要。
性能更好
使用以 XML 为中心的方法时应该能得到更好的运行时性能,因为并不会创建额外的对象,因而不需要进行垃圾回收。如果是处理大型 XML 文件,您将更加重视这一优点。
结束语
在典型的 SOA 解决方案中,需要跨应用程序的不同层次(客户机、流程、服务器总线和服务器层)序列化数据。最适合流的数据格式是 XML 。在每个层次中,都可以对数据进行查询、转换和更新,因此只要保持了数据的 XML 本质,就可以使用不同的语言(如 Java 、 JavaScript™ 、 PHP 或 Xquery )来操作数据。尽管所使用的相关语言可能不同,但所有层次中用于遍历 XML 文档的语言是相同的: Xpath ,其表达式可以外部化,并在所有层次共享。这应该是用于构建分布式 SOA 系统的一种更为完善而一致的方法。