5

我经常有调用层次结构,因为所有方法都需要相同的参数。如果我不想将它们放在实例级别(类成员),那么我总是问我在每个方法中检查它们的有效性是否有意义。

例如:

public void MethodA(object o){
   if(null == o){
      throw new ArgumentNullException("o");
   }
   // Do some thing unrelated to o

   MethodB(o);

   // Do some thing unrelated to o

}

public void MethodB(object o){
   if(null == o){
      throw new ArgumentNullException("o");
   }
   // Do something with o
}

如果MethodA 使用该参数,那么它就很清楚了,我必须在那里以及在 MethdoB 中检查有效性。但是,只要 MethodA 只o提供给它MethodB,那么检查有效性是否也是一种好习惯MethodA

也签入的好处MethodA可能是异常在被调用者调用的方法中抛出,这很好,但有必要吗?调用堆栈也会说明这一点。也许它在公共、内部、受保护的方法中有意义,但在私有方法中没有?

我以空检查为例,但索引验证或范围验证也属于自我问题,但我认为由于冗余代码的危险,存在限制。你怎么看?

更新

通过 AakashM 的回答,我发现我不太准确。MethodA不仅电话MethodB,它还做其他事情,但不相关o。我添加了一个示例来澄清这一点。谢谢阿卡什M。

4

3 回答 3

9

Steve McConnell 的 Code Complete 谈到了“路障”的概念——一堵防御墙,外面的数据是不可信的,里面的数据是可信的。想要进入路障的数据必须经过验证过程,但在路障内,数据可以自由移动,不受验证码的限制。

如果你能在你的项目中强加如此多的结构化和分层,并坚持下去,它确实会让路障内的代码少一些仪式感,多一些本质。但是,只要有一种方法可以调用路障,一切都会出错。

In your example, MethodB is public. This means that you have no automatic future guarantees that MethodA will be its only caller - I would say therefore that its validation code should remain. If it were private to the class, however, you could make an argument for removing it.

As for MethodA, if it actually does nothing more than call MethodB, it shouldn't exist. If it's a stub for future expansion, and at some point it is going to do something with o, then its validation code should also remain.

于 2010-07-14T10:37:10.093 回答
1

我认为你应该确保它一旦产生输入值(调用者的责任)。如果该类仅由内部客户端使用,则此方法有效。如果它是公共 API 的一部分,那么您不能免除检查,但您可能希望将它们分解,正如其他答案中所建议的那样。

出于测试目的,您也可以在这两种方法中使用,如果性能有问题Debug.Assert(o != null),检查将从发布代码中删除。

于 2010-07-14T10:36:21.260 回答
1

我不认为参数验证是“冗余代码”。您需要保护所有外部入口点。如果您有一个private方法,并且您在时间流到达它时知道它的所有参数都将是有效的,那么您可能有一个案例,但对于public(甚至protected)方法您真的没有。

于 2010-07-14T11:24:13.020 回答