随笔 - 17  文章 - 49  trackbacks - 0
<2006年9月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

常用链接

留言簿(1)

随笔分类(17)

随笔档案(17)

相册

最新随笔

搜索

  •  

最新评论

阅读排行榜

评论排行榜

2006 929 星期五

检查方法参数,平凡处的学问

-effective java item 23


    大多数方法和构造器都对参数有一定的限制要求,然而有否显式地检查参数就因人而异,回想自己的编码历程,也常在兴冲冲之际,直接奔向业务逻辑。然而这个看似平凡的小地方,却应该养成一个坚固的习惯,小小付出带来的效果事实上相当可观。

若有非法的参数传入,加以检查,则会立刻引发意义明确的异常。相反,若无此检查,后续情形大相径庭。该方法可能在某一行猝死,死因报告相当迷离;更劣者,方法最后寿终正寝,返回的却是错误的计算结果;最劣者,顺利走完并返回正确的结果,但执行的过程某些牵涉到的对象被设置成不正确的状态,这些隐患最后爆发于无法预计的时刻和地点。

因而,检查参数的正确性这一举动带来的贡献,更多的是来源于这一举动若不存在时可能带来的麻烦,这扇大门过于开放,则带来日后清理门户时过多的周折。

除去检查需要进行计算的参数,更要注意检查在本方法中并未使用但存储起来以备后用的参数,若不加检查,等到异常发生的时候,来源难以追踪。大大增加了debug的痛苦,这一点,想必很多coder会有这样的郁闷回忆。构造方法是这种情形的典型,构造器的大多数参数是属于这种“以备后用”的类型。错误的参数可能导致类的逻辑规则被破坏,此后导致的异常可能非常奇怪而且难以理清缘由。

凡事必有例外。某些情形下,参数检查是不应该执行的,例如这种检查代价昂贵或者不切实际,而且,(注意,是而且)合法性的检查在计算的过程中隐式的进行。例如一个对list里的object进行排序的方法,这些object必须是相互可比较的,否则,比较过程中就会抛出ClassCastException,这也正是排序方法应该抛出的异常,因而事先进行可比性的检查就无意义了。但如果不谨慎的使用这种隐式检查的技巧,就会损失错误的原子性,比如这个方法不仅仅是比较,而且还进行写操作,那么中途抛出异常的时候,已经有某些数据被改动了,你不得不进行roll back,否则就要接受一个半成品。这一方面在item 46里有更多的描述。另外,有时候这种隐式的检查所抛出的异常,也可能并非真正的病因,你还需要做些异常的“翻译”来指引真实的问题根源。

以上所说并非鼓励你限制参数,事实上,只要方法本身能应付得来,就应该尽量放宽参数的限制,方法才能有通用性。

总而言之,每当你写一个方法或构造器,就应该考虑会有什么限制需要加之于参数上,为此配上文档说明,在方法一开始就显式检查,养成这样的习惯很重要,这一点点谨慎的工作,在这个方法第一次抛出参数异常的时候,就开始了对你的回报。


Friday, September 29, 2006