为什么Perl :: Critic不喜欢使用shift来填充子程序变量?

Wee*_*gee 16 perl perl-critic

最近,我决定在我的代码上更频繁地使用Perl :: Critic.在Perl编程近7年后,我已经习惯了大部分Perl最佳实践,但我知道总有改进的余地.有一件事让我烦恼的是,Perl :: Critic并不喜欢我为子程序解包@_的方式.举个例子:

sub my_way_to_unpack {
    my $variable1 = shift @_;
    my $variable2 = shift @_;

    my $result = $variable1 + $variable2;
    return $result;
}
Run Code Online (Sandbox Code Playgroud)

这就是我一直以来的做法,而且,正如PerlMonks和Stack Overflow所讨论的那样,它也不一定是邪恶的.

将上面的代码段更改为...

sub perl_critics_way_to_unpack {
    my ($variable1, $variable2) = @_;

    my $result = $variable1 + $variable2;
    return $result;
}
Run Code Online (Sandbox Code Playgroud)

...也有效,但我发现它更难阅读.我也读过Damian Conway的书Perl Best Practices,我真的不明白我的首选解包方法是否属于他的建议,以避免@_直接使用,正如Perl :: Critic所暗示的那样.我一直认为康威在讨论如下的肮脏:

sub not_unpacking {
    my $result = $_[0] + $_[1];
    return $result;
}
Run Code Online (Sandbox Code Playgroud)

上面的例子很糟糕,很难阅读,我永远不会考虑在一段生产代码中编写它.

简而言之,为什么Perl :: Critic认为我的首选方式不好?我是否真的犯了令人发指的罪行?

这是否是我自己认为应该与Perl :: Critic维护者一起培养的东西?

小智 11

简单的答案是Perl :: Critic在这里没有关注PBP.该书明确指出,转换习语不仅可以接受,而且在某些情况下实际上是首选.


mob*_*mob 9

运行perlcritic--verbose 11解释了策略.但是,这些解释看起来并不适用于您.

Always unpack @_ first at line 1, near 
'sub xxx{ my $aaa= shift; my ($bbb,$ccc) = @_;}'.
  Subroutines::RequireArgUnpacking (Severity: 4)
    Subroutines that use `@_' directly instead of unpacking the arguments to
    local variables first have two major problems. First, they are very hard
    to read. If you're going to refer to your variables by number instead of
    by name, you may as well be writing assembler code! Second, `@_'
    contains aliases to the original variables! If you modify the contents
    of a `@_' entry, then you are modifying the variable outside of your
    subroutine. For example:

       sub print_local_var_plus_one {
           my ($var) = @_;
           print ++$var;
       }
       sub print_var_plus_one {
           print ++$_[0];
       }

       my $x = 2;
       print_local_var_plus_one($x); # prints "3", $x is still 2
       print_var_plus_one($x);       # prints "3", $x is now 3 !
       print $x;                     # prints "3"

    This is spooky action-at-a-distance and is very hard to debug if it's
    not intentional and well-documented (like `chop' or `chomp').

    An exception is made for the usual delegation idiom
    `$object->SUPER::something( @_ )'. Only `SUPER::' and `NEXT::' are
    recognized (though this is configurable) and the argument list for the
    delegate must consist only of `( @_ )'.


fri*_*edo 8

重要的是要记住,Perl最佳实践中的很多东西只是一个人看起来最好或者最容易使用的东西,如果你以另一种方式做到这一点并不重要.达米安在书的介绍性文本中也说了很多.这并不是说这是所有这样的-里面还有很多事情是绝对必要的:使用strict,例如.

因此,当您编写代码时,您需要自己决定自己的最佳实践,并且使用PB​​P是一个很好的起点.然后保持符合您自己的标准.

我尝试跟踪PBP中的大部分内容,但Damian可以使用我的子程序参数shift和我的unlesses,当他从我冷酷的指尖撬开它们时.

对于Critic,您可以选择要强制执行的策略,如果它们尚不存在,甚至可以创建自己的策略.