领域模型驱动(
Domain Driven Design
),很热的名词。
Openfans
,不太热的网站。今天俺就借着很热的
ddd
,给不太热的
openfans
再造点势。
Openfans
就不多介绍了,网站用
spring+hibernate
为核心的一堆开源软件构建。有了
spring
的
IOC
和
hibernate
的
ORM
,打着
ddd
的旗号也就名正言顺了很多。先声明其实俺对
ddd
的理解也多是道听途说,没有什么系统的学习过,倒是和
Joe
阿牛讨论过几次,颇有受益,他对这个理解还是很深刻的。
言归正传,就讲
openfans
现在经
ddd
思想改造过的模型。整体上看还是普通的三层架构体系:展现层、业务层、持久层。展现层用
spring mvc
,力图做到只是展示相关,避免出现业务逻辑。再具体细分,就是
jsp
页面只有展示逻辑,主要使用
jstl
完成显示功能。
Controller
负责从页面获得参数、把数据传回页面、控制页面流传和调用业务层的接口。持久层使用
hibernate
,在设计上我不是按
dao
方式为每个对象建立相应的
dao
,也不是
ddd
推荐的每个
domain
一个
repository
,而是分成了
Persistence
和
Fetcher2
个接口。
Persistence
处理持久相关如
save
和
remove
方法,
Fetcher
则处理
get
相关。这样分的原因也很简单,
persistence
是很稳固的,对象都可以共用一个接口如
save
(
Object
),而
fetcher
就千变万化,需要分页、排序等接口。
这样设计是与业务层架构相关的。我采用的是
domain
对象(简称
DO
)
+
一层薄薄
façade
的方式。
DO
处理自身的逻辑,包括持久功能。本身
DO
是没有持久能力的,需要依靠注入的
persistence
接口,这里就体现按
Persistence
和
Fetcher
分开的一个好处,
persistence
所有
DO
可以共用一个,给编程带来了方便。
Openfans
中采用的是
DO
继承一个抽象
PersistentObject
类的方式,这样
DO
方便的获得了注入的能力和持久的能力。这样做有何优缺点还需要做些讨论,为了方便我也就先这么用。
PersistentObject
代码如下:
public abstract class PersistentObject implements NeedPersist {
private Persistence persistence;
public void save() {
persistence.save(this);
}
public void remove() {
persistence.remove(this);
}
public void setPersistence(Persistence persistence) {
this.persistence = persistence;
}
public Persistence getPersistence() {
return persistence;
}
}
这样
DO
只需要注入
persistence
就获得了持久的能力,而且可以把这种能力往下传递。
DO
获得了持久能力,就有点接近富血模型的想法了,他能够处理一些业务,做持久然后调用引用对象的业务和持久方法
(
从另外的角度看持久与业务其实是分不开的
)
。这样把业务封装在了领域本身,更适于用领域对象出发的方式去思考问题。领域层的
façade
主要是为了
Transaction
管理和隐藏
DO
接口。这样
DO
的业务方法都可以设置成
friendly
,仅相互间可见。
Façade
就放在
domain
包中,它负责给
DO
注入
persistence bean
,调用
DO
的接口,提供给
controller
一个
use case
级别的接口,同时它也代理
fetcher
的接口。
有了这个架构,实现起来也不复杂,要配置的
bean
很少(现在还没有使用
spring 2.0
将
DO
配置在容器中)。设计就从
DO
出发,明确它的属性和方法,让
hibernate
自己生成数据库表。
这样设计也算是一次尝试吧,其中肯定有很多考虑不周的地方,需要不断的讨论和改进。