InfoQ

文章

面向XML的领域建模设计

作者 王翔(Vision Wang) 发布于 2007年10月30日 下午10时56分

社区
.NET,
Architecture
主题
设计,
企业架构
标签
领域驱动设计,
XML

在领域驱动设计(DDD:Domain Driven Design)中,实现业务逻辑层主要有三种模式[1]:Transaction Script、Domain Module和Table Module。随着业务逻辑复杂程度的增加,采用各模式实现的工作量变化趋势有所不同;根据应用特点,三种模式也各有优势:

  1. Transaction Script:业务逻辑直接用SQL脚本与数据库交互,实现简单,但是限于SQL面向过程化的特点,完成复杂业务逻辑时工作量较大。
  2. Domain Module:将业务数据封装为业务对象,适于业务逻辑复杂的应用,但需要O/R映射的支持。
  3. Table Module:将业务数据组织成数据表方式,虽然对象化特征不如Domain Module明显,但适于展现层使用。

图1:实现所需工作量与业务逻辑复杂度的关系

应用建设初期选择的实现模式随着业务需求和历史数据量的变化可能需要进行调整,此时要增加一个适应性机制,保证在尽量不影响客户程序的前提下,选择合适的实现模式。随着XML数据使用日趋广泛,须借助XPath、XQuery和XSL为层次型数据增加专门的扩展机制,使得基于XML数据源的业务逻辑也可以采用上述三种模式实现。

概要设计

整体逻辑结构

总体适配机制如下:

图2:总体实现结构

为业务服务增加抽象接口IDomainService,客户程序通过DomainServiceFactory获得该抽象接口,这样客户程序不依赖于具体的业务服务实体类,仅依赖于抽象的服务接口,当下层实现模式调整时,不影响客户程序;为了让框架可以同时适应关系数据库和XML数据,增加了抽象接口IDataSource,代表不同的数据源对象;IDataMapper负责根据不同的数据源,完成关系数据或XML数据与业务对象的映射;为了减少DomainServiceFactory与具体业务服务对象产生依赖,增加配置管理对象ConfigManager,由它获取指定的业务服务的实体类名称,并通过反射机制动态生成目标实例。

性能改进

由于业务实体经常会对应到具有Master-Detail关系的多个表,而且有些复杂业务实体本身会包含一组或几组其它业务实体,出于性能考虑,为了避免IDataMapper在映射过程中频繁调用数据源逐个生成子业务实体,需要在IDataMapper与数据源之间增加一个DTO(Data Transfer Object)对象IDataTransferObject,通过将调用打包的办法,减少频繁的远程调用。

图3:借助DTO,Domain Module对象间接访问数据源

详细设计

面向关系数据库的业务服务设计

为了将业务实体纳入适配机制的管理,依据依赖倒置原则,先对各模式实现的业务实体进行抽象。

图4: 关系数据库方式下的适配机制

为每种模式实现的业务对象抽象独立接口,并编写对应的关系数据库实现类;Domain Module需要调度数据映射和DTO进行关系数据与业务实体的映射;增加抽象基类DomainModuleBase,通过调用IDataMapper和IDataTransferObject完成数据提取和映射工作。

表1:关系数据库下三种模式的执行特征

面向XML数据的扩展设计

由于XML的层次特征,3个模式的实现技术与关系数据库不同:

表2:XML数据下三种模式的执行特征

图5: XML数据方式下的适配机制

配置机制设计

通过增加服务接口工厂类的方式隔离客户程序与具体业务服务实体类间的依赖,工厂类通过配置管理ConfigManager获得每个目标服务接口对应的实体类名称,借助反射动态包装目标服务接口。静态结构和执行过程如下:

图6:配置管理机制

图7:客户程序获得业务服务接口的时序关系

实验环境准备及实验结果分析

测试业务对象

为了比较三种模式实现特点的不同,测试中设计了2个具有Master-Detail特征的业务实体:Customer和Order,两者之间也存在1:N的关系,对应的关系数据库和XML数据实现如下:

图8:业务实体

