带集合的ORM类;试图保持专注于父母而不是孩子

时间:2009-05-18 18:35:15

标签: web-applications orm collections oop

假设我有一个农民阶级,一个农民有一群猪。

如果我使用像Hibernate这样的ORM,我可以将更新级联到Farmer's Pig集合中,这样我就可以从我的控制器中做到这样的事情:

Pig pig = new Pig("Charlie");
farmer.addPig(pig);
farmerService.save(farmer);

我的农民服务对Pigs一无所知。根据应用程序的要求,我甚至可能根本不需要Pig DAO。我只关心农民。

很酷,但当猪变成培根时会发生什么?

farmer.removePig(pig);
farmerService.save(farmer);

这里的问题是,在无状态的Web应用程序中,我需要一些方法来创建一个Pig,我将传递给Farmer的removePig方法。

我能做到:

// manual search Farmer's collection - requires loading all pigs.
// Yes, I could just pass id to removePig, but it confuses the example
pig = farmer.getPigById(id);
farmer.removePig(pig);
farmerService.save(farmer);

// loads up a pig, and hopefully it belongs to the farmer
pig = farmerService.getPigById(id);
farmer.removePig(pig);
farmerService.save(farmer);

后者似乎更好,但是如果我要在我的farmerService中添加一个getPigById()方法,我可能也只有一个savePig()方法。这会把焦点从农民变成猪。

pig = farmerService.getPigById(id);
farmerService.removePig(pig);

啊哈,看起来代码更少。然而,它违背了想要与农民及其养猪集合合作的逻辑观点,而不是个体猪。我不再明确地从农民身上移除一头猪,这一切都是隐含的和倒退的。

我似乎经常遇到这个问题。应该关注的类是Farmer。猪是次要的。但是,如果没有滑下斜坡进入单独的猪群,那么很难对猪群进行处理,这些猪的变化只会在农民从持久性中重新加载时反映出来。

在这件事上你能给我什么建议?

1 个答案:

答案 0 :(得分:1)

在场景中,我倾向于倾向于你的第二种方法。您处于较少环境状态的事实不应该反映在您的对象模型中,只会以您在特定http请求中恢复状态的方式反映出来。这是在这里完成的:

pig = farmerService.getPigById(id);

此代码应出现在控制器中(在MVC或MVP模式中)。然后其他代码继续像往常一样:

farmer.removePig(pig);
farmerService.save(farmer);

处理当前请求的特定控制器应负责维护当前正在考虑的猪的状态。它应该负责将一个pig id发送到浏览器,并负责将这个pig id转换为pig对象。它的方式是它自己的,但使用农民服务的呼吁是最有意义的。从这里开始,您可以通过一般的id-to-object调用进一步自动执行此转换,反之亦然。

您认为此域模型应该以农民为中心是正确的,并且与域驱动设计一致。在这种情况下,农民类是猪的集合,因此定义了一组猪的边界。所有的猪都应该通过农民进入。通过这种方式,您可以清楚地了解如何创建和销毁和修改猪。因此,你的最后一种方法并不像以前那样健全。