【问题标题】:SRP applied to a workflow example: how to structure the classes in a sensible waySRP 应用于工作流示例:如何以合理的方式构造类
【发布时间】:2009-11-24 20:17:21
【问题描述】:

我在决定班级职责时遇到了问题。
我有 3 个 html 表单:

  1. 对于每个表单,都有一个 html 模板,其中包含一些文本和要包含的表单的标记
  2. 需要验证每个表单,如果出现错误,则需要重新显示模板和 (1) 中的表单以及一些错误消息。只有一些字段在不同的表单中是通用的。
  3. 如果没有错误,则需要邮寄结果消息。每个表单都有一个结果邮件模板。

我发现很难为这个问题决定一个好的班级方案。一种可能性是按功能分离类

  • CheckFormData:检查表单数据
  • DisplayForm:显示有/无错误的表单(或者也分开这个?)
  • 电子邮件表单:电子邮件表单。

对此我不确定。关于一种特定形式的领域的知识分散在各个类别中。

有一些工作流程。也许我也应该有一个工作流类:

class FormSubmitWorkFlow
{
   function start() 
   {
     $this->displayForm->render();
   }

   function processFormData($data)
   {
      $this->checkForm->setData($data);
      if (!$this->checkForm->isValid())    {

         $errors = $this->checkForm->getErrors();
         $this->displayForm->setData($data)->setErrors($errors)->render();
      } else {
         $this->emailForm->setData($data)->email();
      }
   }

   function setDisplayForm(DisplayForm $df)
   {
      $this->displayForm = $df;
   }

   function setCheckForm(CheckForm $cf)
   {
      $this->checkForm = $cf;
   }

   function setEmailForm(CheckForm $ef)
   {
      $this->emailForm = $ef;
   }
}

对于每种表单类型(请记住,其中有 3 个)我需要一个

  1. CheckForm,
  2. EmailForm
  3. DisplayForm 班级。

3*3 = 9 个类 + 3 个基类 = 12 个类。
此外,您想将正确的 CheckForm-subclass 和 EmailForm-subclass 注入工作流程,它们都需要具有相同的表单类型。也许我们需要为此创建一个 FormWorkFlowFactory。这总共有 13 个类。

现在我觉得我做错了什么。 如果我有 FormSubmitWorkFlow 作为模板方法类,我可以只创建 3 个子类,但每个子类会混合不同的职责。

你如何改进这一点,你能激发你的答案,即什么方法引导你得到答案?


编辑:虽然目前唯一的答案很有用,但很高兴看到一些同意它的人的投票,或者我想听到社区提供更好的解决方案。我是唯一一个赞成这个答案的人。这个问题可能需要更多的输入,所以请随时提供:-)

【问题讨论】:

  • 一个可能有用也可能没有帮助的建议是改变问题。我注意到它只有 25 个视图。我认为部分原因是您选择的标签,部分原因是标题的措辞以及问题有点难以理解的事实。我的建议是添加标签以获得更多视图,如 oo 设计或类似的东西。还可以尝试制作一个更醒目的标题,例如:“我在尝试应用 SRP 时创建了太多类吗?”然后尝试将您的问题缩小到更小的尺寸,以便更多人阅读它。浓缩它需要一些工作,但这是值得的。
  • 我的意思是重新发布问题,只是不同。
  • 感谢您的建议。将以更有吸引力的方式重新发布。有点羞耻,因为问题应该是详细和集中的。感谢您的支持!

标签: design-patterns workflow single-responsibility-principle template-method-pattern


【解决方案1】:

我不确定这是否会回答您的问题,但显然 SRP 的目标是编写您的代码,以便在您必须更改某些内容时,仅出于一个原因。就像如果你的车有 SRP,那么就不会有调节温度和上下车窗的课程。那将违反原则。在这种情况下,您似乎做得对。是的,有很多课程,但另一种选择是很多混乱。除非有一种方法可以创建一个可以验证表单的类(这实际上应该是可能的,具体取决于您需要哪种验证)。

如果您创建了一个验证类,您可以在其中添加一系列预期值并查看它们是否匹配,那么您可能会有更多的整体类,但我认为它的耦合度会低得多。让我知道我是否理解正确。

【讨论】:

  • 感谢您的关注!所以如果我理解正确,你会投票给 12 个班 + 1 个工厂吗?如果您有类似 if field1 > 12 then field2 必须介于 3 和 12 之间的逻辑,则通用验证类可能不起作用,否则如果...或者您的链也打算处理这个问题?我可以把它打包成一个班级,但我有类似($this->formType === self::FORM_TYPE_ONE) 之类的东西。我认为这不漂亮吗?
  • 我个人认为最好有一个类来处理这种类型的输入,例如 validator.test(field1 > 12);这样,您可能只需让验证器将自身或某些消息传递给错误控制器。我肯定想将我的验证器(或包装它的类)注入错误控制器。您希望事情尽可能分开,这对我来说似乎是最安全的选择。
  • 我不完全理解validator.test(field1 > 12)这行。这将评估为validator.test(<bool>)。这如何适应整个画面?通常,如果当前控制器中出现我无法处理的错误,我只会点击错误控制器。处理表单输入错误是验证器的职责(它将错误注入表单)。我想你会同意这个地方最有意义?
  • 啊,好吧,我明白你在做什么。是的,我觉得你说的很有道理。在我看来,这至少是一种可靠的方法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多