在阅读Evan和Nilsson的书籍后,我仍然不确定如何管理域驱动项目中的数据访问。如果CRUD方法是存储库的一部分,即OrderRepository.GetOrdersByCustomer(customer),或者它们应该是实体的一部分:Customer.GetOrders()。后一种方法看起来更多OO,但它将为多个对象(即Customer.GetOrders(),Invoice.GetOrders(),ShipmentBatch.GetOrders()等)中的单个实体类型分配数据访问。怎么样插入和更新?DDD中的数据访问?
回答
CRUD-ish方法应该是Repository的一部分...... ish。但我想你应该问为什么你有一堆CRUD方法。他们真的是吗?他们是什么真的是?如果您实际调用应用程序使用的数据访问模式,我认为这会使存储库更加有用,并且在您的域发生某些类型的更改时,不必进行霰弹枪手术。
CustomerRepo.GetThoseWhoHaventPaidTheirBill()
// or
GetCustomer(new HaventPaidBillSpecification())
// is better than
foreach (var customer in GetCustomer()) {
/* logic leaking all over the floor */
}
“保存”类型的方法也应该是存储库的一部分。
如果您拥有聚合根,这可以防止存储库爆炸或逻辑分散:您没有4 x个实体数据访问模式,只是您实际在聚合中使用的实体根。
这是我的$ .02。
即使在DDD中,我也会将数据访问类和例程与实体分开。
的原因是,
- 可测性提高的担忧
- 分离和模块化设计
- 从长远来看更容易维护,当您添加的实体,例程
我不是专家, 只是我的观点。
Nilsson的应用DDD & P令人讨厌的事情是,他总是以“我不会在真实世界的应用程序中这样做,但......”然后他的例子如下。返回主题:我认为OrderRepository.GetOrdersByCustomer(customer)是要走的路,但也有关于DDD的ALT.Net邮件列表(http://tech.groups.yahoo.com/group/altdotnet/)的讨论。
我已经完成了你所说的两种方式,现在我的首选方法是持续的无知(或PONO - Plain Ole'.Net对象)方法,其中你的域类只担心是域类。他们不知道他们如何坚持或甚至是坚持不懈。当然,你必须时时务实,并且允许诸如Id之类的东西(但是即使如此,我也只是使用了具有Id的图层超类型,所以我可以拥有一个像默认值一样的单个点)
主要原因是我努力遵循单一责任原则。通过遵循这个原则,我发现我的代码更具可测试性和可维护性。在需要时进行更改也容易得多,因为我只有一件事需要考虑。
有一点需要注意的是存储库可能遭受的方法膨胀。 GetOrderbyCustomer.GetAllOrders.GetOrders30DaysOld ..等等。这个问题的一个很好的解决方案是查看查询对象模式。然后你的仓库可以接受一个查询对象来执行。
我也强烈建议寻找像NHibernate的东西。它包含许多使存储库如此有用的概念(标识映射,高速缓存,查询对象..)
DDD通常优先于您使用Customer.Save提示的活动记录模式的存储库模式。
Active Record模型的一个缺点是它几乎假设一个持久性模型,除了一些特别侵入性的代码(在大多数语言中)。
存储库接口在域图层中定义,但不知道数据是否存储在数据库中。使用存储库模式,我可以创建一个InMemoryRepository,以便我可以孤立地测试域逻辑,并在应用程序中使用依赖注入来让服务层实例化一个SqlRepository。
对很多人来说,拥有专门用于测试的特殊存储库听起来很愚蠢,但是如果使用存储库模型,您可能会发现您并不需要特定应用程序的数据库;有时候一个简单的FileRepository会起作用。在知道需要数据库之前将自己嫁接到数据库可能会受到限制。即使数据库是必需的,对InMemoryRepository运行测试也要快很多。
如果你没有太多的领域逻辑,你可能不需要DDD。 ActiveRecord非常适用于很多问题,特别是如果您主要有数据和一点逻辑。
让我们退后一秒。 Evans建议存储库返回聚合根,而不仅仅是实体。因此,假设您的客户是一个包含订单的聚合根,那么当您从其存储库中提取客户时,订单就会随之而来。您将通过浏览客户与订单之间的关系来访问订单。
customer.Orders;
因此,要回答您的问题,CRUD操作存在于聚合根存储库中。
CustomerRepository.Add(customer);
CustomerRepository.Get(customerID);
CustomerRepository.Save(customer);
CustomerRepository.Delete(customer);
- 1. DDD中的非业务逻辑数据库访问
- 2. 在DDD中打包访问权限?
- 3. 如何使用actor来访问数据库和DDD?
- 4. DDD:域事件应该如何访问Web请求数据?
- 5. 访问数据访问层中的HttpContext.Current
- 6. DDD - 从实体访问存储库,
- 7. 访问Yii2中的数据
- 8. 访问数据
- 9. 访问数据
- 10. 访问数据
- 11. 访问数据
- 12. 访问数据
- 13. 访问数据
- 14. 访问数据(“”)
- 15. 访问数据
- 16. 访问数据
- 17. 访问数据
- 18. asp.net MVC ddd DRY vs松散耦合和持久性/数据访问层
- 19. 访问Facebook的数据 - 离线访问
- 20. 在JSON中访问数据
- 21. 数据库数据访问
- 22. 访问多维数组中的数据
- 23. 访问对象中的数组数据
- 24. VB.net访问数据库中的行数
- 25. 无法访问数组中的数据
- 26. 访问数组中的数据
- 27. 访问EXIF数据
- 28. 访问ORM数据
- 29. 数据库访问
- 30. 访问USB数据