`
upheart
  • 浏览: 15781 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

回复:对领域模型实现的总结性观点

阅读更多

为什么要分层呢?——大部分人是为了分层而分层,比如我们以前的一个做法就是强制一个实体对应一个dao、一个service一个action等等,就像是写八股文章,还美其名曰规范化,为了以后好维护。结果都是一两行的代码在几层之间包来包去。

我觉得分层最主要的目的是解耦。很多人可能觉得分层是为了分类职责,这可能是分层带来的一个好处,但不是主要目的。要的目的是解耦,解耦的主要目的是应对变化。比如我分一个dao层,可以屏蔽掉hibernate或jpa或jdbc的具体实现,这样我可以切换不同的实现了。你看spring里边的petstore例子提供了不同的实现。

问题是对于变化我们应该什么态度。我觉得应该在三个方面考虑:1.变化发生的可能性和机率;2.提前准备应对这个变化要增加的成本(包括机会成本)3.如果不提前考虑这个变化,以后通过重构来应对的代价。

比如你有多大的可能要切换hibernate到jdbc或其他的实现呢?如果hibernate已经被证实足够稳定,那依赖它有什么问题呢?就像你依赖java.util一样是吧。这种被Rod JSon成为“幻影需求”提前为此而分层实在不值得吧。其实就算你分了层以后切换的时候还是会有很多问题的(比如你用了hibernate的二级缓存、关联关系要是切换到其它实现,很容易引入潜在的问题),除非你的应用就像petstore一样简单。所以与其这么做,不如完善你的测试,如果变化来了,有测试做保障,提炼重构付出的代价不一定比你提前预防这种变化的的代价要大很多。而且一定要考虑这种变化的机率的大小。

分层的另一个好处是可以做孤立测试,说白了就是分离职责然后单独测试。但我前面说过分离职责不一定要分层的,如果这种情况不是很多,你可以把业务复杂职责单一的功能放在同一层中另外一个类中。

我现在的做法是用spring web flow做控制层,不需要java代码,只要xml的flow定义,其中调用service层。这个service层负责事务边界也代理业务,service方法中直接调用JPA接口。domain对象除了jpa等元数据的映射,提供一些get方法(我是说计算方法,比如getTotalSize()),还提供一些验证逻辑。页面使用Rich Faces。

service测试大部分不做mock,而是连接数据库做测试,spring test框架支持自动回滚,可以用dbunit初始化测试数据就可以了。业务计算复杂的,如果不依赖于数据存储,应该放在domain对象中,否则,提炼出一个service类,这样对这段逻辑就可以做孤立测试了。domain就是普通的javabean,测试自然没有问题。

可能以后还想加上selenium做验收测试,现在还没有加。

2
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics