Java 在ddd实践中,是否应该将CRUD方法放在模型对象中

Java 在ddd实践中,是否应该将CRUD方法放在模型对象中,java,domain-driven-design,crud,Java,Domain Driven Design,Crud,我试图实践领域驱动设计,代码的基本结构包括以下对象: Action->Facade-> Service Model Repository 您认为CRUD方法应该放在模型中的什么位置,如下所示: order.save(new order()) addOrderFacade.save(new order()) 或者像下面一样放在正面: order.save(new order()) addOrderFacade.save(new order()) 我建议不要把它们放在域类中,因

我试图实践领域驱动设计,代码的基本结构包括以下对象:

Action->Facade->
Service
Model
Repository
您认为CRUD方法应该放在模型中的什么位置,如下所示:

order.save(new order())
addOrderFacade.save(new order())
或者像下面一样放在正面:

order.save(new order())
addOrderFacade.save(new order())

我建议不要把它们放在域类中,因为


您的域类包可以在其他应用程序中的某个地方重用,您的DAO层可能不同,因此最好在DAO的模型上创建另一个层,即属于存储库的“保存”或“删除”方法。通常由服务或命令处理程序调用Save(如果您使用基于命令的方法更新域)。Save从CRUD处理CU,D有自己的方法,R部分是有趣的部分

当R表示“GetEntity”以更新它时,它可以是域存储库(有多个存储库)的一部分,与保存在同一位置处理


但是,如果您想通过读取来显示,basicaly只是将结果返回给用户的查询,那么应该使用专用于查询的不同存储库以及简化的只读模型。可以从控制器甚至UI调用此repo。

惯例是将CRUD方法放在存储库或服务层中,而不是放在模型中。事实上,当使用Spring或Hibernate等框架时,您会被引诱使用这种方法。仅出于这个原因,通常更容易:

  • 其他开发人员也希望如此
  • 框架支持它
  • 教程和示例假定了这一点
然而,从设计角度来看,有充分的理由反对这种方法。它导致了一个,换句话说,只有状态而没有行为的对象(结构),公平地说,它不是非常面向对象的。需要通过视图、控制器、服务和存储库层传递大量数据,并且需要大量“开销”代码来将状态和行为结合在一起。缺乏对规范化模型层的关注也可能导致团队之间的模型不匹配、支离破碎

埃里克·埃文斯(Eric Evans)经常这样定义一种试图避免这种设计陷阱的方法。请注意,在DDD中,还有一个地方可以放置服务和存储库,从Wikipedia页面:

  • 服务:当一个操作在概念上不属于任何对象时。按照问题的自然轮廓,您可以在服务中实现这些操作。服务理念在理解上被称为“纯制造”
  • 存储库:检索域对象的方法应委托给专门的存储库对象,以便可以轻松地交换替代存储实现
  • 工厂:创建域对象的方法应该委托给一个专门的工厂对象,这样替代实现就可以很容易地互换

如果您感兴趣,请查看支持DDD的应用程序和(就在下面)DDD示例应用程序。

什么是“CRUD方法”?从持久性存储中持久化/重新水化实体的方法?=>存储库。操作CRUD用例的方法?=>控制器或应用程序服务。作为CRUD操作的结果更新实体的方法=>域层。CRUD操作不会发生在一个层的一种方法中,它们跨越多个层…我不确定这里的相关性。域对象中没有CRUD方法并不一定意味着它是贫血的。除了积垢,你还有很多其他类型的行为。此外,我同意实体的部分创建操作可以在该实体的聚合根中进行。但您肯定不会将聚合根方法直接添加到持久性存储中。这是一个存储库的工作。正如我在回答的开头所指出的,有支持和反对的论点。CRUD方法的位置并不是这里的全部问题。我们需要决定如何划分责任,框架约定(由JavaBeans发起)和开放的面向对象之间存在明显的裂痕。