【问题标题】:Are there disadvantages to autodie?autodie有缺点吗?
【发布时间】:2010-10-15 11:08:20
【问题描述】:

我时不时地在 StackOverflow 上看到人们提倡使用 autodie。但是在这里和网络其他地方的代码中,我不经常看到自动死亡。有一些缺点吗?使用 autodie 时我会丢失一些东西吗? (在使用 autodie 时,我有被宠坏的想法)

【问题讨论】:

    标签: perl autodie


    【解决方案1】:

    这项技术大部分都很好,但它的作用是远距离和神奇。一些只阅读部分代码的人可能不明白会发生什么,因为autodie 离他们检查的代码很远。由于不是每个人都使用它,而且它最近才成为一种做法,我怀疑大多数人都不会期待它。这没什么大不了的,但这种事情对我来说总是很丑陋。

    【讨论】:

    • 我在翻译您的答案时遇到了一些困难。你能解释一下“不要指望它”的部分吗?是指期待在这里等待吗? “它”指的是什么?
    • 很多人不知道 autodie 已启用,因为它的声明与他们正在查看的代码相去甚远。
    【解决方案2】:

    有一种语言模型遵循C 的 基于函数的范例,其中所有函数都返回一个值,并由用户检查返回值。 Perl 在这个组中。如果我调用一个函数,我有责任检查该函数是否真的返回了有用的东西。

    还有另一种语言模型遵循Java 的 基于异常的范例,其中失败的函数返回异常,如果用户需要处理异常,他们必须显式处理异常。自 Java 以来编写的大多数现代语言都遵循这种基于异常的方法。

    较新的语言是基于异常的,因为它处理懒惰的开发人员问题。在 C 风格的编程语言中,如果开发人员忘记或懒得检查函数的退出状态,程序会继续。在 Java 风格的编程语言中,程序会死掉。在这两种情况下,开发人员可以处理无效函数结果的问题,只是基于异常的语言迫使开发人员这样做。

    为什么你在这里看不到use autodie?几种理论:

    这是新的

    autodie pragma 是相当新的,大多数开发人员没有很好的方法将新知识融入他们的 Perl 编程。例如,say 从 5.10 开始就已经存在,但我仍然看到很少有开发人员使用它,尽管它比 print 有了很大的改进,并且使用简单。如果开发人员在最初学习 Perl 时没有学习 autodie,他们可能永远不会知道它。

    Perl 中没有 Try/Catch 语法

    Perl 通常是这样工作的:

    open $fh, "<", $file;
    if ( not defined $fh ) {
       ...    # What I do if `$fh` didn't get set.
    }
    

    我在open 语句之后检查$fh 的值(好吧,通常你检查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调用forksystemexec,即使在这里,它也不完整:printflock 不适用于 autodie。除此之外,没有其他 Perl 内置函数可与 autodie 一起使用。从空数组中弹出值不会迫使我的程序发牢骚。很少有模块会检查autodie 的状态以查看它们的函数或方法是否应该croak 而不是返回false 值。因此,将 Perl 转变为基于异常的语言的整个想法并未实现。

    即使您认为autodie 可以工作的地方也没有。如果您使用File::Copy 获取copymove 命令,请不要依赖autodie 来捕获错误的文件副本。您仍然需要检查copy 的返回值。如果您使用File::IO,则所有带有autodie 的投注都将关闭。

    因此,autodie 并没有完全兑现其将 Perl 转变为更加基于异常的编程语言的大胆承诺。对于大多数人来说,它主要是捕获open 语句,大多数开发人员对open ... or die... 没有问题。

    我喜欢基于异常的开发方法,并且我相信默认情况下所有模块都应该因错误而发牢骚。强制开发人员处理异常而不是忽略它们。当出现问题时,我编写模块和函数来呱呱叫,并使用eval 来处理异常。不幸的是,autodie 现在并没有做很多事情。

    【讨论】:

    • 您的答案与“但是,其中大多数都是相对较小的,从长远来看也是可以修复的”:) 我不会使用它,因为它的逻辑背后的神秘性,但很高兴现在知道有实际理由不这样做:)
    【解决方案3】:

    autodie documentation 列出了一些您应该注意的问题和错误。但是,其中大部分相对较小,从长远来看也是可以修复的。

    除了在旧的 perl 版本上运行时可能会产生额外的依赖性之外,没有真正的缺点。它不经常使用的事实很可能是由于它相对较新。不过,autodie(甚至旧的Fatal 模块)通常是个好主意。

    【讨论】:

    • 我将文档解释为您想与 autodie 一起使用的任何用户定义的子例程必须在 any 调用 use autodie; 之前声明在useing 任何模块之前声明(这是否意味着原型?)任何您想使用的子组件,因为该模块可能在内部use autodie; - 有什么想法吗?还想知道与 AUTOLOAD 的交互。
    • 这意味着如果你想使用autodie 使一个非内置函数致命,你必须要么完全定义它,要么先预先声明它。这与原型无关。其用例通常是您无法控制的模块,但它们具有通过返回魔术值来指示失败的奇怪语义。因此,您所要做的就是在 autodie 之前加载它们。很容易。对于您自己的函数,您总是可以通过适当的异常使其失败,或者可能在其周围编写一个 magic-retval 包装器,以防您需要考虑向后兼容性。
    • AUTOLOAD 用于方法autodie 用于使函数致命。
    • 谢谢。我不知道可以在不使用原型的情况下在 Perl 中“预先声明”函数,但一些谷歌搜索表明 use subs qw(foofunc barfunc); 就是这样做的。这是你的意思吗?我还担心如果它们 use autodie;,您加载的其他 模块是否会导致问题。假设我想使用模块 A 和 B,并自动对 B.pm 中定义的 f() 进行自动化处理。我写use A; use B; use autodie qw(f);。但是如果 A.pm 在内部调用use autodie;,例如在其import()?世界会爆炸吗?
    • use subs ... 通常不需要预先声明潜艇。您可以使用没有正文的子声明。 sub foo; ... later in the code ...; sub foo { ... }
    【解决方案4】:

    另一个考虑因素是 autodie 和 utf8::all 在recent release of utf8::all 之前不能很好地配合使用。 utf8::all 是另一个方便的模块,它和 autodie 一样,帮助设置 Perl 自动执行常见任务(这次是 unicode)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-26
      • 2011-02-28
      • 1970-01-01
      • 2011-11-05
      • 2011-11-05
      • 1970-01-01
      • 1970-01-01
      • 2015-01-01
      相关资源
      最近更新 更多