理解领域模型
大概从去年开始,就开始觉得,我一直在写的Java根本是面向过程的。并且绝大多数的代码都非常丑陋,那些封装,抽象,设计模式。压根没有一点用武之地。我很努力的在项目中尽量让我的代码显的优美,可收效甚微。于是我怀疑,是不是这很多书中所谓的“三层框架”从一开始就是有问题的。
之后在《轻量级JavaEE企业应用实战 Struts2 Spring3 Hibernate整合开发》读到了相关的架构设计策略。网上搜索才知道,原来不止我一个人有各种怀疑。javaeye很久以前就有次关于domain object的大讨论了。
网上的资料不多,一般有两种分类:
贫血模型、领域模型,这种分类方法应该来自Martin Fowler的《企业应用架构模式》。
失血模型、贫血模型、充血模型、胀血模型,这种分类方法可能是在javaeye上的robbin提出的,我不太确定。
作为学习资料,这里使用更为标准的领域模型的相关概念。
贫血模型
只有get/set的model,Dao,还有Service。
service处理业务逻辑。其本质和存储过程其实也没啥大差别,即事物脚本。
贫血模型的包结构:
- dao:负责持久化逻辑。
- model:包含数据对象,是service操纵的对象。
- service:放置所有的服务类,其中包含了所有的业务逻辑。
- facade:提供对UI层访问的入口。
这就是很多书里介绍的“三层架构”。代码写到现在,我做过的所有项目都这样写的,连C#都不例外。当业务逻辑复杂,service便会变得无比庞大,维护非常困难。还有这种模型根本就不面向对象,最多只能算基于对象。更可恶的是,似乎大家都以为这才是标准。
对于业务逻辑简单的项目,贫血模型是可以使用的。但业务复杂后,即应避免贫血。或重构代码时去除贫血。
领域模型(domain model)
现在比较公认的领域模型是将与持久化无关的业务逻辑放入model中,dao负责持久化。service负责跨领域的业务逻辑。
更加面向对象,且实现方法清晰,易于控制。
但有个问题就是,service中包含了DAO的持久化方法,还不是纯粹的业务逻辑处理。
- infrastructure: 代表基础设施层,一般负责对象的持久化。
- domain:代表领域层。domain包中包括两个子包,分别是model和service。model中包含模型对象,Repository(DAO)接口。它负责关键业务逻辑。service包为一系列的领域服务,之所以需要service,按照DDD的观点,是因为领域中的某些概念本质是一些行为,并且不便放入某个模型对象中。比如转帐操作,它是一个行为,并且它涉及三个对 象,fromAccount,toAccount和TransferTransaction,将它放入任一个对象中都不好。
- application: 代表应用层,它的主要提供对UI层的统一访问接口,并作为事务界限。
富领域对象(rich domain model)
将model与dao相结合。也即将持久化方法放入model中。
这样就带来一个难点,service与model怎么划分。
实现需要深刻的理论与丰富的经验。难度较大。
据说,ROR实现该模型非常方便,看来有必要学习一下Ruby。
由于Service与model难于划分,所有有人提出废除service。所有的业务逻辑都放在model中。
完全消除分层,事物没法控制,且无法将会由web层控制业务逻辑。这是比贫血模型更应该摒弃的。
对领域模型的一个疑问:在团队开发中,由于每个开发者水平层次不齐。如何保证每个领域内的业务逻辑可以在各个不同开发人员之间协作开发呢?
参考资料:
http://www.iteye.com/topic/17579
http://www.iteye.com/topic/283668
《轻量级JavaEE企业应用实战 Struts2 Spring3 Hibernate整合开发》