我时不时地在 StackOverflow 上看到人们推广autodie的使用。但是在这里和网络其他地方的代码中,我不经常看到自动死亡。有一些缺点吗?使用 autodie 时我会丢失一些东西吗?(在使用 autodie 时,我有被宠坏的想法)
4 回答
该autodie文档列出了您应该注意的几个问题和错误。但是,其中大多数都是相对较小的,从长远来看也是可以修复的。
除此之外没有真正的缺点,除了在旧的 perl 版本上运行时可能会产生额外的依赖性。它不经常使用的事实很可能是由于它相对较新。尽管如此,autodie(甚至是旧Fatal模块)通常都是一个好主意。
这项技术大部分都很好,但它的作用是远距离和神奇的。一些只阅读部分代码的人可能不明白会发生什么,因为autodie远离他们检查的代码。由于不是每个人都使用它,而且它最近才成为一种做法,我怀疑大多数人都不会期待它。这并不是什么大不了的事,但那种事情对我来说总是很丑陋。
有一种语言模型遵循C 的基于函数的范例,其中所有函数都返回一个值,由用户检查返回值。Perl 在这个组中。如果我调用一个函数,我有责任检查该函数是否真的返回了有用的东西。
还有另一种语言模型遵循Java 的基于异常的范例,其中失败的函数返回异常,如果用户需要处理异常,他们必须显式处理异常。自 Java 以来编写的大多数现代语言都遵循这种基于异常的方法。
较新的语言是基于异常的,因为它处理了懒惰的开发人员问题。在C风格的编程语言中,如果开发人员忘记或懒得检查函数的退出状态,程序会继续。在Java风格的编程语言中,程序会死掉。在这两种情况下,开发人员都可以处理无效函数结果的问题,这是基于异常的语言迫使开发人员这样做。
怎么没看到use autodie这里?几种理论:
这是新的
pragma 是相当新的autodie,大多数开发人员没有很好的方法将新知识融入他们的 Perl 编程。例如,say自 5.10 以来一直存在,但我仍然看到很少有开发人员使用它,尽管它比print. 如果开发人员autodie在最初学习 Perl 时没有学习,他们可能永远不会知道它。
Perl 中没有 Try/Catch 语法
Perl 通常是这样工作的:
open $fh, "<", $file;
if ( not defined $fh ) {
... # What I do if `$fh` didn't get set.
}
我检查了$fh我的open声明之后的值(好吧,通常你检查它本身的返回值open而不是打开的值$fh,但请耐心等待!)。语法相当简单和干净。这很容易理解。
如果您使用autodie并采用基于异常的方法会怎样?Perl中没有像 Java 中那样的内置try/catch语句。相反,您采用了一种半笨拙的使用方式eval:
use autodie;
my $fh; # Got to be declared outside of the eval
eval {
open $fh, "<", $file;
}; # Don't forget that semicolon!
if ( $@ ) {
... # What I do if function "foo" doesn't return a good value...
}
你能说恶心吗?我知道你可以!因为$fh是词法范围的,所以我必须在我的eval. 另外,我什至没有涉及成为$@全局范围变量的整个问题!
这是不完整的方式
大多数模块和内置函数都无法使用,autodie它们或多或少仅限于 IO 调用、fork、system和exec,即使在这里,它也是不完整的:print并且flock不能使用autodie. 除此之外,没有其他 Perl 内置函数可用于autodie. 从空数组中弹出值不会迫使我的程序发牢骚。很少有模块会检查状态autodie以查看其函数或方法是否应该croak返回错误值。因此,将 Perl 转变为基于异常的语言的整个想法并没有发生。
即使你认为autodie可以工作的地方也没有。如果您用于File::Copy获取copyandmove命令,请不要依赖于autodie捕获错误的文件副本。您仍然需要检查copy. 如果你使用File::IO,所有的赌注autodie都将被取消。
因此,autodie它并没有完全兑现将 Perl 转变为更加基于异常的编程语言的大胆承诺。对于大多数人来说,它主要是 catchopen语句,大多数开发人员对open ... or die....
我喜欢基于异常的开发方法,并且我相信所有模块都应该默认出现错误。强制开发人员处理异常而不是忽略它们。当出现问题时,我编写我的模块和函数来发牢骚,并用于eval处理异常。不幸的是,autodie现在并没有做很多事情。
另一个考虑因素是 autodie 和 utf8::all 直到最近发布的 utf8::all才能很好地结合在一起。utf8::all 是另一个方便的模块,它和 autodie 一样,帮助设置 Perl 自动执行常见任务(这次是 unicode)。