Ruby中的异常处理代码编写示例
单个异常使用fail关键字仅仅当捕获一个异常并且反复抛出这个异常(因为这里你不是失败,而是准确的并且故意抛出一个异常)。
begin fail'Oops' rescue=>error raiseiferror.message!='Oops' end
不要为fail/raise指定准确的RuntimeError。
#bad failRuntimeError,'message' #good-signalsaRuntimeErrorbydefault fail'message'
宁愿提供一个异常类和一条消息作为fail/raise的两个参数,而不是一个异常实例。
#bad failSomeException.new('message') #Notethatthereisnowaytodo`failSomeException.new('message'),backtrace`. #good failSomeException,'message' #Consistentwith`failSomeException,'message',backtrace`.
不要在ensure块中返回。如果你明确的从ensure块中的某个方法中返回,返回将会优于任何抛出的异常,并且尽管没有异常抛出也会返回。实际上异常将会静静的溜走。
deffoo begin fail ensure return'verybadidea' end end
Useimplicitbeginblockswhenpossible.如果可能使用隐式begin代码块。
#bad deffoo begin #mainlogicgoeshere rescue #failurehandlinggoeshere end end #good deffoo #mainlogicgoeshere rescue #failurehandlinggoeshere end
通过contingencymethods偶然性方法。(一个由AvdiGrimm创造的词)来减少begin区块的使用。
#bad begin something_that_might_fail rescueIOError #handleIOError end begin something_else_that_might_fail rescueIOError #handleIOError end #good defwith_io_error_handling yield rescueIOError #handleIOError end with_io_error_handling{something_that_might_fail} with_io_error_handling{something_else_that_might_fail}
不要抑制异常输出。
#bad begin #anexceptionoccurshere rescueSomeError #therescueclausedoesabsolutelynothing end #bad do_somethingrescuenil
避免使用rescue的修饰符形式。
#bad-thiscatchesexceptionsofStandardErrorclassanditsdescendantclasses read_filerescuehandle_error($!) #good-thiscatchesonlytheexceptionsofErrno::ENOENTclassanditsdescendantclasses deffoo read_file rescueErrno::ENOENT=>ex handle_error(ex) end
不要用异常来控制流。
#bad begin n/d rescueZeroDivisionError puts"Cannotdivideby0!" end #good ifd.zero? puts"Cannotdivideby0!" else n/d end
应该总是避免拦截(最顶级的)Exception异常类。这里(ruby自身)将会捕获信号并且调用exit,需要你使用kill-9杀掉进程。
#bad begin #callstoexitandkillsignalswillbecaught(exceptkill-9) exit rescueException puts"youdidn'treallywanttoexit,right?" #exceptionhandling end #good begin #ablindrescuerescuesfromStandardError,notExceptionasmany #programmersassume. rescue=>e #exceptionhandling end #alsogood begin #anexceptionoccurshere rescueStandardError=>e #exceptionhandling end
将更具体的异常放在救援(rescue)链的上方,否则他们将不会被救援。
#bad begin #somecode rescueException=>e #somehandling rescueStandardError=>e #somehandling end #good begin #somecode rescueStandardError=>e #somehandling rescueException=>e #somehandling end
在ensure区块中释放你程式获得的外部资源。
f=File.open('testfile') begin #..process rescue #..handleerror ensure f.closeunlessf.nil? end
除非必要,尽可能使用Ruby标准库中异常类,而不是引入一个新的异常类。(而不是派生自己的异常类)