DDD聚合和根聚合创建的有效建模


v-star*위위
2025-03-18 09:16:00 (21天前)
  1. 是那个


商业
</跨度>
设想针对每项任务提出了大量意见。

由于每个注释都与一个任务相关,因此注释需要将外键保存回任务 好吧将此责任推送到域服务CreateProjectFromTemplate()中的方法

编排
</跨度>
每个存储库的单独对象的创建和持久性?
是方法

3 条回复
  1. 0# 滔滔江水 | 2019-08-31 10-32



    这是一个不同的视角,可能会让你摆脱僵局。



    我觉得你正在做数据建模而不是真正的域建模。您关注的是使用ORM(EF)直接持久化的关系模型,而不太关心实际的问题域。这就是为什么你担心项目会加载太多东西,或者哪些对象会将外键保存到什么东西。



    另一种方法是暂时忘记持久性并专注于可能需要什么责任的事情。有责任我不是指保存/加载/搜索等技术问题,而是域定义的东西。就像创建任务,完成任务,添加评论等一样。这应该给你一个大纲,比如:




    1. interface Task {

      void CompleteBy(User user);

      }

    2. interface Project {

      Workstream CreateWorkstreamFrom(Template template);

      }

    3. </code>


    此外,不要过分关注什么是实体,值对象,聚合根。首先,以您和您的同事满意的方式正确地代表您的业务。这是重要的部分。尝试与非技术人员讨论您的模型,看看您使用的语言是否合适,是否可以与之进行对话。你可以决定

    后来

    什么对象是实体或价值对象,那部分纯粹是技术性的,不那么重要。



    另一点:不要将模型直接绑定到ORM。 ORM是钝器,可能会迫使你做出糟糕的决定。您可以

    使用

    域对象中的ORM,但不要使它们成为一个

    部分

    ORM。这样,您可以以正确的方式执行您的域,并且不必害怕为特定功能加载太多。您可以为所有业务功能做正确的事情。


  2. 1# 咿呀哟 | 2019-08-31 10-32




    团队对这种方法感到不舒服,感觉不对劲。




    这是一个非常好的迹象。




    但是,根据您只能通过其根引用另一个聚合的原则,这是不可能的。




    你会想放下这个想法,它会妨碍你。



    简短的回答是标识符不是引用。持有另一个实体的标识符副本是可以的。



    更长的答案:DDD基于埃里克埃文斯的工作,埃里克埃文斯正在描述一种在千禧年开始时为他的Java项目工作的风格。



    他遇到的痛苦是:如果应用程序允许对象引用

    随意

    数据实体,然后域的行为最终散布在整个代码库中。这会增加您理解域所需的工作量,并且会增加制作(和测试!)更改的成本。



    反应是引入一门学科;通过限制应用程序访问一些精心约束的门守护者(“聚合根”对象)来隔离应用程序中的数据。该应用程序可以容纳

    对象引用

    到根对象,并且可以向那些根对象发送消息,但是应用程序不能持有引用,或者直接发送消息给隐藏在聚合的api后面的对象。



    相反,应用程序向根对象发送消息,然后根对象可以将消息转发给其自己的聚合中的其他实体。



    因此,如果我们想要向某个Project内部的Task发送消息,我们需要一些机制来了解

    哪一个

    要加载的项目,以便我们可以将消息发送到项目以向Task发送消息。



    实际上,这意味着你需要一个可以接受TaskId的函数,并返回相应的ProjectId。



    最简单的方法是简单地将两个字段存储在一起




    1. {
      taskId: 67890,
      projectId: 12345
      }

    2. </code>



    我认为逻辑创建项目应该是创建项目,向项目添加一个或多个工作流,向工作流添加任务,然后让EF处理持久化的对象结构。



    也许关注的是对象结构受到我们如何在只读中呈现数据的影响




    这里有一种气味,就是你在描述数据结构的关系。聚合不是由关系定义的,而是它们的变化。




    是否可以将此责任推送到域服务CreateProjectFromTemplate中的方法




    有一个草稿聚合(理解编辑)与已发布的聚合(理解使用)是分开的,这实际上是很正常的。域驱动设计的一部分是

    改善业务

    通过注意用例之间的隐含边界并使它们显式化。





    可以

    使用域服务从模板创建项目,但在常见的情况下,我的猜测是你应该“手工” - 从草稿中复制状态,然后发送使用该状态来创建项目;当发布和编辑同时发生时,它避免了混淆。


登录 后才能参与评论