代码之家  ›  专栏  ›  技术社区  ›  Jon Davis Glenn Block

“告诉,不要问”是否适用于用户输入验证?

  •  5
  • Jon Davis Glenn Block  · 技术社区  · 17 年前

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

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

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

    3 回复  |  直到 17 年前
        1
  •  4
  •   Tom Ritter    17 年前

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

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

    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
  •  2
  •   Patrick McDonald    14 年前

    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!');
    }
    

        3
  •  0
  •   jcrossley3    17 年前

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

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

    推荐文章