图9:关系数据库方式下业务实体实现

图10:XML数据方式下业务实体的实现

目标服务是一个根据客户名称,返回其所有订单明细项小计之和的接口。

测试内容准备

针对关系数据库和XML数据方式的不同,业务逻辑如表3。其中,XML数据的Transaction Script模式为了计算简单,增加一个采用XSTL生成 “客户名称—订单项明细小计”的中间过程:

图11:XML

Transaction Script方式下生成中间结果的XSLT

表3:两种数据模型下三个实现模式的计算方法

测试数据

表4:测试数据

测试结果及分析

通过修改ConfigManager中实现业务服务的实体类名称,结合数据库调用监控获得如下数据:

表5:测试结果

测试结果分析如下:

1)借助适配机制,在目标实现模式甚至数据模型修改时,客户程序保持稳定,修改内容控制在配置文件部分,不影响客户程序的业务逻辑;

2)使用不同模式设计完成的业务对象,借助适配机制和XML数据扩展机制,在关系数据库和XML数据方式下,可完成同样的服务功能;

3)通过DTO组件的调用打包作用,可以将包括2份订单、4项订单明细的信息一次性提取,将多次调用打包为1次调用,减少了网络往复。

总结

依据依赖导致原理设计的适配机制可以从一定程度上减少客户程序与业务逻辑的耦合程度,在部署、运行环境变化时,可通过调整配置选择合适的业务逻辑实现模式,并且不需要客户程序联动修改;DTO对象的加入可以减少分布式调用中的往复次数,对应用性能的提升有利。实际工程中,由于业务逻辑实体往往需要被多个客户程序调用,需要有效的并发机制配合,后续研究中将着重对并发能力进行调整。

参考文献:

[1] Fowler, Martin著,Patterns of Enterprise Application Architecture

[2] Biping Joshi著,Pro .Net 2.0 XML

源代码下载: DomainMechanism

10 条回复

回复

非常希望能看到实现代码 发表人 Franky Yang 发表于 2007年11月2日 上午1时11分
Re: 非常希望能看到实现代码 发表人 hello hello 发表于 2007年11月2日 上午8时10分
Re: 非常希望能看到实现代码 发表人 emil chan 发表于 2007年11月2日 下午8时24分
Re: 非常希望能看到实现代码 发表人 霍 泰稳 发表于 2007年11月4日 上午5时56分
Re: 非常希望能看到实现代码 发表人 liufeng zheng 发表于 2007年11月4日 下午7时36分
Re: 非常希望能看到实现代码 发表人 hello hello 发表于 2007年11月4日 下午8时58分
Re: 非常希望能看到实现代码 发表人 霍 泰稳 发表于 2007年11月4日 下午9时5分
很有启发 发表人 jun zhang 发表于 2007年11月5日 下午7时51分
Re: 很有启发 发表人 hello hello 发表于 2007年11月9日 上午5时12分
Re: 很有启发 发表人 hello hello 发表于 2007年11月10日 上午4时21分
  1. 返回顶部

    非常希望能看到实现代码

    2007年11月2日 上午1时11分 发表人 Franky Yang

    非常希望能看到实现代码。

  2. 返回顶部

    Re: 非常希望能看到实现代码

    2007年11月2日 上午8时10分 发表人 hello hello

    示例打了个包,提交给编辑了。 XML部分采用Altova Enterprise Architect 2008的XMLSPY + MapForce做的。 逻辑部分用VS 2005 + .NET Framework 2.0。 UML部分比较传统,只用过Rose。 看看能否上传附件。 不过您也可以先留个mail。 希望可以与您多多交流。

  3. 返回顶部

    Re: 非常希望能看到实现代码

    2007年11月2日 下午8时24分 发表人 emil chan

    能给我一份学习么?谢谢emilchan6k@126.com

  4. 返回顶部

    Re: 非常希望能看到实现代码

    2007年11月4日 上午5时56分 发表人 霍 泰稳

    如果文件不大的话,是可以直接上传的,没有问题,谢谢hello hello的源码分享:)

  5. 返回顶部

    Re: 非常希望能看到实现代码

    2007年11月4日 下午7时36分 发表人 liufeng zheng

    希望hello hello 给我发个源码学习学习,谢谢! zdz8207@163.com

  6. 返回顶部

    Re: 非常希望能看到实现代码

    2007年11月4日 下午8时58分 发表人 hello hello

    已经麻烦编辑帮忙上传了。 :) 谢谢Taiwen.

  7. 返回顶部

    Re: 非常希望能看到实现代码

    2007年11月4日 下午9时5分 发表人 霍 泰稳

    已经上传,参加文末“ 源代码下载: DomainMechanism”部分!

  8. 返回顶部

    很有启发

    2007年11月5日 下午7时51分 发表人 jun zhang

    很有启发,慢慢拜读

  9. 返回顶部

    Re: 很有启发

    2007年11月9日 上午5时12分 发表人 hello hello

    这几天参加了Tech-ED,发现XML几乎Everywhere,不仅是软件部分,就连平时很少去听的Windows Networking,将的很多还是通过XML定义策略,XML Web Service防火墙之类的东西。

  10. 返回顶部

    Re: 很有启发

    2007年11月10日 上午4时21分 发表人 hello hello

    通过这两三年一些项目的体会,一般是这样的: Tx Script用于批量处理,尤其是后台处理; TM 用于各种前台的分析、聚合、统计; DM 用于业务流转过程的单业务实体(或几个关联业务实体);

