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

时间:2009-02-18 16:27:31

标签: oop tell-dont-ask

我多年来一直忽略了“告诉,不要问”OOP原则,因为我刚刚在几天前第一次了解它。

但是上下文是关于验证代码的讨论,该代码已经从ASP.NET Web表单页面转移到数据/业务对象中,并且没有“Validate()”方法,只是一个自身的save方法做了验证,并且(据说)提出了例外。我问为什么这是以这种方式设计的,我被引导到OOP的“告诉,不要问”原则,这是我从未听说过的,所以我们一起看了谷歌,我立即接受了教育。 ;)

然而,有些东西闻不到,不应该在将数据从用户传递到处理和/或收集的业务层之前清除数据,而不是反过来?我对如何做好设计感到困惑。

似乎“告诉,不要问”的规则与你不应该向目标对象询问目标对象的状态的想法有关,并且该原则从未真正意味着应用于数据将传递给目标对象。

3 个答案:

答案 0 :(得分:3)

我觉得这听起来像是一堆“最佳实践”和“设计方法”出错了,但现在对我来说有点意义了。以这种方式看待它:

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

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。你可以争论所有关于抛出异常的想法,这只是一个例子。返回状态,bools,无论你想要什么。

答案 1 :(得分: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方法,它不会抛出异常。

答案 2 :(得分:0)

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

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