基本综合问题

发布于 2024-11-30 03:04:19 字数 228 浏览 0 评论 0原文

是否允许客户端代码引用非根聚合中的实体?我有一个Story(根)、Team(实体)和TeamMember(实体)。我试图确定 AddTeamMember 方法是否属于 TeamStory

我想我的例子有点误导。我真正的问题是客户端代码可以引用聚合中的非根实体吗?

Is client code allowed to reference entities within an aggregate that is not the root? I have a Story (Root), Team (Entity) and TeamMember (Entity). I am trying to decided if the AddTeamMember method belongs on the Team or Story.

I guess my example was a little mis-leading. My real question is can client code reference non-root entities within an aggregate?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

葬心 2024-12-07 03:04:19

我的意见 - 不应该。引用属于某个聚合的实体意味着您可以在没有完整聚合上下文的情况下调用该实体上的方法,如果您允许这样做,您将永远无法确定整个聚合是否有效且一致。

简单的示例:

    public class MyAggregateRoot
    {
        protected MyEntity entity;

        public void BuildUpAggregate()
        {
            ValidateSomeRule();
            LoadEntityFromDatabase();
        }

        public MyEntity MyEntity
        {
            get 
            {
                VerifySomeOtherRule();
                return entity; 
            }
        }
    }

如您所见,在通过聚合根构建和检索 MyEntity 时,我们检查了两个验证规则 - 如果您允许客户端直接引用 MyEntity,则聚合可能会在客户端检索实体和执行操作之间的时间发生变化它,因此支票将不再有效,但您甚至不会意识到这一事实。换句话说,您的聚合将不一致并且可能无效。

一般来说,在 DDD 中有一条强有力的规则,规定对聚合中的实体的所有访问都应该通过从聚合根开始遍历来执行——这条规则正是为了聚合的一致性。

也就是说,您的客户端可以引用的是实体的投影 - 一种只读副本,其中仅包含显示和决定特定操作在当前上下文中是否可用所需的数据。您可以更进一步,将一组实体中的数据聚合到单个投影中,稍微调整一下,以便根据 UI 的要求进行定制。我发现这种技术非常有用,因为它不允许我的 UI 决定如何对业务领域进行建模。

My opinion - it should not. Having a reference to an entity that belongs to certain aggregate means that you are able to invoke a method on that entity without full aggregate context and if you allow that, you can never be sure if your entire aggregate is valid and consistent.

Simple example:

    public class MyAggregateRoot
    {
        protected MyEntity entity;

        public void BuildUpAggregate()
        {
            ValidateSomeRule();
            LoadEntityFromDatabase();
        }

        public MyEntity MyEntity
        {
            get 
            {
                VerifySomeOtherRule();
                return entity; 
            }
        }
    }

As you can see, while building and retrieving MyEntity via aggregate root we have two validation rules checked - if you would allow the client to reference MyEntity directly, the aggregate might change in time between client retrieved the entity and performed an operation on it, so the checks would no longer be valid, but you wouldn't event be aware of this fact. In other words, your aggregate would be inconsistent and potentially invalid.

In general, in DDD there's a strong rule that states that all access to entities in aggregate should be performed by traversing from the aggregate root - this rule is exactly for the sake of consistency of aggregates.

That said, what your client can reference is a projection of an entity - a sort of read-only copy that contains only data required for displaying and deciding whether a certain action is available in current context. You can go even further and aggregate the data from a set of entities to a single projection, tune it up a little, so it would be tailored to the requirements of UI. I found this technique quite useful for not allowing my UI to decide how the business domain should be modeled.

楠木可依 2024-12-07 03:04:19

在不知道您的架构应该如何工作的情况下,听起来它应该在Team而不是Story上进行。假设您有一个从 TeamTeam Member 的一对多关系,并且 Team MemberTeam 的子级code> 对象,而不是 Story

Without knowing how your architecture is supposed to work, it sounds like it should go on Team instead of Story. That's assuming you have a 1 to many from Team to Team Member, and that Team Member is a child of the Team object, not Story.

蓝眼睛不忧郁 2024-12-07 03:04:19

我不确定“根”或“聚合”规则,但我认为故事不应该知道如何管理团队成员资格。

I'm not sure about 'root' or 'aggregate' rules but I don't think a Story should know anything about how a Team's membership is managed.

夕嗳→ 2024-12-07 03:04:19

团队应该与团队成员有“有”关系。其中故事和团队成员彼此没有直接关系。

你的类应该如下所示:

class team
{
list<TeamMember> teamMembers;
void AddTeamMember(TeamMember member){}
}

团队必须有添加团队成员方法的另一个原因,如果该方法是故事的一部分,那么你必须明确提及你想要在哪个团队中添加成员。

addteamMember(Team T, TeamMember member);

根应该提供正确的方法来访问非根元素(第一层嵌套)。在您的情况下,团队应该有 addTeamMember 方法,而故事应该有一个方法 (AddMemberToTeam(team t, teammember m)) 调用指定团队的 addTeamMember 方法。

Team should have "has a" relationship with Team member. where as story and team member are not directly related to each other.

your class should look like:

class team
{
list<TeamMember> teamMembers;
void AddTeamMember(TeamMember member){}
}

another reason why Team must have add team member method, if the method is part of story then you have to explicitly mention in which team you want to add member.

addteamMember(Team T, TeamMember member);

Root should provide proper methods to access non root elements(first level of nesting). In your case Team should have addTeamMember method and story should have a method (AddMemberToTeam(team t, teammember m)) which calls addTeamMember method of specified team.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文