在编写小函数时,我经常遇到一些参数被赋予一个函数的情况,该函数本身只将它们传递给不同的小函数来实现其目的。
例如(C#-ish Syntax):
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();
}
所以这些参数不是在被调用的函数中使用,而是在执行该工作的小函数的深处“某处”。
那么什么时候最好检查我的param-Object是否为空?
签入功能A时:
临: - 通过使用其他方法没有任何开销,最后这些方法无效,因为对象为空。
缺点: - 我的语法很棒很好的功能A被丑陋的验证码弄脏了。
仅在使用param-object时进行检查:
临: - 我的语法精彩功能AA值得高兴阅读:)
缺点: - 通过调用方法会产生开销,因为param-object为null,所以这些方法无效。 - 目前我没有考虑进一步的缺点。
答案 0 :(得分:6)
总是把它放在尽可能远的调用堆栈中,这样如果你以后重构代码和其他东西调用除DoA以外的DoD,你就可以进行检查,而不必重新进行参数检查。在大多数情况下,小的空检查和可能的一些额外的方法调用的开销将是微不足道的,并且多做几次检查不是你应该担心的事情。
答案 1 :(得分:4)
除非您认为绝大部分时间值都可能为空,否则我会将验证放在DoD()中。如果你将它放在FunctionA()中,那么当你决定FunctionB()也需要使用DoD()时,你将不得不重复验证代码。对我来说,额外的开销不值得重复自己。
答案 2 :(得分:1)
作为指导原则,我习惯于通过该方法检查所使用的每个参数,甚至包括我自己的私有变量。因此,我只会在你的国防部方法中检查是否为零。
你可能想看看Bertrand Meyers Design By Contract咒语。
答案 3 :(得分:1)
提前失败。除非部分结果优于完全没有结果,否则只要代码可以检测到存在问题,就应该停止执行。当结果下游将成为无效或缺少参数时,为什么代码应该运行多个方法?
如果可以单独调用下游方法,则可以通过调用已经建议的常用验证来处理验证。
答案 4 :(得分: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风格的预处理器,或者只是坚持使用断言,从发布版本中排除这种“偏执”验证应该是微不足道的。
答案 5 :(得分:0)
传递有效参数是调用者的责任。在这种情况下:
if(param != null)
{
FunctionA(param);
}