DDD存储库:使用DAO进行分离?

Mic*_*ble 1 dao domain-driven-design repository-pattern

关于存储库,它们在stackoverflow和整个Web上的使用和布局存在争议性的讨论.我对如何有效地实现存储库后面的数据访问抽象(例如数据库)感到困惑.

我没有使用ORM工具/框架,因为我想亲眼看到细节.目前我正在使用DAO对象访问(mysql)数据库并提供Business Objects(域对象).由数据库表中的外键给出的关联被解析并加载到相应对象的DAO中(当前没有延迟加载).由于我不想直接在业务逻辑中使用我的数据库DAO,因此我认为存储库是一个很好的进一步抽象.当我在Repository中实现像GetEmployeesByShopAndPosition()这样的复杂查询时,我遇到了困难:我看到了实现这个的两种可能性:

  1. 暴力破解:使用员工DAO并将所有员工作为业务对象(包括关联的商店/职位)从数据库加载到存储库的集合中.迭代收集并返回在给定的商店和位置工作的员工.
  2. 高效:实现连接相关表的数据库查询,并仅返回EmployeeDAO中where where子句所需的Employees.

第一种方法使用了存储库实际应具有的集合性质,但似乎效率非常低.第二种方法生成一个膨胀的DAO,但效率更高.

我的问题:

  1. 这里更喜欢什么或者在实践中如何完成?
  2. 我错了,存储库不应该与DAO一起使用,数据库相关的代码可以直接进入存储库吗?
  3. 当存储库处理聚合时,它是否应该实际组装相关的外键来构建(完整)Business Objects而不是我当前使用的DAO?

我知道这个主题不是黑/白,因为所涉及的设计模式也可以以不同的方式实现,但我想有一些指导方针不应该被打破或混淆以分离关注点和持久性无知(PI).

Ebe*_*oux 5

你实际上在这里问了很多问题所以我会尽量保持答案尽可能简洁:)

存储库返回一个Aggregate Root或一个Entity.有些人非常坚持认为存储库只能返回AR,这很好并且总是足够的.

有两种类型的存储库(Vaughn Vernon在他的实现领域驱动设计书中很好地描述了它):

  • 集合为本
  • 持久性为导向

您可能会遇到并更频繁地使用面向持久性的方法.这可能是在DAO中出现混乱的地方.当然,DAO可以返回一个业务对象,但它可能会返回更多.

您的查询示例是DAO可能更合适的地方.因此,在域驱动设计领域,您会经常遇到CQRS(命令/查询责任隔离).归结为查询您的域名.

您应该拥有一个精简的专用查询层,以最合适的格式返回结果(但不是实体).在C#中我用的东西一样DataTable,DataRow,string有时一个复杂的DTO如果需要的话.

存储库仅与AR有关,例如:

  • 得到
  • 去掉

存储库基本上使用各种逻辑DAO(ADO.NET,ORM ---我试图避免使用ORM).

关于使用相关外键检索AR的第二位:AR应该永远不应包含对另一个AR的引用.实体并且Value Objects很好.对于关联的AR,使用ID或值对象来表示外来AR.AR可能由复杂的结构本身组成,但不会将所有权与遏制混淆.一个OrderLine包含在一个Order.A Customer拥有一个Order.所以Order会有一个OrderLine集合但不是Customer对象的引用(而不是ID/VO).

Order/ OrderLine例子说明了为什么我们不查询域.当我们想要一个给定的开始和结束日期之间的订单列表时,我们可能不会对所有订单数据感兴趣,当然也不会对订单行感兴趣.因此加载这些聚合没有任何意义.这就是在查询域时,懒惰加载等令人讨厌的东西蔓延.懒惰加载不应该存在恕我:) :)一个简单的查询层就足够了.

希望有所帮助.