5

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

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

仍然,有些东西闻起来不对劲,是否应该在数据从用户手中转移到处理和/或收集数据的业务层之前对其进行清理,而不是反过来?我很困惑这如何促成好的设计。

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

4

3 回答 3

4

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

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

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

注意,您可以就抛出异常进行任何争论,这只是一个例子。返回状态,布尔值,无论你想要什么。

于 2009-02-18T16:33:54.330 回答
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 方法,它不会抛出异常。

于 2009-02-18T16:43:17.087 回答
0

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

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

于 2009-02-18T16:43:40.080 回答