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不是一个很好的例子,因为可以建立一个参数来检查两个级别但返回不同的错误消息。
答案 0 :(得分:3)
我会说不。
虽然你在这个的情况下确实知道它已经被检查了可空性,但是在两个月的时间里,最年轻的实习生会来并写 PublicMethod2也调用了PrivateMethod,但是看到他忘了检查null。
答案 1 :(得分:2)
由于公共方法并不真正使用foobar,我不确定它为什么要检查。目前的私人方法关心,但私人方法的责任是关心。实际上,私有方法的全部意义在于将所有责任委托给它。
方法检查它实际使用的输入;它不会检查它刚刚通过的东西。
如果一个不同的子类具有相同的公共方法,但是一些不同的私有方法实现 - 一个可以容忍空值的 - 现在呢?您有一个公共方法,现在对新子类有错误的约束。
您希望在公共方法中尽可能少地执行此操作,以便各种私有实现可以自由地执行正确的操作。不要“过度检查”或“只是在案件中”检查。委派责任。
答案 2 :(得分:1)
我会错误地检查你能做的一切,你永远不知道什么时候你可能会想到的事情。 (而且比抱歉更安全)
答案 3 :(得分:1)
当按合同(http://en.wikipedia.org/wiki/Design_by_contract)使用设计时,通常客户(公共方法)负责进行正确的调用,即传递有效参数。在这种特殊情况下,它取决于null是否属于一组有效输入值,因此有3个选项:
1)Null是有效值:抛出异常或错误意味着违反合同,服务器(私有方法)必须处理null并且不应该抱怨。
2)Null是无效值,并由您控件中的代码传递:由服务器(私有方法)决定如何做出反应。显然,抛出异常是处理这种情况的更优雅方式,但是它需要在堆栈的其他地方处理该异常。例外不是处理编程失误导致的违约的最佳方式。你真的应该抛弃异常,而不是在合同已经被违反的情况下,但由于环境问题而无法通过软件控制而无法实现。通过将断言插入私有方法的开头来检查参数是否为空来更好地处理错误。这将降低代码的复杂性,不需要在堆栈中处理异常,并且它将实现在测试期间突出显示损坏的合同的目标。
3)然后是防御性编程(http://en.wikipedia.org/wiki/Defensive_programming)。当处理由控制之外的外部代码传递的参数时,代码的直接层需要运行偏执级别的检查并根据与外部世界的通信协议返回错误。然后,深入到外部没有暴露的代码层,通过契约坚持编程仍然更有意义。
答案 4 :(得分:0)
至少发表评论说PrivateMethod必须有一个非空的FooBar,并且PublicMethod会检查这个。
答案 5 :(得分:0)
您可能还希望将“私有”方法标记为私有或受保护。
答案 6 :(得分:0)
这取决于null值是否表示方法的错误。请记住,方法也可以被称为对象的消息;它们也可以在物体的状态下运行。参数可以专门化发送的消息类型。
您可以将后一种情况视为提供对象内部功能的接口。
答案 7 :(得分:0)
我认为答案是“是的,再次检查”,因为: -
如果我有一个静态分析器可以选择这个并且不在私有方法中标记可能使用空引用,我的视图可能会改变。
答案 8 :(得分:0)
如果经常使用已经验证过的输入调用PrivateMethod,并且很少使用用户输入,那么我将使用PublicMethod / PrivateMethod概念而不对PrivateMethod进行错误检查(并且PublicMethod不执行任何操作,然后检查参数和调用PrivateMethod)
我还会将私有方法称为PublicMethod_impl(用于“实现”),因此很明显它是一种内部使用/不检查方法。
我认为这种设计会导致更多强大的应用程序,因为它会强制您考虑什么时候检查。经常检查参数的人经常陷入“我已经检查了一些东西的陷阱,因此我已经检查了所有东西”。
作为一个例子,在使用指针之前,前同事(在C中编程)总是会检查它是否为空。通常,他的代码中的指针被初始化为启动并且从未改变,因此它为null的可能性非常低。此外,指针有一个正确的值和65535个可能的错误值,他只检查其中一个错误值。