Расширенный поиск функций в @INC - PullRequest
2 голосов
/ 09 марта 2020

Мы являемся авторами большого, сложного Perl программного продукта. Часть кода находится в исполняемых файлах (сетевых демонах), а часть - в Perl библиотеках (файлы .pm). Некоторые из наших клиентов хотят настроить свои системы, переопределив наши функции Perl 'sub xxx {}' собственным кодом. Это довольно просто сделать, когда мы вызываем функцию в другой библиотеке - мы помещаем / usr / local / lib / our_product в @ IN C, и они могут поместить туда свой собственный код. С этим связаны две проблемы:

  1. Созданный ими пользовательский файл должен иметь все функции в файле .pm, которые они переопределяют. Если они отсутствуют, Perl не найдет их в файле по умолчанию .pm, который мы отправляем.

  2. Perl всегда проверяет локальный файл перед @ IN C. Это препятствует тому, чтобы их пользовательский файл .pm переопределял вызовы функций в одном и том же файле.

Есть ли способы обойти эти проблемы?

Ответы [ 2 ]

3 голосов
/ 10 марта 2020

Когда я сделал это для унаследованного кода, я создал пакет с другим именем, который сначала будет загружать пакеты поставщика, а затем разрешать переопределения:

 package Local::Overrides;
 use Vendor::Real::Name;
 use Vendor::Other::Name;


 package Vendor::Real::Name {
     no warnings 'redefine';

     sub new_definition {

          }
     };

 package Vendor::Other::Name {
     no warnings 'redefine';

     sub new_definition {

          }
     };

1; 

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

package Local::Overrides;

1;

Я расскажу о некоторых вещах такого рода в Эффективных Perl Программирование .

Есть много других хитростей, но, не зная специфики вашей архитектуры, я не могу многое порекомендовать.

2 голосов
/ 09 марта 2020

На самом деле нет необходимости, чтобы их пользовательский код находился в файлах, соответствующих именам пакетов, и, следовательно, заменял или должен был взаимодействовать с его загрузкой из @INC. Вы можете просто организовать загрузку пользовательского кода после другого файла, который все еще изменяет исходные пакеты. Конечно, это должно произойти до любого импорта из этого пакета, и вы захотите отключить redefine предупреждений в таком файле.

# Whatever.pm
package Some::Module;
use strict;
use warnings;
no warnings 'redefine';
sub foo { ... }

Переопределения могут даже использовать Class :: Method :: Модификаторы , которые способны заменить сабы на место оберткой, даже если не задействованы никакие классы или методы.

use Class::Method::Modifiers;
around 'Some::Module::foo' => sub { ... };

Самый большой молот, если вы действительно не хотите изменять существующие файлы любым способом могут быть настроены на сайте, что описано здесь , или App :: My Perl, что является несколько более сфокусированной версией этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...