DDD示例:CargoRepository.Store()可以在控制器中使用吗?

时间:2011-03-06 23:22:32

标签: architecture domain-driven-design encapsulation

我正在查看来自http://code.google.com/p/ndddsample的优秀NDDDSample源,以了解DDD。与某些东西混淆了

CargoRepository有一个Find()方法,由BookingService.AssignCargoToRoute()和CargoTrackingController.Search()调用:

Cargo cargo = CargoRepository.Find(trackingId);

CargoRepository还有一个从BookingService.AssignCargoToRoute()调用的Store()方法:

Cargo cargo = cargoRepository.Find(trackingId);
if (cargo == null)
{
    throw new ArgumentException("Can't assign itinerary to non-existing cargo " + trackingId);
}

cargo.AssignToRoute(itinerary);
cargoRepository.Store(cargo);

我的困惑是,似乎没有什么可以阻止CargoTrackingController调用CargoRepository.Store(),它会绕过BookingService.AssignCargoToRoute()中的业务逻辑

为什么DDD允许这样做?是否应将存储库拆分为两个,一个用于读取应用程序/ ui /域/服务,另一个用于写入域/服务?

3 个答案:

答案 0 :(得分:2)

在DDD中,服务不是所有业务逻辑的持有者。它们只代表与多个对象交叉关注的动词,域的行为,因此在不破坏单一责任原则的情况下不会适合其中一个实体或聚合根,并创建可能混淆实体的紧密耦合。

在您的示例中,Cargo.AssignToRoute(行程)和BookingService.AssignCargoToRoute()似乎是多余的。这两种将货物绑定到路线的方式的存在造成了混乱。您可以保留其中任何一个,具体取决于您是否认为货物为自己分配路线负责,或者使用不属于该实体的功能使实体超载。

除此之外,Controller直接调用Repository方法是完全合法的。服务不是控制器的单一访问点。

答案 1 :(得分:1)

嗯,我猜这就是CQRS想要实现的目标。

当然在这种情况下绕过BL是一个坏主意(显然很容易实现,甚至更糟)。但是你只是不能在代码中强制执行所有规则,有些只会保留代码中未明确声明的约定。一些不好的事情可能很难,但仍然不是不可能实现的,而且总会有很多愚蠢的错误。编程就是这样:你必须考虑你真正在做什么,否则没有像DDD这样的指导方针可以帮助你实现目标。

答案 2 :(得分:1)

需要在持久性层和服务层中分离应用程序,以帮助您作为开发人员维护一些易于理解和维护的结构,开发人员有责任遵循某些模式并正确使用代码。

这不是限制您(开发人员)使用它的框架不正确,DDD是设计模式(如何组织您的应用程序结构的指导)。