domain-driven-design - 如何使用 DDD 为 StackOverflow 网站建模

标签 domain-driven-design cqrs event-sourcing

我以 StackOverflow 为例,因为很明显你知道那个网站,而且我的真实用例非常接近。

所以让我们想象一个简化的 SO 域描述:

  • 有用户
  • 用户可以创建新问题
  • 用户可以创建这些问题的答案
  • 用户可以编辑自己的问题和答案
  • 声望超过1000的用户可以编辑其他用户的问题 (随机取那个阈值)

  • 最后一条大胆的规则对我来说很重要。

    我对 AggregateRoot 的理解是它应该包含用于决定接受或拒绝命令的状态,并且它不应该查询数据库来这样做。它保证了应用程序的一致性。它应该只监听它发出的事件以更新其状态。

    现在我认为 SO 域有一个名为 Question 的聚合根。
    然后,该问题将处理以下命令:
  • 创建答案
  • 编辑问题

  • 问题是,当 EditQuestion 被触发时,Question AggregateRoot 如何决定是接受还是拒绝该命令?因为如果您还记得,如果您的声誉 < 1000,如果您尝试编辑另一个用户的问题,该命令应该被拒绝。

    对我来说,问题 AR 维护所有用户声誉的列表似乎没有意义,以便能够知道如何根据该命令采取行动。

    问题是,当我尝试对我的域建模时,我会一遍又一遍地遇到这个建模问题,而且我总是以一个大的 AggregateRoot 告终

    有人可以告诉我我缺少什么并帮助我解决这个问题吗?谢谢

    question似乎在说我们不应该将授权系统放在域模型中。我同意这对于基于角色的身份验证之类的事情可能是实用的。但是,对我来说,“除非有足够的声誉,否则用户无法编辑”确实是一个 SO 业务规则,那么它怎么会在域之外呢?

    重要提示:回答时请考虑您是业务专家 .作为用户,您了解 StackOverflow,并且可以自己猜测 SO 约束是什么。即使你错了,也没什么大不了的:只要为你错误的业务限制提出建议,我就可以了!!!

    这不是我第一次问这种问题,结果总是没有答案,只是无休止的讨论。我想知道的是,如果您必须构建此站点,您将如何对 StackOverflow 进行建模,重点是关于要编辑的最低声誉的业务规则。

    最佳答案

    好吧,IMO 事情很简单(仅在此 SO 场景中)。就是这样会这样做(显然,其他开发人员可能有不同的方法):

    您用“cqrs”很好地标记了问题。在 EditQuestion 处理程序中,我将使用域服务(从 CQRS 的角度来看的查询),它将检查某个用途是否具有所需的点,然后返回真/假。像这样的东西(或多或少是伪代码)

    public class CanUserEditQuestionService
    {
        //constructor with deps\\
    
        public bool Handle(CanUserEditQuestion input)
        {
           //query the read model, maybe a query object to get us the rep of the user
          var rep=getReputation.Get(input.UserId);
    
          //we can have a dependency here which tell us the number of points required for a specific permission
    
         return(rep>=1000);
        }
    }
    

    如果查询返回 true,则处理程序将对 Question 实体执行更改,即 question.ChangeText() 或 smth(我认为 SO 采用事件溯源方法)。

    这里有一个简单的用例,它包含一个概念“问题”、它的命令行为“编辑”和决定谁可以做什么的业务规则。问题是,1000 rep 规则从来不是问题概念定义的一部分,因此它不属于该聚合,即问题是如何编辑的。然而,它是用例本身和应用程序服务的一部分。

    我相信你会问我:“如果域查询使用的读取模型在命令模型后面怎么办?”。在这种情况下,它无关紧要,延迟可能最多以秒为单位。这里的主要内容是:业务规则不是问题聚合的一部分,因此它不关心是否立即保持一致。

    另一件事是用户代表始终与问题的概念不同,因此处理代表永远不应成为问题聚合的一部分。但它是应用程序服务的一部分。

    如果您将应用程序视为一组使用概念(它们本身封装数据和业务约束)做事的用例,则很容易识别哪个是应用程序服务、聚合、域服务等。

    关于domain-driven-design - 如何使用 DDD 为 StackOverflow 网站建模,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33858699/

    相关文章:

    java - 值对象与数据传输对象

    cqrs - 如何开始在现有数据库上使用 CQRS 和 Axon 框架

    azure - CQRS:读取端 ACID

    c# - Autofac 解决 CQRS CommandDispatcher 中的依赖关系

    domain-driven-design - 为什么将命令和事件限制为一个集合? CQRS + ES + DDD

    ravendb - 使用 nosql 的事件存储性能注意事项

    asp.net-core - 如何处理多层一对多关系的DAL?

    javascript - 前端领域模型

    domain-driven-design - DDD - 业务决策基于数据库逻辑

    architecture - 如何正确处理事件溯源中的聚合关系?