Oop DDD:在何处放置持久性逻辑,何时使用ORM映射
我们将对我们的(Java)web应用程序模式进行长期、深入的研究。在过去,我们的对象模型过于贫乏,控制器、服务和DAO之间的分离过于程序化,简单的值对象(基本上只是数据包)在它们之间移动。我们使用了声明式(XML)管理的ORM(Hibernate)进行持久化。所有实体管理均在DAOs中进行 在尝试转移到更丰富的领域模型时,我们发现自己正在为如何最好地设计持久层而挣扎。我花了很多时间阅读和思考领域驱动的设计模式。不过,我想得到一些建议 首先,我更自信的是:Oop DDD:在何处放置持久性逻辑,何时使用ORM映射,oop,design-patterns,domain-driven-design,dao,Oop,Design Patterns,Domain Driven Design,Dao,我们将对我们的(Java)web应用程序模式进行长期、深入的研究。在过去,我们的对象模型过于贫乏,控制器、服务和DAO之间的分离过于程序化,简单的值对象(基本上只是数据包)在它们之间移动。我们使用了声明式(XML)管理的ORM(Hibernate)进行持久化。所有实体管理均在DAOs中进行 在尝试转移到更丰富的领域模型时,我们发现自己正在为如何最好地设计持久层而挣扎。我花了很多时间阅读和思考领域驱动的设计模式。不过,我想得到一些建议 首先,我更自信的是: 我们将在前端使用“精简”控制器,只处理
- 我们将在前端使用“精简”控制器,只处理HTTP和HTML—处理表单、验证和UI逻辑
- 我们将有一个无状态业务逻辑服务层,它实现通用算法或逻辑,不知道UI,但非常清楚(并委托给)域模型
- 我们将有一个更丰富的域模型,其中包含该域模型中对象固有的状态、关系和逻辑
- 我们是否希望将DAO注入域对象,以便它们可以在save()方法中执行“this.someDao.save(this)”操作?这有点尴尬,因为域对象不是单例对象,所以我们需要DAO的工厂或后期构造设置。从数据库加载实体时,这会变得很混乱。我知道SpringAOP可以用于此,但我无法让它工作(使用Play!framework,另一系列实验),而且它看起来相当混乱和神奇 我们是否将DAOS(存储库)与完全无状态的业务逻辑服务保持完全分离?这可能有点道理,但这意味着如果“保存”或“删除”是域对象的固有操作,则域对象无法表达这些操作
- 我们是否完全不使用DAO,而是使用JPA让实体自行管理
Martin我不是Java专家,但我在.NET代码中使用了NHibernate,因此我的经验应该可以直接翻译到Java世界 当使用ORM(如您提到的Hibernate)构建域驱动的设计应用程序时,一个好的(我不会说是最佳的)实践是在UI和域之间创建所谓的应用程序服务。它们类似于您提到的无状态业务对象,但应该几乎不包含任何逻辑。它们应该是这样的:
public void SayHello(int id, String helloString)
{
SomeDomainObject target = domainObjectRepository.findById(id); //This uses Hibernate to load the object.
target.sayHello(helloString); //There is a single domain object method invocation per application service method.
domainObjectRepository.Save(target); //This one is optional. Hibernate should already know that this object needs saving because it tracks changes.
}
对DomainObject包含的对象的任何更改(也向集合添加对象)都将由Hibernate处理
您还需要某种AOP来拦截应用程序服务方法调用,并在方法执行之前创建Hibernate会话,并在方法完成后保存更改,无异常
有一个非常好的示例,说明如何在Java中进行DDD。它基于Eric Evans的样本问题。应用程序逻辑类示例代码是。您的问题和疑问在这里敲响了一个有趣的警钟,我认为您对“富域模型”的解释有点过头了。丰富性并不意味着持久性逻辑必须由域对象处理,换句话说,不,它们不应该知道如何保存和删除它们自己(至少不是明确地,尽管Hibernate实际上透明地添加了一些持久性逻辑)。这通常被称为持续无知 我建议您保留现有的DAO注入系统(对于单元测试来说,这是一件好事),保持持久性层不变,同时尝试将一些业务逻辑移动到适合的实体中。一个很好的起点是识别聚合并建立聚合根。它们通常包含比其他实体更多的业务逻辑
然而,这并不是说域对象应该包含所有逻辑(特别是不包含应用程序中许多其他对象所需的逻辑,这些对象通常属于服务)。根据域驱动设计,域对象应该是持久性无关的。好吧,公平点。但是看看我问题的最后一部分:类似Hibernate/JPA的东西使持久性的处理变得更加容易。然而,如果我们在域模型上这样做,那么它就内置了这种逻辑。如果我们不这样做,那么我们要么完全放弃ORM,要么在它们之间有一个“映射”对象和“域”对象以及数据映射器的并行层次结构