【问题标题】:How to deal with a value object that needs to look up data in the database如何处理需要在数据库中查找数据的值对象
【发布时间】:2009-02-17 21:46:45
【问题描述】:

我刚开始研究领域驱动设计,很可能我对实体/价值划分的理解是错误的,所以如果是这样,请告诉我。

据我了解,由于其身份完全由其属性定义,因此 Address 是典型的值对象。据我了解,这意味着不应该有单独的存储库或地址的数据访问对象。

这给我带来了两难境地,因为在我的例子中,地址包含一个国家,其中一个国家有一个名称和一个国家代码,并且应该从数据库中加载国家代码列表。

我的问题是,我该如何设计这个?我希望人们能够使用 new 运算符创建地址,但我不想为国家/地区创建数据访问对象,如果我这样做了,我当然不想在地址对象中引用它。

我有一些想法,但我想听听任何人可能有的任何建议。

【问题讨论】:

    标签: architecture domain-driven-design


    【解决方案1】:

    DDD 中没有任何内容阻止值对象持有对实体的引用。因此,您的地址将引用国家实体。

    【讨论】:

    • 也许吧,但鉴于在我的域内它仅用于地址,将 Country 设为实体似乎是错误的
    • 另外我不知道如何实现。如果我允许人们新建地址对象,那么地址对象将需要引用国家 DAO 的实现,这违反了一些严重的 DI 原则
    • 为什么地址需要知道关于 DAO 的东西。只需拥有一个国家财产,让客户处理必须找到一个国家的问题。当使用 hibernate 作为存储库/DAO 时,这种东西是微不足道的,因为它会确保在从数据库加载地址时获得一个国家/地区。
    【解决方案2】:

    首先我要说的是,我对域驱动设计的唯一经验是几分钟前阅读了 Wikipedia 文章。话虽如此,以下是我对您的问题的看法:

    我同意地址对象不应该需要任何数据访问对象,那么处理国家代码并根据用户输入构建地址对象的地址工厂怎么样?这样,工厂将保存数据访问对象,而您的地址对象可以保持值唯一。

    如果这不符合 DDD 规定,请告诉我。我很想知道社区的其他人会怎么想。

    【讨论】:

    • 不确定这如何与 DDD 啮合,我认为它很好。这与我的想法相似,尽管我只是让 Address 类从应用程序启动时设置的静态 Country 列表管理它。我想我更喜欢你的。
    【解决方案3】:

    采用 DDD 方式,您会首先考虑应用程序的需求,然后从那里构建模型。

    您不必担心 Country 仅在 Address 中使用。使其成为实体本身并没有错。主要问题是:您认为国家是具有身份的事物,还是仅由属性定义?如果您有两个具有相同名称(和相同国家代码)的国家/地区,您能看出有什么区别吗?

    也许您应该考虑将 Country 设为值对象。它不会阻止您从数据库中加载一些国家/地区的存储库列表,或根据其代码加载国家/地区。在实施方面,您的存储库仍然可以从数据库中加载国家列表一次并将其缓存在内存中。或者它可以对其进行硬编码,或者从 XML 中读取。您的域模型不会在意。

    您可能会在 Address 上创建一个工厂方法,该方法接受国家代码以及其他参数。然后它会使用存储库创建一个 Country 实例并返回一个正确的 Address 对象。

    考虑聚合也可以产生一些关于存储库布局的想法。

    希望对你有帮助

    【讨论】:

    • 可以,非常感谢。它与我的想法一致。您认为地址是可新建的还是只能通过包含国家/地区列表的 AddressFactory 创建?
    • 嗯,Eric Evans 喜欢看到他的构造函数非常简单。在这种情况下,国家查找可能是工厂方法的工作,而不是构造函数。我对此还没有强烈的看法。
    【解决方案4】:

    这让我陷入两难境地,因为 我的情况下,地址包含国家 一个国家有一个名字和一个 国家代码和列表 应该加载国家代码 从数据库中输入。

    Address 对象不会将国家列表作为其属性。相反,它将具有国家对象的单个实例。表示层将提供 Country 对象列表,可能位于下拉列表中。在加载一个特定地址时,您可以将下拉列表的值设置为国家对象的国家 ID,该国家对象是地址对象的一个​​属性。换句话说:

    myDropDown 的(包含 Country 对象列表)选定对象值 = address.Country 或者myDropDown的键值=address.Country.ID

    现在,要填充表示层,您的数据访问层应该提供一个函数,该函数返回 Country 对象的原始列表。在 .NET 方式中,它类似于:

    Namespace Dal
    
        Public NotInheritable Class Countries
        ...
        Public Shared Function Read(ByVal countryId as Integer) As BusinessObjects.Country
        ...
        Public Shared Function ReadList() As List(Of BusinessObjects.Country)
        ...
    

    【讨论】:

    • 我只是在设计领域模型,而不是规定如何使用它。问题是用户可以创建新的 Country 对象,但如果他们这样做了,我如何确保它处于有效状态?
    • 这种方法做了太多假设。我不能假设会有一个表示层可以访问您的国家/地区列表。就像我说的,值对象的数据访问对象似乎是错误的......
    猜你喜欢
    • 1970-01-01
    • 2012-02-18
    • 2011-01-26
    • 1970-01-01
    • 1970-01-01
    • 2020-04-07
    • 1970-01-01
    • 2015-02-14
    • 2023-03-04
    相关资源
    最近更新 更多