首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不变量、验证和干原理

不变量、验证和干原理
EN

Stack Overflow用户
提问于 2014-03-20 07:04:51
回答 1查看 660关注 0票数 1

我目前正在尝试消化与DDD中的不变量和验证相关的信息。如果我得到了正确的验证不是一个领域的关注,应该做外部,以防止不变量的发生。另一方面,不变量必须在域中强制执行,特别是在Aggregates中。

让我困惑的是两件事:

  • 如何区分业务规则(不变量)和验证
  • 如何尊重干燥原则

让我详细说明一下。考虑到我们有一个涵盖投标书的领域模型。投标过程组织者( (Participant). )和投标过程参与方( actors )是两个主要的参与者。组织者发布招标公告,其中包含关于阶段条款和要求的信息(例如,开始最高价格)。Tender是一个由多个阶段组成的过程。每个舞台都有自己的条件。第一个阶段的是“招标”。在这个阶段,允许参与者发送他的报价(Proposal)。

有两项基本要求:

  1. 建议书价格必须低于起始最高价格。
  2. 参赛者只可在“招标”阶段提交报盘。

从技术上讲,我们可以这样实现它(省略细节):

代码语言:javascript
复制
class SubmitHandler
{

    /**
    * Send proposal
    *
    * @param SubmitCommand $command
    */
   public function execute($command)
   {
       $this->isReadyToBeSend($command);

       $participant = $this->participantRepository->find($command->id);
       $participant->submitProposal();

   }

   private function isReadyToBeSend($command)
   {
        $result = $this->validate($command);
        if (!$result->isValid()) {
            throw new ProposalException($result->getMessages()[0]->getMessage());
        }
   }

   public function validate($command)
   {
       // Here we check if starting price is provided 
       // and it is less than starting maximum price 
       // as well as the Call for bids Stage is still active 
       // so that we are allowed to submit proposals

       return Validator::validateForSending($command);
   }

   public function canBeExecuted($command)
   {
       return $this->validate($command)->isValid();
   }
}

// In the UI we send command to the handler
$commandHandler->handle($submitCommand);


class Participant extends AggregateRoot
{
   public function submitProposal()
   {
      // here we must enforce the invariants
      // but the code seems to be almost the same as
      // in the validator in the Command Handler
      $this->isReadyToBeSent();
   }

   // throws exceptions if invariants are broken
   private function isReadyToBeSent()
   {
       $this->isPriceCorrect();
       $this->AreTermsCorrect();
   }
}

考虑到上面提到的一切,在给定的上下文中,不变量和验证之间有什么细微的区别?应该在验证器和聚合中复制代码吗?(我不想将验证器注入实体)

非常感谢。

更新

我想我还不够清楚。长话短说,我有两件事要考虑:

  1. 业务规则和不变量之间的区别。
  2. 坚持干违反SRP,反之亦然。

我和另一位开发人员最近进行了一次讨论,我们得出的结论如下:

  • 不变量是一些必须独立于业务规则遵守的规则。代码可能是相同的,尽管在概念上它们是两种不同的东西。
  • 在这方面,为了遵守SRP原则,可能会违反干原则。

如果我错了,请纠正我。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-03-28 23:58:44

尽管我已经编写了很多DDD代码,但坦率地说,我仍然对术语不太确定,我也不确定是否有社区的共识。我已经很大程度上不再使用DDD的行话了,我发现我的问题比你提出的问题少得多。

所以另一种用实际术语表述问题的方法是..。

被出价较低的人超过将真正激怒你的用户,就像在一个关闭的拍卖中的出价一样。所以我们得确保那不会发生。

读取数据时的验证

当您显示供用户输入出价的屏幕时,您当然会对用户进行一些验证,即出价必须大于以前的出价(例如通过jQuery),并且只有在CallForBids阶段才能接受投标(例如,只显示表单)。

你必须做这个验证,否则你会给用户一个非常糟糕的体验-允许他们进入一个出价,但被告知拍卖结束。因此,我们知道,在读取数据时,您必须以某种方式表达这些规则。然而,关键是:

您不能保证根据A时的信息在屏幕上显示的任何内容在用户执行在B时写入数据的操作时都是正确的。

所以这里的验证不一定是密封的。别担心太多了。即使你重复逻辑而搞砸了,我们也不能100%地保证一次写无论如何都会通过。

写入数据时的验证

正如我们上面观察到的,屏幕上的数据已经过时:用户可能在拍卖结束后输入了出价,或者由于数据显示在屏幕上,最低出价可能已经上升。因此,为了避免系统的状态违反业务规则(因此是不可靠的,没有完整性).

在编写数据时,您必须根据业务规则进行检查,并且必须在同一个事务中进行检查,否则无法保证一致性。

(也有最终的一致性,但这是另一个蜡球,超出了这个答案的范围。)

那对你来说意味着什么?

  • 您的命令处理程序是聚合/事务边界/不管本周人们怎么称呼它。
  • 如果这2条规则中的任何一条被破坏,该命令就无法成功(应该抛出异常)。任何状态都不应该改变。
  • 应该假定这一指挥是成功的。也就是说,在MVC控制器中,不要为失败的命令添加任何特殊的错误处理。命令失败是非常罕见的,但它会不时发生。
  • 任何内部实现都不重要:如果您想要有两个类,一个来强制执行每条规则,那么就直接去做。--只要在单个事务中强制执行规则,这对业务并不重要。--这就是您应该关注的问题。
  • --这也是您应该测试的--只有当命令的参数相对于系统的状态无效时,才会抛出异常。(只有在发布将触发其他处理程序的事件时,才会测试成功。)

希望这能把它弄清楚。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22525780

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档