2

首先,我承认我是 DDD 的新手,需要阅读“蓝皮书”。

我正在构建一个具有“匹配”类型的 AggregateRoot 的系统。每个匹配都可以有一个“投票”集合,并且还有一个只读的“投票计数”属性,当用户对匹配进行投票或否决时,该属性会增加。

由于许多用户可能同时对匹配进行投票,因此必须从匹配中添加/删除投票,并且必须将 VoteCount 作为一个涉及写锁的原子操作增加/减少(由数据库处理锁)。(我需要 VoteCount 作为数据库中的静态值,以便其他进程/组件有效地查询。)

在我看来,如果我坚持严格的 DDD,我会这样编码这个操作:

应用程序服务将接收一个投票请求对象,然后该服务将从匹配存储库中检索匹配对象。然后,该服务将调用匹配对象上的某种方法,以将投票添加到集合中并更新 VoteCount。然后,存储库会将 Match 实例保留回数据库。但是,这种方法对我的应用程序不可行,主要有两个原因,正如我所见:

我在后端使用 MongoDB,无法将此读写操作包装到事务中,以防止对 Match 数据及其关联的 Votes 和 VoteCount 的脏读。

这是非常低效的。我拉回整个对象图只是为了添加一个投票并增加投票计数。尽管这在文档数据库中比在关系数据库中更有效,但我仍在执行不必要的读取操作。

将单个 Vote 对象发送到存储库并对 Mongo 执行一个原子更新语句时,问题 1 和 2 不是问题。

在这种情况下,投票是否可以被视为“聚合”并值得拥有自己的存储库和聚合状态?

4

2 回答 2

2

在这种情况下,投票是否可以被视为“聚合”并值得拥有自己的存储库和聚合状态?

我认为这可能是正确的答案。聚合应该是事务一致性边界。比赛投票之间是否有一致性要求?Match 聚合上的 Vote 集合的存在表明存在。然而,似乎一票与下一票无关。

Instead, I would store each vote individually. This way you can use the aggregate functionality of MongoDB to get the count, though I'm not sure whether it is still slow. If it is, then you can aggregate using the Map/Reduce functionality.

More generally, this may not be a best fit for DDD. If the domain doesn't consist of complex behavior there is hardly a reason to try to adapt the DDD tactical patterns (entity, agreggate) to this domain.

于 2013-02-01T01:02:47.453 回答
1

是的,您可以将Vote建模为自身的聚合。在现实世界中,人们通常会同时为几件事投票。然后聚合将被称为选票而不是投票。你只是有一个特殊情况,一次只有一个项目可以投票。

我不能为 MongoDB 说话(也许其他人可以)——但你可以在 RavenDB 中轻松地做到这一点,例如:

public class Match
{
    public string Id { get; set; }
    public string Name { get; set; } // or whatever
}

public class Vote
{
    public string Id { get; set; }
    public string MatchId { get; set; }
    public string UserId { get; set; }
    public bool YeaOrNay { get; set; } // or whatever
}

然后你只需在你的投票上建立一个 map/reduce 索引来计算结果。

于 2013-02-01T00:35:57.817 回答