在域驱动设计(DDD)中建模查找表的实用方法是什么?

Joh*_*ohn 43 lookup domain-driven-design

我刚刚学习DDD(Eric Evans的书在我面前开放),我遇到了一个我无法找到答案的问题.当您只是想获得一个简单的查找记录列表时,您在DDD中做了什么?

防爆.

EmployeeID:123
EmployeeName:John Doe
State:Alaska(下拉列表)
县:Wasilla(下拉 - 将根据州进行过滤).

例如,假设您有一个Employee域对象,一个IEmployeeRepository接口和一个EmployeeRepository类.UI将使用它来显示员工列表和个人详细信息.在UI中,您希望使用员工所在州和郡的下拉列表.将根据选择的状态筛选可用县.

不幸的是,数据库表和UI看起来非常不同.在tblEmployees中,它包含州代码= AK和县代码= 02130,而不是州和县名称.

旧的方式(在我开始此DDD任务之前)将非常简单,只需创建2个查询并使用DataReader填充下拉列表.下拉列表中显示的下方是值,它会自动用于表单帖子.

但是,对于DDD,我不确定你应该怎么做.我首先开始创建State和County对象以及存储库的存储库和接口.但是,编写4个类+2个接口以及hbm.xml文件和Employee Business对象中的管道对于2个下拉列表的2个查询来说似乎有些过分.必须有更好的方法,不是吗?我不会很快改变州或县表中的记录,即使我这样做,也不会通过这个应用程序.因此,如果我不需要,我真的不想为State和County创建业务对象.

我看到的最简单的解决方案是使用返回字典的方法创建一个辅助类,例如GetStatesAll(),GetState()和GetCounties()以及GetCounty(),但从DDD的角度来看,这感觉不对.

请帮忙.如何在没有过度设计的情况下使用DDD只需几个简单的查找?

最终解决方案 我认为我终于通过经验找到了答案,即将GetStates()方法放入自己的Data Access类中,尽管不是存储库类.由于我只进行只读访问,因此我将其放入结构DTO中.由于数据库很小,我把它们完全扔进了一个类,就像下面描述的Todd一样.

我的结论:

  1. 查找表永远不是值对象,因为查找表总是具有标识.如果他们没有身份,你就会有重复,这没有多大意义.
  2. 只读查找表可以有一个存储库,但可能不需要存储库.存储库的目标是通过仅通过聚合强制访问来降低复杂性.通过聚合为您提供了一种确保可以实施业务规则的方法,例如,如果您没有汽车,则不会添加轮胎.
  3. 如果您在查找表上允许CRUD维护,那么查找表有自己的存储库是有意义的.
  4. 我最终将代码存储为结构的事实并没有使它们成为"值类型".Fowler在POEAA中说结构是一种价值类型.这是真的,结构是不可变的,这就是福勒说它们是"价值类型"的原因,但是我使用它们的方式不同.我使用结构作为一种轻量级方式来传递DTO,这些DTO在我们最初的创建之后并没有计划改变.事实上,我所使用的结构确实具有同一性,但由于它们是只读的,因此它们起到了结构的作用.
  5. 我一直在使用的一种模式,我在其他地方看不到的是使主键字段不可变.它们由构造函数设置,但它们是只读的(不是私有访问器),并且在创建对象后无法更改.

Dan*_*ger 7

您可能希望研究命令查询分离的概念.我不担心查找值的类型存储库,但我仍然可能使用DTO类型类而不是数据集等...

你可能想花点时间阅读Greg Young的博客,从这一篇到现在.他没有专门讨论填充查找数据,但他经常谈到不通过存储库中的类型化方法处理应用程序的读取/报告功能.


Tod*_*ith 6

使用DDD我有以下类似的东西:

interface IAddressService
{
  IList<Country> GetCountries ();
  IList<State> GetStatesByCountry (string country);
  IList<City> GetCitiesByState (string state);
  // snip
}
Run Code Online (Sandbox Code Playgroud)

Country,State和City是来自数据库中的查找表的值对象.