2
public void PublicMethod(FooBar fooBar)
{
    if (fooBar == null)
        throw new ArgumentNullException("fooBar", "fooBar cannot be null");

    // log the call [added:  Thanks S.Lott]
    _logger.Log("PublicMethod called with fooBar class " + fooBar.Classification);

    int action = DetermineAction();
    PrivateMethod(fooBar, action);
}

private void PrivateMethod(FooBar fooBar, int action)
{
    if (fooBar == null)
        throw new ArgumentNullException("fooBar", "fooBar cannot be null");  // Is this line superfluous?

    /*
        Do something
    */
}

如果已经在公共接口上检查了输入,是否可以在私有方法中跳过这种错误检查?通常有一些经验法则可以通过......

编辑:

也许 ArgumentNullException 不是一个很好的例子,因为可以使您应该在两个级别都检查但返回不同的错误消息的参数。

4

9 回答 9

3

我会说不。

虽然在这种情况下您确实知道它已经检查了可空性,但在两个月内,最年轻的实习生会出现并编写也调用 PrivateMethod 的 PublicMethod2,但是你瞧,他忘了检查 null。

于 2008-10-08T14:50:21.600 回答
2

由于 public 方法并没有真正使用 foobar,我不确定它为什么要检查。当前的私有方法关心,但关心是私有方法的责任。实际上,私有方法的全部意义在于将所有职责委托给它。

一个方法检查它实际使用的输入;它不检查它只是通过的东西。

如果一个不同的子类具有相同的公共方法,但有一些不同的私有方法实现——一个可以容忍空值的方法——现在怎么办?您有一个公共方法现在对新子类有错误的约束。

您希望在公共方法中做的尽可能少,以便各种私有实现可以自由地做正确的事情。不要“过度检查”或“以防万一”检查。委派责任。

于 2008-10-08T15:00:30.240 回答
1

当使用按合同设计(http://en.wikipedia.org/wiki/Design_by_contract)时,进行正确调用通常是客户(公共方法)的责任,即传递有效参数。在这种特殊情况下,它取决于 null 是否属于一组有效输入值,因此有 3 个选项:

1)空值是有效值:抛出异常或错误意味着违反合同,服务器(私有方法)必须处理空值并且不应该抱怨。

2) Null 是无效值,由您控制的代码传递:由服务器(私有方法)决定如何反应。显然,抛出异常是处理这种情况的更优雅的方式,但它的代价是必须在堆栈的其他地方处理该异常。异常并不是处理因编程失误导致的合同违约的最佳方式。您真的不应该在合同已经违反时抛出异常,而是在由于环境问题而无法在软件中控制的情况下无法履行时抛出异常。通过将断言插入私有方法的开头以检查参数是否为空,可以更好地处理错误。这将降低代码的复杂性,

3)然后是防御性编程(http://en.wikipedia.org/wiki/Defensive_programming)。在处理您无法控制的外部代码传递的参数时,您的代码的直接层需要运行偏执级别的检查并根据其与外部世界的通信合同返回错误。然后,深入到没有暴露在外部的代码层,坚持契约式编程仍然更有意义。

于 2008-10-08T16:10:45.933 回答
1

我会尽你所能检查一切,你永远不知道什么时候会发生你没有想到的事情。(而且它比抱歉更安全)

于 2008-10-08T15:09:42.637 回答
0

I'd consider the answer to be "yes, do the check again" because:-

  • The private member could be reused again in the future from a different path through the code, so program defensively against that situation.
  • If you perform unit tests on private methods

My view might change if I had a static analyser that could pick this up and not flag the potential use of a null reference in the private method.

于 2008-10-08T16:32:09.757 回答
0

这取决于空值是否指示方法的错误。请记住,方法也可以称为对象的消息;它们也对对象的状态进行操作。参数可以专门化发送的消息类型。

  • 如果 publicMethod() 不使用参数并在 privateMethod() 使用参数时改变实例的状态,不要认为它在 publicMethod 中是错误的,而是在 privateMethod() 中做。
  • 如果 publicMethod() 没有改变状态,则认为这是一个错误。

您可以将后一种情况视为为对象的内部功能提供接口。

于 2008-10-08T16:05:05.147 回答
0

如果使用已经验证的输入频繁调用 PrivateMethod,并且很少使用用户输入,那么我将使用 PublicMethod/PrivateMethod 概念,不对 PrivateMethod 进行错误检查(并且 PublicMethod 除了检查参数和调用 PrivateMethod)

我还将私有方法称为 PublicMethod_impl (用于“实现”),因此很明显它是内部使用/无检查方法。

我坚持认为这种设计会导致强大的应用程序,因为它迫使您考虑何时检查什么。经常检查参数的人经常陷入“我检查了一些东西,所以我检查了一切”的陷阱。

例如,一位前同事(用 C 语言编程)在使用指针之前总是检查它是否为空。一般来说,他的代码中的指针被初始化为启动并且从未改变过,因此它为空的可能性非常低。此外,指针有一个正确值和 65535 个可能的错误值,而他只是检查其中一个错误值。

于 2008-10-08T17:15:06.597 回答
0

至少要注释一下 PrivateMethod 必须有一个非空的 FooBar 并且 PublicMethod 会检查这个。

于 2008-10-08T14:49:56.407 回答
0

您可能还想将“私有”方法标记为私有或受保护。

于 2008-10-08T14:54:38.177 回答