Почему бы не использовать строгие предупреждения и предупреждения в Perl?
Я видел запутанный и играющий в гольф код, который держится, чтобы не объявлять переменные, и я вижу, как пропустить их в командной строке с помощью ключа -e, чтобы уменьшить однострочный шрифт. Каковы случаи, когда вы не хотели бы use strict
и/или use warnings
в производственном коде?. Какими причинами вы не хотели бы их использовать?
Вопрос возникает потому, что я видел сообщения здесь, где опытные пользователи Perl рассказывают людям, которые не знакомы с Perl, всегда использовать их.
Здесь я нашел некоторые связанные вопросы, но они не объясняют случаи, когда мы могли бы отключить их.
Ответы
Ответ 1
Прагма strict
ограничивает вас подходящим подмножеством Perl. Некоторые старые функции имеют исторический смысл (или имеют преимущества с одним лайнером), но им не место в современной, читаемой базе кода.
Прагма strict
имеет три категории:
-
"vars"
Заставляет вас объявлять все ваши переменные. Это защищает от опечаток и гарантирует, что вы выберете область действия (глобальную/лексическую). В однострочном пространстве это не так необходимо, поскольку, как правило, очень мало областей и очень мало переменных. Некоторые одноязычные идиомы не будут работать только с лексическими переменными.
-
"refs"
запрещает symrefs. Они не имеют смысла с лексическими переменными, а Perl5 имеет реальные ссылки. Поэтому они вообще бесполезны. Тем не менее, symrefs остаются ценными для метапрограммирования:
# generate accessors
for my $field (qw/foo bar baz/) {
no strict 'refs';
*{ __PACKAGE__ . '::' . $field } = sub { shift()->{$field} };
}
-
"subs"
заставляет интерпретировать большинство простых слов как вызовы подпрограмм. Это устраняет двусмысленность foo . "bar"
как foo() . "bar"
. Если эта категория не активирована, и если в настоящее время не определено значение foo
, то оно будет анализироваться как "foo" . "bar"
. Это имеет смысл для программиста оболочки, где все слова являются строками. Но в программе Perl это значительно увеличивает когнитивную нагрузку программиста и не стоит того.
Сводка: для простых скриптов, которые не оптимизируются для чтения, strict "vars"
на самом деле не обязательно. Есть несколько случаев, когда требуется no strict 'refs'
.
Прагма warnings
позволяет осуществлять мелкозернистый контроль над предупреждающими сообщениями. Это особенно важно для программистов, новых для Perl, которые часто пишут такие вещи, как
my %hash = { foo => 1, bar => 2 };
и задайтесь вопросом, откуда взялся этот ключ HASH(0x1234567)
. Желательно, даже если вы используете однострочный вкладыш, за исключением случаев, когда вы используете строение undef
и т.д.
В профессиональной кодовой базе нет оправдания для того, чтобы не использовать warnings
всюду. Если предупреждение script предупреждает, что, скорее всего, есть ошибка, а no warnings
не устраняет эту ошибку. Ваши знания о Perl никогда не столь обширны, как у прагмы warnings
. Даже гуру ошибаются. use warnings
- отличный отладочный ярлык.
Тем не менее, при развертывании программы может быть просто комментировать use warnings
. Но никогда не для развития.
В зависимости от консенсуса в команде разработчиков также должны использоваться другие прагмы:
-
no indirect
запрещает вызовы метода lathed new Foo
. Я видела ошибки, которые можно было поймать во время компиляции с этой прагмой.
-
no autovivification
предотвращает появление ссылок на операции только для чтения, такие как $hash{doesnt_exist}{foo}
.
Ответ 2
Иногда strict
и warnings
мешают вам делать то, что вы хотите сделать, например, делать определенные манипуляции в таблице символов, которые будут нарушать strict 'refs'
, или переопределить подпрограмму, в которой будет срабатывать warnings 'redefine'
. В других случаях более удобно игнорировать определенные предупреждения, чем писать защитный код против них, например, быстрый и грязный дамп базы данных для таблицы, которая может содержать значения NULL/undef
, которые будут запускать warnings 'uninitialized'
.
use strict
и use warnings
, а их замедлители no strict
и no warnings
могут быть локально локализованы, поэтому лучше всего отключить strict
и warnings
в наименьшей практической области.
@data = get_some_data_from_database();
if (some_condition()) {
no warnings 'uninitialized';
logger->debug("database contains: @$_") for @data;
## otherwise, suppressing the warnings would take something
## less readable and more error-prone like:
# logger->debug("database contains: @{[map{defined?$_:''}@$_]}") for @data
# logger->debug("database contains: @{[map{$_//''}@$_]}") for @data
}
# end of scope, warnings `uninitialized' is enabled again
Ответ 3
Выполнение use strict
и use warnings
помогает кому-то точно понять, что делает Perl.
Кто-то, кто понимает точно, что делает Perl, и почему все время (т.е. практически никто), не может отказаться от них, чтобы сэкономить место и, возможно, время выполнения. К сожалению, многие люди, которые хотят экономить место и время, это те, кто не знает точно, что делает Perl, и почему, и их понимание того, что делает Perl, основано на стольких ложных предположениях, полученных с других языков, что они никогда не должны позволять их пропускать.
Есть и другие веские причины:
- экспериментирование с поведением, которое приведет к предупреждению о том, что вы уже полностью осознаете (например, много рекурсии)
- с использованием старых пакетов (хотя любой из моих пакетов, написанных после июля 2000 года, по-прежнему не генерирует сообщений с
use strict
или use warnings
, поэтому "старый" здесь означает действительно, действительно старый, например Perl версии 4 или старше)
- когда вы хотите воспользоваться магическим поведением Perl, которого никто не ожидал бы (но который вы ожидаете, потому что вы эксперт) и не хотите платить цену за предупреждение за это
Кстати, для программ, принимающих любые входные и выполняемые действия на основе этого ввода, также очень важно использовать флаг -T
, чтобы помочь отслеживать использование возможно испорченных данных, полученных от пользовательского ввода.
Обновление: @mob делает заявку в комментарии, которая имеет некоторое исследование, то есть, что не использование строгих и предупреждений - это микро-оптимизация ниже точки даже средних незначительных микроптимизаций. В каждом случае ниже реальное время для не использования строгих и предупреждений составляет 12 миллисекунд, и в каждом случае ниже реальное время их использования составляет 57 миллисекунд или более.
Таким образом, как я уже сказал, это возможное преимущество во время исполнения (что будет иметь значение, если вы делаете что-то вроде встраивания скриптов Perl в шаблоны и запускаете 10 или 20 из них за раз каждый раз, когда веб-страница был загружен, например), но по-прежнему рекомендуется использовать их, если вы точно не знаете, что делает Perl и почему, все время. Мое описание этой категории "экспертов" должно быть очень близко к пустому набору. Если вы считаете, что попадаете в эту категорию, вы автоматически этого не делаете.
[[email protected] ~]$ time perl -e '1;'
real 0m0.012s
user 0m0.005s
sys 0m0.007s
[[email protected] ~]$ time perl -e '1;'
real 0m0.012s
user 0m0.010s
sys 0m0.005s
[[email protected] ~]$ time perl -e '1;'
real 0m0.012s
user 0m0.011s
sys 0m0.001s
[[email protected] ~]$ time perl -e '1;'
real 0m0.012s
user 0m0.004s
sys 0m0.007s
[[email protected] ~]$ time perl -e '1;'
real 0m0.012s
user 0m0.005s
sys 0m0.007s
[[email protected] ~]$ time perl -e 'use strict; use warnings;'
real 0m0.058s
user 0m0.058s
sys 0m0.000s
[[email protected] ~]$ time perl -e 'use strict; use warnings;'
real 0m0.057s
user 0m0.041s
sys 0m0.016s
[[email protected] ~]$ time perl -e 'use strict; use warnings;'
real 0m0.057s
user 0m0.033s
sys 0m0.025s
[[email protected] ~]$ time perl -e 'use strict; use warnings;'
real 0m0.057s
user 0m0.050s
sys 0m0.009s