【问题标题】:Am I breaking my aggregate boundaries in this model?我是否打破了这个模型中的聚合界限?
【发布时间】:2009-07-09 06:37:12
【问题描述】:

我正在使用 NHibernate 为一个非常基本的 ASP.NET MVC 应用程序建模,但我似乎被困在我的设计上。这是我的模型的草图:

如您所见,这是非常基本的,但我对此有些担心。 User 根实体和 Organization 根实体通过两个一对多关系访问同一个 Organization_Users 实体子实体。这似乎不对,我认为我正在打破总体界限。这个模型对我来说很奇怪,但我喜欢这个想法,因为我想要这样的代码:

var user = userRepository.Load(1);
var list = user.Organizations; // All the organizations the user is a part of.

var org = orgRepository.Load(1);
var list = org.Users; // All the users in an organization.

Organization 实体也将使用表中的额外数据(如 flagged 和 role)。这是一个糟糕的设计吗?如果您有任何想法,那就太好了。我仍在努力思考 DDD。谢谢

【问题讨论】:

    标签: nhibernate model domain-driven-design aggregate


    【解决方案1】:

    这是典型的多对多关系。 Organization_Users 表是桥接表。 Infact NHibernate 和所有其他 ORM 工具都内置了支持桥接表的功能。

    这件事应该在数据建模级别而不是在应用程序级别解决。您应该分析您的数据模型,建议避免多对多关系(从某种意义上说,如果不是领域模型的必要性,则应尽量避免多对多关系)。

    首先,您需要确保数据模型中的多对多关系对于映射域实体是必要的。完成此操作后,图表中表示的模型就可以在应用程序级别映射这些关系了

    【讨论】:

      【解决方案2】:

      我曾多次使用类似于您的第一个模型的方法。这种方法的一个问题是您需要在您的域中创建一个 OganizationUser 类来处理您域中的 RoleFlagged 字段。这会让你在代码中留下类似的东西。

      var user = userRepository.Load(1);
      var list = user.OrganizationUsers; // All the organizations the user is a part of including their role and flagged values.
      
      var organization = list[0].Organization; 
      

      *如果您要经常遍历所有用户组织,您可能希望急切加载 Organization 实体以及 OrganzitionUser

      使用您提交的第二个设计,您似乎可以将用户添加到 OrgUserDetails,而无需将用户添加到 OrganizationUser。这似乎不是我想从我的域中支持的东西。

      【讨论】:

      • 非常感谢您的回答。这就是我想要实现这个模型的确切方式。您提出了一个很好的观点,即必须使用相同的信息更新 OrgUserDetails 和 OrganizationUser 并不是一个好主意。我将使用我的第一个模型并将该 OrganizationUser 类(如您所说)添加到我的 Organization 域中,以便我可以访问这些额外的属性。看起来这会很好。再次感谢您的帮助!
      【解决方案3】:

      在 DDD 中首先要考虑的是:

      • 忘记您的数据库架构(有 没有数据库!)
      • 从领域的角度来看,您将对这些实体执行哪些操作?

      【讨论】:

      • 直到您遇到性能问题,然后您才后悔忘记了数据库:)
      【解决方案4】:

      我认为你的模型很好。当我想到它们时,我通常会想到域聚合根,就公开暴露的内容而言,而不是内部实现。对于关系,我会想到关系中哪个实体“穿裤子”。也就是说,将用户添加到组织还是将组织添加到用户更自然?在这种情况下,两者都可能有意义,用户加入组织;组织接受用户的成员资格。

      如果您的域从用户的角度来看关系,您可以将维护(添加、删除等)关系的方法放在用户上,并在组织上公开只读集合。

      针对您的第二个设计(如果您编辑了原始问题会更好):我一点也不喜欢它。你原来的设计很好。在设计您的类时,我不一定会忽略数据库,一个好的设计应该准确地对域进行建模并且可以直接在关系数据库中实现。有时您必须在两个方向上妥协才能达到最佳效果。打破聚合界限不会被判入狱。 :-)

      【讨论】:

      • 感谢您的意见。是的,现在我看到第二个设计我也真的不喜欢它! :)
      【解决方案5】:

      我的理解是:

      一个用户可以属于 0 对多的组织。 和 一个组织由 0 对多的用户组成。

      这两个都对吗?如果是这样,那听起来对我来说确实是多对多。

      在多对多中,您几乎需要某种类似关系的对象来弥补这一差距。问题是,域中没有 user_organization。

      这让我认为您不应该将 user_organization 作为您的域的一部分,就其本身而言。感觉像是一个实现细节。

      另一方面,也许在您的域中拥有一个名册是有意义的,该名册将用户保存在组织中并存储他们的角色和特定于该关系的其他信息。

      【讨论】:

        【解决方案6】:

        感谢大家的回答。他们非常有帮助。

        当我更多地考虑我的模型时,我画了一些我认为会更好的新东西。

        我的想法是这样的:

        1. 当用户登录网站时,系统会找到他们的帐户,然后返回他们所属的组织列表,并从 user_organizations 对象中获取此信息。

        2. 当用户点击他们所属的组织之一时,它会将他们定向到该组织的控制面板。

        3. 然后,所选组织在其 org_user_details 中查找该用户的角色,以了解该用户对该组织控制面板的访问权限。

        这有意义吗? :)

        我觉得这在模型中会很好,但我对数据库的实现有些怀疑。我知道我什至不应该担心它,但我还不能改掉我的坏习惯!您可以看到 user_organizations 对象和 org_user_details 对象中存在某种重复数据。我不是数据库专家,但这是一个糟糕的数据库设计吗?我是否应该将 user_organizations 和 org_user_details 中的数据合并到一个表格中,就像我第一篇文章中的表格一样,然后告诉 NHibernate 用户将其视为多对多关系,而组织将其视为一对多关系?这听起来像是我在欺骗系统。抱歉,如果我对此感到很困惑。

        您对此有何看法?我是不是想太多了? :P

        【讨论】:

        • 跑题了,但我无法抗拒......你用哪支笔画了这个图表?
        • 大声笑,没问题。我用的是一支Sharpie细尖笔。我认为它会很好地拍照。我想它工作正常。不如类或 UML 图好! :)
        猜你喜欢
        • 2019-07-18
        • 1970-01-01
        • 2015-06-20
        • 1970-01-01
        • 2011-07-27
        • 1970-01-01
        • 1970-01-01
        • 2015-03-05
        • 1970-01-01
        相关资源
        最近更新 更多