LaR*_*RRy 21 java validation exception
我们来看看这两个例子.
第一:
try {
execute(testObj);
} catch(Exception e) {
//do somethingwith that
}
public void execute(TestObj testObj) throws Exception {
if (testObj == null){
throw new Exception("No such object");
}
//do something with object
}
Run Code Online (Sandbox Code Playgroud)
第二:
if (testObj != null){
execute(testObj);
} else {
//handle this differently
}
public void execute(TestObj testObj) {
//do something with object
}
Run Code Online (Sandbox Code Playgroud)
如果我们需要检查"is null"或其他任何东西,现在不是重点.我想知道哪种做法总体上更好 - " 检查,然后做 "或" 做,然后处理异常,如果发生 "?
Lie*_*yan 29
也不应该只检查系统之间的边界.
系统之间的界限是什么?
在库代码中,由于公共API可能由外部代码调用,因此您应该始终检查可由外部代码调用的任何内容.无需检查仅限内部的方法(即使其访问修饰符是公共的).然后,异常或返回代码可以根据个人喜好来发出参数错误信号,但是不能忽略已检查的异常,因此通常是向外部代码发送错误信号的首选方法.
在应用程序代码(而不是库)中,只应在接收来自用户的输入,加载URL,读取文件等时进行检查.不需要在公共方法中进行输入检查,因为它们只是由您自己的应用程序代码调用.
在您自己的代码中,您应该避免首先需要检查的情况.例如,null您可以使用"null object pattern"代替检查.如果你仍然需要做一个检查,尽早做,这通常意味着在外面做,但试图找到更早的点.
即使没有正式记录,即使没有强制执行,所有方法,无论是内部还是面向公众,都应该有合同.不同之处在于,在面向外部的代码中,您应该将合同强制执行作为错误检查的一部分,而在仅限内部的代码中,您可以并且应该依赖于调用者知道要传递什么和不传递什么.
简而言之,由于只在系统边界上进行检查,如果您实际上可以选择是在方法内部还是外部检查,那么您可能不应该检查那里,因为那不是系统边界.
在系统边界中,双方总是必须检查.调用者必须检查外部调用是否成功,并且被调用者必须检查调用者是否提供了合理的输入/参数.忽略调用者中的错误几乎总是一个错误.坚固原则适用,始终检查从外部系统收到的所有内容,但只发送您知道外部系统可以接受的内容.
但是,在非常大的项目中,通常需要将项目划分为小模块.在这种情况下,项目中的其他模块可以视为外部系统,因此您应该在API中进行检查,这些API将暴露给项目中的其他模块.
TLDR; 检查很难.
正如@LieRyan所说,你应该只检查系统之间的界限.但是一旦你进入你自己的代码,你仍然需要能够发现意外的问题,主要是因为:
清楚地记录哪些方法接受null作为参数,或者可以返回null.
一个很好的工具,可以帮助你,如果你使用Eclipse Juno,(我认为IntelliJ-Idea有类似的东西)是启用空检查分析.它允许您编写一些注释以使编译时空检查.真的很棒.你可以写类似的东西
public @NonNull String method(@Nullable String a){
//since a may be null, you need to make the check or code will not compile
if(a != null){
return a.toUppercase();
}
return ""; //if you write return null it won't compile,
//because method is marked NonNull
}
Run Code Online (Sandbox Code Playgroud)
它还有一个很好的@NonNullByDefault,基本上说"没有方法接受或返回null,除非标记为@Nullable"这是一个很好的默认值,保持你的代码干净和安全.
有关更多信息,请查看Eclipse帮助
第二个比第一个更好,任何异常都可能引发,并且您会认为这是预期的。
请记住,使用异常来控制程序流在计算上也很昂贵,因为构建异常会降低性能。例如,在 hibernate 中,最好执行 a 来SELECT COUNT(*)检查行是否存在,而不是查看 recordNotFoundException 是否触发并将应用程序逻辑基于该异常触发。