Можно ли использовать модули из подпрограмм?
Недавно я начал играть с OO Perl и создал довольно много новых объектов для нового проекта, над которым я работаю. Поскольку я не знаком с любой лучшей практикой в отношении OO Perl, и мы добросовестно пытаемся это сделать:P
Я помещаю много такого кода в каждую из моих функций:
sub funcx{
use ObjectX; # i don't declare this on top of the pm file
# but inside the function itself
my $obj = new ObjectX;
}
Мне было интересно, если это вызовет какое-либо негативное влияние по сравнению с положением на use Object
линия над модулями Perl вне области действия любой функции.
Я делал это так, чтобы чувствовать себя чище, на случай, если мне нужно будет изменить функцию.
И еще одна вещь, которую я заметил, это то, что когда я пытаюсь запустить сценарий test.pl на самом сервере unix, который проверяет мои объекты, он медленно работает. Но когда тот же код выполняется через CGI, который подключен к серверу Apache, веб-страница загружается не так медленно.
3 ответа
Где использовать?
use
происходит во время компиляции, поэтому не имеет значения, куда вы его поместите. По крайней мере, с чисто прагматической точки зрения, "будет ли это работать". Потому что это происходит во время компиляции use
всегда будет выполняться, даже если вы поставите его в условный. Никогда не делай этого: if( $foo eq 'foo' ) { use SomeModule }
По моему опыту, лучше всего поместить все ваши операторы использования в начало файла. Это позволяет легко увидеть, что загружается и каковы ваши зависимости.
Обновить:
Как указывает Брайан Д. Фой, вещи, собранные до use
заявление не будет затронуто этим. Таким образом, местоположение может иметь значение. Для типичного модуля местоположение не имеет значения, однако, если оно влияет на компиляцию (например, импортирует функции с прототипами), местоположение может иметь значение.
Также Час Оуэнс указывает, что это может повлиять на компиляцию. Модули, предназначенные для изменения компиляции, называются прагмами. Прагмы, как правило, получают имена в нижнем регистре. Эти эффекты применяются только в пределах области применения модуля. Час использует integer
Прагма в качестве примера в своем ответе. Вы также можете отключить прагму или модуль в ограниченном объеме с ключевым словом no
,
use strict;
use warnings;
my $foo;
print $foo; # Generates a warning
{ no warnings 'unitialized`; # turn off warnings for working with uninitialized values.
print $foo; # No warning here
}
print $foo; # Generates a warning
Косвенный объектный синтаксис
В вашем примере кода у вас есть my $obj = new ObjectX;
, Это называется косвенным синтаксисом объекта, и его лучше избегать, поскольку это может привести к неясным ошибкам. Лучше использовать эту форму:
my $obj = ObjectX->new;
Почему ваш тестовый скрипт работает медленно на сервере?
Невозможно рассказать с помощью предоставленной вами информации.
Но самый простой способ выяснить это - профилировать ваш код и посмотреть, где расходуется время. NYTProf - еще один популярный инструмент профилирования, который вы можете попробовать.
Лучшие практики
Ознакомьтесь с рекомендациями Perl и краткой справочной картой. Эта страница содержит краткий обзор рекомендаций ОАП Дамиана Конвея от PBP.
Кроме того, вы можете рассмотреть возможность использования Moose. Если длительное время запуска сценария приемлемо для вас, Moose - это огромный выигрыш.
Вопрос 1
Это зависит от того, что делает модуль. Если он имеет лексический эффект, то он будет влиять только на область, в которой он используется:
my $x;
{
use integer;
$x = 5/2; #$x is now 2
}
my $y = 5/2; #$y is now 2.5
Если это обычный модуль, то не имеет значения, где вы его используете, но обычно используются все эти модули в верхней части программы.
вопрос 2
Вещи, которые могут повлиять на скорость программы между машинами
- скорость процессора
- версия установленных модулей (некоторые модули имеют версии XS, которые намного быстрее)
- версия Perl
- количество записей в PERL5LIB
- скорость езды
Даотоад и час. Оуэнс уже ответил на часть вашего вопроса, относящуюся к позиции заявления об использовании. Позвольте мне отметить кое-что еще здесь:
Я делал это так, чтобы чувствовать себя чище, на случай, если мне нужно будет изменить функцию.
Лично я считаю, что все используемые модули находятся в одном месте вверху файла. Вам не придется искать операторы использования, чтобы увидеть, какие другие модули используются, и быстрый взгляд скажет вам, что используется и даже что не используется.
Что касается вашей проблемы с производительностью: с Apache и mod_perl интерпретатор Perl должен будет проанализировать и скомпилировать ваши используемые модули только один раз. При следующем запуске сценария выполнение должно быть намного быстрее. Однако в командной строке второй запуск не дает этого преимущества.