在ruby中编写一个相当简单的命令行工具我需要在命令行参数中报告有关错误的有意义的消息,或者对于程序中的其他错误条件 . (未找到输入文件,输入格式无效等)
现在,我只是在检测到参数列表中的错误时,使用合理的描述引发ArgumentError . 这是一种好的做法,还是冒着隐藏编程错误的风险?换句话说,系统定义的ruby异常是否适用于应用程序,或者我们是否应始终创建自己的异常以报告非系统错误?
Edit: 例如,如果我使用错误数量的参数调用方法,ruby会引发ArgumentError . 这是一个编程错误,我想通过堆栈跟踪和所有来告诉我 . 但是,当我的程序输入不正确时,我可能想给用户一个简短的消息,或者甚至无声地忽略它 . 这告诉我,ArgumentError不适合应用程序自己使用 .
2 回答
我相信最好的做法是在模块中引发自己的自定义错误 . 所有特定的异常类都应该从一个继承自StandardError的命名空间异常继承 . 所以对于你的情况:
并在用户提供错误参数时引发MyApp :: ArgumentError . 这样它就可以区别于代码中的参数错误 . 并且您可以使用MyApp :: Error从您的应用程序中拯救任何未捕获的异常 .
你还应该看看Thor . 它可以为您处理大多数用户参数 . 您可以查看Bundler以获取良好的cli用法示例 .
Ruby 1.9异常层次结构如下:
Ruby 2异常层次结构是:
您可以使用其中一种,也可以创建自己的 . 在创建自己的时候,有几点需要注意 . 例如,
rescue
默认情况下仅拯救StandardError
及其后代 . 我发现这很困难 . 最好确保自定义错误继承自StandardError
. (顺便说一下,为了解救任何异常,请明确使用rescue Exception
. )您可以使用属性,自定义构造函数等创建一个完整的异常类,但标准做法是创建简单的定义:
您可以使用不同的错误消息区分特定错误,或创建错误层次结构 . 通常没有创建复杂的异常层次结构,或者至少我没有看到它的一个例子(我倾向于阅读我使用的库的源代码) . 我所看到的是使用模块命名您的错误,我认为这是一个好主意 .
然后你的异常将是
MyLibrary::ConnectionError
的形式,并从你的库中拯救错误,特别是你可以rescue MyLibrary::Error
并 grab 它们 .注意:另一种语法是
MyError = Class.new(RuntimeError)
,请参阅下面的Steve Klabnik博客文章 .参考文献:
尼克西格尔
Jamis Buck的
Steve Klabnik撰写了
精彩的读物:Exceptional Ruby作者:Avdi Grimm