Oop 是不是;告诉我,唐';“不要问”;是否应用于用户输入验证?

Oop 是不是;告诉我,唐';“不要问”;是否应用于用户输入验证?,oop,tell-dont-ask,Oop,Tell Dont Ask,这些年来,我一定是忽略了“告诉,不要问”OOP原则,因为我几天前才第一次了解它 但上下文是关于验证代码的讨论,该代码已从ASP.NET web表单页面移到数据/业务对象中,没有“Validate()”方法,只有一个save方法,该方法本身进行验证,并且(据推测)引发了一个异常。我问为什么这样设计,我被引导到OOP的“告诉,不要问”原则,这是我从未听说过的,于是我们一起看了谷歌,我立即接受了教育 尽管如此,有些东西闻起来还是不对劲,难道不应该在数据从用户手中转移到业务层进行处理和/或收集之前对其进

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

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

尽管如此,有些东西闻起来还是不对劲,难道不应该在数据从用户手中转移到业务层进行处理和/或收集之前对其进行清理,而不是相反吗?我不明白这是如何产生好的设计的


“告诉,不要问”这条规则似乎与你不应该向目标对象询问目标对象的状态有关,而且这条原则从来没有真正适用于传递给目标对象的数据。

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

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


n、 b.你可以就抛出异常争论所有你想争论的问题,这只是一个例子。返回状态、布尔值,任何你想要的。

我同意AviewView,但只有在用户告知时才会抛出异常(不是在他询问时):

告诉:

询问:


因此,AssignBar需要一个有效的bar,如果它不是,则抛出一个异常,但我们还提供了一种方法来验证不抛出异常的bar。

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


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

异常可以处理意外情况(内存不足/磁盘已满/连接已关闭/分布式事务失败)-验证用户提交的数据并非意外。改用“处理程序”方法-只需调用validate\u number(无效的\u处理程序\u回调)
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!');
}
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!');
}