业务领域建模Domain Modeling
业务建模其实是一个从多方面描述系统的综合。大约要划分为四个方向:
1.是组织机构和人员模型。 也就是信息化手段应用后对组织、机构和人员的影响和变化。包括工作内容,职责,以及因此带来的制度规范的变化。
2.是业务/处理模型,这里所谓的处理包含的是所有业务过程中的处理。例如把软件打包邮递出去,这个过程完全没有软件参与,但是它是整体工作流程中的一个环节。业务/处理模型,可以根据需要作层次化的细化,此处不再赘述。
3.信息模型。信息模型至少包括了静态的信息形式化后的数据表示,数据规范,数据标准,数据字典、术语、元数据定义等等静态的东西。也包括了数据经过处理后变化的形式、比如显示在屏幕上,打印在报表上,存储在文件中,加载在XML内被传输给一个WebService理解,这种动态的转换和流动的模型。 在大多数MIS系统中,对静态数据的管理就足够解决业务模型中所针对的问题了。但在某些系统中,信息的变化意味着特殊的含义。比如银行系统中你账户上的金额,在这种情况下,就必须要技术手段,例如交易的完整性来保证数据变化和准确性,又例如一个监控系统从外部传感器获取的数据,这种数据的变化常常在业务中有着重要的含义,因此软件必须时刻关注这种数据状态的变化并作出反应,就是很重要的事情。。如此类推。
4.环境模型。环境模型描述了软件系统所运行需要的环境。例如软件环境,OS,数据库,web服务器,也包括了软件的部署环境,部署安装方法。另外,不仅如此在某些软件中还要更加细致的描述环境环境。在这个时候,就必须把业务模型细化并和环境模型一起描述。例如3D软件中作一个宣染处理,总是要放在一个虚拟的场所中处理,每次处理既构成了一个渲染的处理步骤序列,也构成了用户未来观察3D软件制作出来的电影的每次效果观察。更广泛的对环境的描述,甚至还包括了行业规范,国家法规,技术标准等等一系列的东西。又或者是用户信息化素养,知识水平,意识等等,他们通常构成了软件应用环境的一部分,并进而影响到软件的功能,或者是那些隐形的约束。
- 因此,组织/人员模型,业务/处理模型,信息描述和转换模型,环境和部署模型。构成了业务建模最基本的四个模型。也是系统架构师们进一步得到4+1架构模型的基本依据。其中,环境模型直接和场景视图对应;业务/处理模型,信息模型是得出逻辑视图、进程视图的基本依据;物理视图则和几个模型都有关系。在后面追加的则是开发视图,虽然它和业务模型没有直接的关联,但开发模式,开发过程的选择,以及开发手段等都直接受到业务模型中确定的各种需求和约束的影响。举个例子说,如果用户在环境模型中要求软件必须能够以B/S架构部署到虚拟主机上,由于大多数虚拟主机都是基于asp的,那么虽然你可能很希望搞搞j2ee,但这种企图肯定会被老板否决,从而决定了你只能去用MS 的开发工具。
我的工程实践题目是一个关于网站设计的题目,我找了个相关的事例,宠物商店的例子来简要阐述一下网站设计方面如何进行业务领域建模。
为了支持“在线预约”这种特殊的产品,它会影响到大部分的Use Case,具体列举如下:
- 商品信息需要增加“预约时间”这个属性,客户在下订单时会把它作为标识一个预约的关键要素。
- “在线预约”是个虚拟的商品,它可不需要真的需要去检货和包装发货,如果真的那么做啦,我就太傻了。
- 每个宠物医院每天都只能接受一定数量的预约,从这个概念上来说,它与实物商品有类似的库存概念。可是我该怎么去表达它们呢?
- 最要命的是:我真的要把这些所有受影响的Use Case都翻出来去让它们支持虚拟物品的业务吗?我怎么可能在2个月内完成这些重构?
一、概要领域划分
二、找出受影响的领域与接口
从领域的角度来看,只有商品对外暴露出来的接口是会影响到各个领域,需要优先建立商品领域(ProductDomain)及读取商品信息服务接口(GetProductService)来进行重构。
之外,在【图2】 中用绿色标识出来的Use Case是由于增加支持“在线预约”这种虚拟商品所需要进行代码重构的部分。这部分工作如果工期比较紧,可以优先使用模式的方式来进行代码重构,这样也可以在之后更加容易用领域驱动设计的方法再次重构。
三、建立技术框架
这一点,是《领域驱动设计》这本书没有过多提及的内容。这个需要结合你们公司的原来技术框架用最小化改造成本最大化收益的方式来建立领域驱动的技术框架。下面是一个可以广泛使用的领域驱动的技术框架,可以在这之上增加更多的个性元素形成你公司自己的框架。
这个框架的各个元素基本上在 《领域驱动设计》一书中都可以找到对应的解释,但这里需要解释一下我建立这个框架的个性理解:
- 领域对外(页面、AJAX、ESB调用)只暴露领域服务,其它所有领域类都是包内自闭的,对外不可见。
- 基础仓库的引入,基础仓库是一个抽象的仓库,它封装了大量常用工具方法、业务对象生命周期维护(实体OR映射、DAO调用)、外部接口调用。可以降低业务仓库不必要的重复编码与复杂性。业务仓库是继承基础仓库的子类。
- 基础设施的引用,基础设施是用来承载引用非领域调用的桩,我们在使用领域驱动设计的时候往往是从一个旧的系统重构开始。这时我们不可能要求所有的业务子系统相互调用都通过Domain Service调用,这时我们可以通过Infrastructure优美的把调用封装在业务仓库的业务方法内。
四、重构受影响领域的设计与编码
Spark以商品详情页这个Use Case为例展示了以领域驱动设计的重构类图:
- 增加行为表ProductExt用于存储商品的扩展信息,如预约时间段、预约医院。并为表建立一一对应的实体Entity。
- 基础仓库Repository通过Infrastructure中的DAO封装了对实体的操作,如create()、update()、delete()、findById()、findList()
- 商品业务仓库ProductRepository扩展了基础仓库,客户程序可以用productId为参数,通过ProductVo.getProduct()方法获得商品详细信息的业务实现,由于业务仓库的的公开方法对外返回的都是Value Object,因此不会直接暴露Entity类型给客户程序。
- GetProductService服务类通过invoke()服务方法 对外(商品详情页面)提供服务,它通调用业务仓库中的业务方法,并将接口规格化。
- 事务配置在DomainService的invoke()方法上,即事务控制以Use Case为粒度进行控制。