独家内容

程立谈架构、敏捷和SOA实践

支付宝首席架构师程立在本文分享了支付宝技术架构的发展,对架构的认识,成功架构的特点,如何避免架构设计的失败,以及在敏捷和SOA方面的实践等。

Emmanuel Bernard谈Bean验证规范

InfoQ有幸采访到了Emmanuel Bernard,向其了解Bean验证框架及专家组正在寻求的社区参与的更多相关信息。

通过索引器简化C#类型信息访问

作为一个有别于Java、Ruby等语言的一个特性,C#可以用索引器(Indexer)将类型本身以对象数组的形式供外部使用。同时,把索引器和LINQ结合使用倒是一个非常不错的组合,索引器做接口、LINQ完成内部检索逻辑,客户程序在无需记住具体方法名称的前提下,按照键值检索即可,索引器内部则依托LINQ to系列的基础,提供对各种异构数据源的访问。

产品负责人成功之道

Scrum中,产品负责人这个角色具有很大的影响力,能够带来很高的价值。但要想运用得当,可没那么轻而易举。如果做得好,就可以在客户和开发者之间建立更为融洽的关系,并能够增加组织的竞争优势。

硝烟中的Scrum和XP

在本书中,作者Henrik Kniberg讲述了他在一年的时间里,带领40人的团队实施Scrum的过程。他们试过了多种团队尺寸(3~12人)、sprint长度(2~6星期),定义“完成”的不同方式,不同的backlog格式,各种测试策略,在多个Scrum团队之间进行同步的多种方式。他们还尝试过XP实践——持续集成、结对编程、测试驱动开发等等,还试过了把XP跟Scrum组合。

软件开发中的准时化生产

准时化生产(Just In Time)是精益生产(Lean Production)和丰田生产系统(Toyota Production System)中的概念,敏捷开发与准时化生产中的很多观点和实践是一致的,精益思想作为精益生产背后的指导思想也正在积极地影响着软件开发领域,向其中不断注入创新与活力。

Tapestry for Nonbelievers

I. Drobiazko和R. Zubairov合作撰写了一篇文章,详细介绍Apache Tapestry 版本5——一个面向组件web框架。文章向读者展示了创建组件方法,并谈到了Tapestry中的IoC以及Ajax的相关特性。

ESB拓扑方案

在本文中,Adrien Louis讨论了两种基于ESB的SOA拓扑方案的优缺点:单个公司级ESB vs. 彼此互联的“部门级”ESB系统。Adrien讨论了每种方案对管理、业务监测、治理、可靠性和编配等问题的影响。