何时检查函数/方法参数?

3

当编写小函数时,我经常遇到这样的情况:将一些参数传递给一个函数,该函数本身只将它们传递给不同的小函数以达到其目的。

例如(C# 语法):

public void FunctionA(object param)
{
    DoA(param);
    DoB(param);
    DoC(param);
    // etc.
}

private void DoA(object param)
{
    DoD(param);
}

private void DoD(object param)
{
    // Error if param == null
    param.DoX();
}

所以,参数并不在被调用的函数内部使用,而是在执行任务的小函数的深处“某个地方”使用。
那么什么时候最好检查我的参数对象是否为空呢?
在FunctionA中进行检查:
优点: - 通过进一步的方法使用,没有额外的开销,因为对象是空的。 缺点: - 我那句语法精美的FunctionA被丑陋的验证代码弄脏了。
只有在使用param-object时进行检查:
优点: - 我那句语法精美的FunctionA保持阅读的乐趣 :)
缺点: - 通过调用将什么都不做的方法,会因为param-object为空而产生额外的开销。 - 其他缺点我暂时想不到。

这被称为柯里化函数--虽然有点过于简化。http://en.wikipedia.org/wiki/Currying - Joe Johnson
6个回答

6

尽可能将其放置在调用栈的较低位置,这样如果您以后重构代码并且除 DoA 之外的其他东西调用了 DoD,则已经有检查程序,并且不必重新处理参数检查。在大多数情况下,小的 null 检查和可能会增加一些额外方法调用的开销都是微不足道的,因此您不必担心多次检查。


大多数情况下是绝对正确的。如果您有耗时的操作,可能最终会失败,那么您可以尝试避免调用DoA、DoB,因为知道DoC会失败(因为DoD)。但这已经是优化了,我仍然会在DoD中进行检查,但也会在FunctionA中进行检查。 - van

4

除非你认为该值在绝大多数情况下可能为空,否则我建议将验证放在DoD()函数中。如果你把它放在FunctionA()函数中,当你决定FunctionB()也需要使用DoD()时,你将不得不重复验证代码。对我来说,额外的开销是值得的,因为我不想重复自己。


1
作为一个准则,我习惯于检查方法使用的每个参数,甚至包括我的私有变量。因此,在您的DoD方法中,我只会检查nil。
您可能想要查看Bertrand Meyers的契约式设计宣言。

1

尽早失败。除非部分结果比没有结果更可取,否则当代码能够检测到问题时,执行应该立即停止。为什么代码要运行多个方法,当下游的结果将是无效或缺失的参数?

如果可能单独调用下游方法,则可以通过调用常见验证方法来处理验证,如已经建议的那样。


0

调用者有责任传递有效的参数。在这种情况下:

if(param != null)
{
  FunctionA(param);
}

0

永远要检查一切 :) 来自嵌入式系统编程库的深处,这是我会使用的方法:

public void FunctionA(object param)
{
    assert(param != null && param.canDoX());
    DoA(param);
    DoB(param);
    DoC(param);
    // etc.
}

private void DoA(object param)
{
    assert(param != null && param.canDoX());
    DoD(param);
}

private void DoD(object param)
{
    assert(param != null && param.canDoX());
    if ( param != null )
        param.DoX();
    else
        // Signal error, for instance by throwing a runtime exception
        // This error-handling is then verified by a unit test that 
        // uses a release build of the code.
}

为了简化这个问题,显而易见的解决方案是将验证拆分到一个单独的验证器函数中。使用C风格的预处理器或仅使用断言,应该很容易将这种“偏执”的验证从发布版本中排除掉。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接