【问题标题】:Does "tell, don't ask" apply to user input validation?“告诉,不要问”是否适用于用户输入验证?
【发布时间】:2009-02-18 16:27:30
【问题描述】:

这些年来我一定是忽略了“告诉,不要问”OOP 原则,因为我几天前才第一次了解它。

但上下文是关于已从 ASP.NET 网页表单页面移出并移入数据/业务对象的验证代码的讨论,并且没有“Validate()”方法,只有一个本身的保存方法进行了验证并(据说)引发了异常。我问为什么要这样设计,我被引导到 OOP 的“告诉,不要问”原则,这是我从未听说过的,所以我们一起研究了谷歌,我立即受到了教育。 ;)

但是,有些东西闻起来不太对劲,难道不应该在数据从用户传递到处理和/或收集数据的业务层之前对其进行清理,而不是反过来?我很困惑这对好的设计有何影响。

似乎“告诉,不要问”的规则与您不应该向目标对象询问目标对象的状态的想法有关,并且该原则从未真正适用于正在被处理的数据传递目标对象。

【问题讨论】:

    标签: oop tell-dont-ask


    【解决方案1】:

    我认为这听起来像是一堆“最佳实践”和“设计方法”出了问题,但现在对我来说有点道理。这样看:

    想象一下将验证放在业务对象中,但在表示层中“如果验证失败我该怎么办”。这将允许多个不同的表示层重用相同的验证逻辑,但以不同的方式处理错误。

    public Foo
    {
      Validate(Baz bar)
      {
          if(!is_number(bar)) throw numberexception();
      }
    
      AssignBar(Baz bar)
      {
          Validate(bar);
      }
    }
    
    
    //...
    
    try
    {
      foo.AssignBar(bar);
    }
    catch(numberexception e)
    {
      alert('Not a number!');
    }
    

    n.b.关于抛出异常,你可以争论所有你想要的,这只是一个例子。返回状态、布尔值,随心所欲。

    【讨论】:

      【解决方案2】:

      我同意 AviewAview,但只会在用户告知(而不是他要求时)时抛出异常:

      public Foo
      {
        bool Validate(Baz bar)
        {
              if(!is_number(bar)) return false;
              return true;
        }
      
        AssignBar(Baz bar)
        {
              if (!Validate(bar)) throw numberexception();
        }
      }
      

      告诉:

      try
      {
        foo.AssignBar(bar);
      }
      catch(numberexception e)
      {
        alert('Not a number!');
      }
      

      问:

      if (foo.Validate(bar)
      {
        foo.AssignBar(bar);
      }
      else
      {
        alert('Not a number!');
      }
      

      因此,AssignBar 需要一个 VALID 条,如果不是则抛出异常,但我们还提供了一个不抛出异常的 Validate 方法。

      【讨论】:

      • 异常可以处理意外情况(内存不足/磁盘已满/连接关闭/分布式事务失败) - 验证用户提交的数据并不意外。改用“处理程序”方法 - 只需调用 validate_number(invalid_handler_callback)
      【解决方案3】:

      我想知道这是否更像是一个“关注点分离”而不是“告诉不要问”的问题。验证数据是谁的责任?可以说,它负责持久化它。

      当然,有时在多个层中验证数据很有用。如果您的应用程序是这种情况,那么在“用户”层中公开验证逻辑是没有问题的。但我仍然希望它在业务层中。

      【讨论】:

        猜你喜欢
        • 2014-04-11
        • 1970-01-01
        • 2020-02-09
        • 1970-01-01
        • 2017-12-17
        • 2018-04-13
        • 1970-01-01
        • 1970-01-01
        • 2020-09-21
        相关资源
        最近更新 更多