【问题标题】:DDD - How should the domain rules be designed so the upper layers know when a rule was broken?DDD - 应该如何设计域规则以便上层知道规则何时被破坏?
【发布时间】:2014-05-01 07:27:00
【问题描述】:

示例:ShoppingCart 实体有一条规则,即不能添加超过 10 件商品。 shoppingCart 将有一个方法 addItemToCart(item) 来检查它是否没有超过限制。如果超过购物车限制,购物车应该以某种方式通知调用该方法的上层特定业务规则已被破坏。

想到的一件事是使用异常,但这些似乎是对异常的不当使用。应该如何进行消息传递?什么模式可以帮助解决这个问题,保持域与其他层无关并正确封装?

【问题讨论】:

    标签: oop design-patterns domain-driven-design cqrs business-rules


    【解决方案1】:

    如果规则是购物车中最多 10 件商品,那么 ShoppingCart 应该公开 isFull() 以便上层可以在调用 addItem() 之前进行检查。或禁用Add 按钮,或其他任何东西-ShoppingCart 不知道如何使用规则信息,并且不应假设仅在调用addItem 时才需要它。作为安全检查addItem 可以抛出异常,但这不应该是与上层通信的主要机制。

    【讨论】:

    • 我喜欢这种思维方式,暴露领域的一切。我想我试图在域中封装一些逻辑,但这可能会导致上层的不当行为。我只是在想我是否真的应该通过自己进行检查来永远不要让域对象处于无效状态。我想最好的选择和正确的选择是在域端编写规则,但将它们暴露给上层并让他们进行检查。此外,“禁用添加按钮”是在之后停止域对象做某事的好方法检查失败 +1
    • 谢谢!它使我走上了正确的道路!这基本上就像让上层请求并运行检查,域层将缓存检查结果并在需要时使用它们。
    【解决方案2】:

    对此没有秘诀,这实际上取决于您的应用。对于您的具体示例,我相信事情很简单: ShoppingCart 几乎是一个容器,即使它是一个域概念,它仍然是一个容器。 UI 也应该知道这个规则,所以它不应该允许比它假设接受的更多数量的项目。

    但假设购物车 POST 模型到达控制器。很容易拥有服务或直接使用 ShopppingCart 对象来验证输入。关键是,你预料到这种情况,所以你要尽快处理它。但如果您决定 UI 不应该首先允许这种情况发生,那么 ShoppingCart 应该抛出异常,因为这是一个错误(UI 允许无效操作)。

    就我个人而言,我不会对 ShoppingCart 域概念进行建模。 ShoppingCart 将是用于从中创建订单的输入模型。

    作为一个经验法则,如果我预计某些情况(需要向用户提供反馈),那么在使用数据更新域之前我会进行一些验证。每次违反业务规则时,域对象都应该抛出。再说一次,没有食谱,我可能会在不同的应用程序中做不同的事情。

    【讨论】:

    • 好吧,如果你不把业务规则放在域中,你最终会得到一个贫乏的域模型,你应该跳过那个层,只使用控制器/服务/命令/命令处理程序.因此,知道领域层确实存在,它将处理一些可能会破坏的业务规则。 UI 只是应该处理基本检查,业务规则(至少大部分)应该在域中。所以当规则被破坏时(我的例子很简单,你把它看得太重了)上层需要知道 abi=out 它(服务/ui 等)。
    • "但是如果您决定 UI 不应该首先允许这种情况发生,那么 ShoppingCart 应该抛出异常,因为它是一个错误"。域不应该关心其他层,它只需要知道它自己的层发生了什么。数据来自哪里以及是否通过某些过滤器不是域关注的问题。域是核心(不是并行层,是核心层,对上层一无所知,所以被称为“域驱动”)
    • 非常感谢您提供 DDD 教程,但是您错过了“没有配方”部分,所以我只能就一些具体场景向您提供我的想法。该域不关心其他层,这就是我说它应该抛出的原因。但是该应用程序包含的不仅仅是域,并且没有什么可以阻止 UI 使用域验证器(可以实现为服务或静态方法等)。业务规则仍然是域的一部分,但它在域之外被重新使用。我认为您正在尝试提出一个完整的“适用于每个应用程序”的方法,但它根本不是一个。
    • 我只能针对具体场景给出指导、原则或建议。没有人能告诉你在任何应用中做任何事情的最佳方式。
    【解决方案3】:

    与任何其他程序一样:选择一种适合您的团队和您的实施环境的方法。异常工作正常。

    【讨论】:

      猜你喜欢
      • 2023-03-28
      • 1970-01-01
      • 2011-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-24
      • 1970-01-01
      • 2020-10-08
      相关资源
      最近更新 更多