Alberto Gutierrez最近给出了创建优秀领域模型的10条建议。
理解这几条建议并不是什么太难的事情,而且关于领域模型已经有各种形形色色的书籍文章进行过介绍讲解。知易行难,真正的困难在于执行。这其中的原因 是多方面的,其中工具和技术是一个重要因素,虽然我本人并不是一个唯工具论者,但我还是得承认,象AOP和MOP这样技术的出现确实大大促进了DDD。
就拿上面的第5条(让领域模型保持独立)来讲,其内涵讲的是不要在领域模型中引入其他方面的内容,如持久化机制。那么,在不使用AOP和MOP的前提下,常见的做法就是:实现领域类,然后再实现一个DAO来完成领域类的持久化。典型的使用大概是这样:
1 |
dao.save(domain); |
可 是从概念上讲,domain.save(),是不是更自然呢?如果要让你的领域类具备这样的功能,最简单的做法就是在领域类中包含一个DAO的引用,然后 将save操作转发到所引用的DAO实例上。如果要保持领域类和DAO的独立,那么最好引用的是DAO的接口,然后再实现相应的setter,在运行时注 入DAO实例。要是只有一个领域类还罢了,如果有几十个,那就太麻烦了……
“麻烦”就会导致人们走捷径,而某些时候走捷径恰恰是一种短期获利行为,最终会带来长期的痛苦。对于这个例子,捷径有两种:
- 第一种:完成领域类和DAO就算了,就让自己麻烦点,使用类似dao.save(domain)的方式算了。
- 第二种:干脆在领域类里直接实现持久化逻辑,造成对领域类进行单元测试的困难。使领域类更持久化底层之间建立起强耦合。
第二种捷径恰恰属于前面说的“短期获利,长期痛苦”的情形。
借助前面的两项技术中的任意一种,如MOP,我们完全可以按照自然的方式去实现领域类,而在运行时去享受类似“domain.save()”这样的好处。也正是这个特性,让Grails成为了一个优秀的DDD框架,而又没有给我们这些Grails开发者带来额外的负担。
凭借Grails对DDD良好地支持,贯彻Alberto的这10条建议不再困难,相反,在开发应用时不采用DDD反而成了一件别扭的事情。好的工具可以促进工作,反之则为工作造成阻碍。