关于暴露业务模型(Exposed Domain Model Pattern)2


核心构件与功能构件的关系
让我们回到现实世界。软件系统呈现出连续谱系的特征,就模型层来说,在其核心存在与功能用例正交的横切构件,而在其边缘也存在一些呈现出与功能层有某种程度平行关系的构件,我们称之为功能构件;它们位于核心层之上,在实现上是核心层的组合;直接位于功能层之下,横切能力弱于核心组件,支持有限的几个用例,甚至一个用例。核心组件与功能组件的并存在空间上是任何应用软件系统的现实结构,在时间上构成一对矛盾,在软件系统发展演化的历史上呈现出此消彼长的形态,是系统的动态结构:

实现一个用户需求,权衡资源,可能以一种直接的、也是狭隘的方式直接针对这个功能,很少或者没有考虑可扩展性,没有考虑充实、完备一个通用的、抽象的模型,系统增加了一个功能组件。
系统逻辑层的功能组件在积累;这些功能组件集合中的某些逻辑都单独实现,但实际上具有共享的可能性
开发团队有了一个合适的机会,将其中具有共享价值的逻辑、计算抽象出来,其结果是:有些功能组件依然存在,但变得较薄;有些丧失了存在的必要性,消亡了。
以上的过程被重复,形成了系统的进化史
如果将第三步去掉,或者没有抓住时机,系统将急速走向崩溃。主要的设计、重构活动都在第三步,它使系统维持了一种动态的平衡,可持续的发展;在这个过程中,边缘的功能组件产生、削弱、消亡,沉淀为核心组件。系统的模型内核的强大引力不断克服用户需求所产生的离心力,在系统本身的存在发展中起作用。

在这个意义上,我并非否定Façade或者DTO在应用系统体系结构的作用,只不过这个作用要置于以上的过程中来看。横向来看,核心组件在结构单元中的足够的比例和份量是系统稳定性和良好扩充性的根本保障;历史的看,功能组件的向核心层的沉积是系统进化的积极方面。

关于外观
Façade作为一种被普遍使用的模式的主要价值应该在于用来封装开发平台API,它将广泛适用的、细粒度的、通用的API封装为粗粒度的适用于某一行业的、领域的直接面向应用的API;因此,封装到什么程度又是一个折中。平台提供者和应用系统的构造者各自的视野有巨大差异,在各方面都不对等,这些差异足以导致封装的必要性。对于应用系统的各个层之间,Façade所起的作用完全不同。关于这个问题就不作更深的探讨了。


小结:
与功能用例相平行的结构单元是系统体系结构中的消极因素;它的存在是软件系统的现实;但在系统良性进化的方向上应该倾向于被消解、吸收、沉淀。正交的、横切的核心组件是模型的精髓,模型应该发展壮大。

以下的段落来自于POJO IN ACTION,作者显然基本是Exposed Domain Model pattern的支持者,但他的几个观点与我还是有不小的差异。原文没有翻译,我的Comment也用英文写出便于参照。

One drawback of using a POJO façade is that you must write potentially complex and error-prone code to detach domain objects.

(Of course we must do that because we are forced to repeat the model as a set of facades and a lots of DTOs)

A simpler approach, which eliminates the need to detach objects, is to use the Exposed Domain Model pattern. This pattern keeps the persistence framework connection open for the duration of the request, which allows the presentation tier to lazily load objects.

(This pattern does not necessarily keeps the framework connection open, just that the OpenSessionInView do it(Spring); Exposed Domain Model pattern as a methodlogy has no direct relationship with it; In fact we do have other alternatives.)

The presentation tier calls domain services to update the domain objects, as well as repositories to query the database, and then gets the data to display directly from domain entities and value objects. You no longer have to worry about detaching the objects that it needs. However, while this approach reduces the amount of code that you must write, there are some tricky design issues because of how transactions, persistence frameworks, and the servlet API interact. Also, the lack of a façade increases the chance that changes to the business tier could affect the presentation tier. There is also the risk of business logic creeping into the presentation tier. Despite these drawbacks, this approach makes sense for many applications and is becomingly increasingly popular.

(In my opinion the other side is more troublesome: the existence of facades tends to absorb logic that should belong to core model and eventually loads to lots of vertically divided structural elements which is most harmful to the health of the system.)