Подтвердить что ты не робот

Почему Perl:: Critic не нравится использование shift для заполнения переменных подпрограммы?

В последнее время я решил использовать Perl::Critic чаще всего в своем коде. После программирования в Perl уже около 7 лет, я долгое время занимался большинством передовых методов Perl, но я знаю, что всегда есть место для улучшения. Одна вещь, которая меня подслушивала, заключается в том, что Perl::Critic не нравится, как я распаковываю @_ для подпрограмм. В качестве примера:

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

    my $result = $variable1 + $variable2;
    return $result;
}

Так я всегда это делал, и, поскольку он обсуждался как на PerlMonks, так и на Stack Overflow, его не обязательно злой.

Изменение фрагмента кода выше...

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

    my $result = $variable1 + $variable2;
    return $result;
}

... тоже работает, но мне труднее читать. Я также прочитал книгу Дамиана Конвей Perl Best Practices, и я действительно не понимаю, как мой предпочтительный подход к распаковке подпадает под его предложение, чтобы избежать используя @_ напрямую, поскольку Perl::Critic подразумевает. У меня всегда было впечатление, что Конвей говорил о гадости, например:

sub not_unpacking {
    my $result = $_[0] + $_[1];
    return $result;
}

Приведенный выше пример плох и трудно читается, и я никогда не подумал бы написать это в куске производственного кода.

Итак, почему Perl::Critic считают мой предпочтительный способ плохой? Действительно ли я совершаю распаковку отвратительного преступления, используя смену?

Будет ли это что-то, что другие люди, кроме меня, должны быть воспитаны с Perl::Critic поддерживающими?

4b9b3361

Ответ 1

Простой ответ заключается в том, что Perl:: Critic не следует за PBP здесь. в книге явно говорится, что идиома сдвига не только приемлема, но фактически является предпочтительным в некоторых случаях.

Ответ 2

Запуск 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 `( @_ )'.

Ответ 3

Важно помнить, что многие вещи в Perl Best Practices - это всего лишь одно мнение парня о том, что выглядит лучше, или проще всего работать, и неважно, делаете ли вы это по-другому. Дамиан говорит так же во вводном тексте книги. Это не означает, что все это так - есть много вещей, которые абсолютно необходимы: используя strict, например.

Итак, когда вы пишете свой код, вам нужно самому решить, каковы будут ваши собственные лучшие практики, а использование PBP также является хорошей отправной точкой, как любая. Затем придерживайтесь своих стандартов.

Я стараюсь следить за большинством вещей в PBP, но у Damian может быть аргумент подпрограммы shift и мой unless, когда он вытаскивает их из моих холодных, мертвых кончиков пальцев.

Что касается Critic, вы можете выбрать, какие политики вы хотите применить, и даже создать свои собственные, если они еще не существуют.

Ответ 4

В некоторых случаях Perl:: Critic не может точно выполнять рекомендации PBP, поэтому он может обеспечить приближение, которое пытается соответствовать духу рекомендаций Conway. И вполне возможно, что мы неправильно истолковали или неправильно использовали PBP. Если вы найдете что-то, что не имеет запаха, отправьте сообщение об ошибке на [email protected], и мы сразу рассмотрим его.

Спасибо,

-Jeff

Ответ 5

Я думаю, вы, как правило, избегаете сдвига, если это действительно не нужно!

Просто наткнулся на такой код:

sub way {
  my $file = shift;
  if (!$file) {
    $file = 'newfile';
  }
  my $target = shift;
  my $options = shift;
}

Если вы начнете что-то менять в этом коде, есть хороший шанс, что вы можете случайно изменить порядок смены или, может быть, пропустить один, и все идет вглубь. Кроме того, это трудно читать - потому что вы не можете быть уверены, что действительно видите все параметры для sub, потому что некоторые строки ниже могут быть другой сменой где-то... И если вы используете несколько регулярных выражений между ними, они могут заменить содержимое $_ и начинает происходить странный материал...

Прямое преимущество использования распаковки my (...) = @_ - вы можете просто скопировать (...) часть и вставить ее там, где вы вызываете метод, и иметь хорошую подпись:) вы даже можете использовать одни и те же имена переменных заранее и не нужно ничего менять!

Я думаю, что shift подразумевает операции с списком, когда длина списка является динамической, и вы хотите обрабатывать ее элементы по одному за раз или где вам явно нужен список без первого элемента. Но если вы просто хотите назначить весь список параметрам x, ваш код должен сказать это с моим (...) = @_; никто не должен удивляться.