Написание рефлексивного метода для загрузки переменных из файла conf и назначения ссылок?

Я работаю с уродливым кодом и пытаюсь выполнить очистку путем перемещения значений в модуле в файл конфигурации. Я хочу сохранить значения модулей по умолчанию, если переменная не существует в файле conf, в противном случае используйте версию файла conf. В модуле много (слишком много) переменных, поэтому я хотел, чтобы вспомогательный метод поддерживал это. Это первый шаг рефакторинга, я, вероятно, пойду дальше, чтобы лучше обрабатывать переменные конфигурации позже, но по одному шагу за раз.

Я хочу метод, который будет принимать переменную в моем модуле и либо загружать значение из conf или установить значение по умолчанию. Так что-то вроде этого (пишу это с нуля, поэтому пока воспринимайте это как псевдокод)

Our ($var_a, $var_b ...);
export($var_a, $var_b ...);

my %conf = #load config file

load_var(\$var_a, "foo");
load_var(\$var_b, "$var_abar");

sub load_var($$){
   my($variable_ref, $default) = @_

   my $variale_name = Dumper($$variable_ref); #get name of variable

   my $variable_value = $conf{$variable_name} // $default;

   #update original variable by having $variable_ref point to $variable_value
}

Итак, два вопроса здесь. Во-первых, кто-нибудь знает, существует ли какая-либо функциональность, такая как мой load_var, которую я повторно использую?

Во-вторых, если я должен написать это с нуля, могу ли я сделать это с версией perl старше 5.22? когда я читаю perlref, он ссылается на установку ссылок как на новую функцию в 5.22, но кажется странным, что такое базовое поведение ссылок не было реализовано раньше, поэтому мне интересно, неправильно ли я понял документ. Есть ли способ передать переменную в мой метод load_var и убедиться, что она действительно обновлена?

1 ответ

Решение

Для такого рода проблем я бы подумал об использовании AUTOLOAD - я знаю, что это не совсем то, о чем вы просили, но это похоже на нечто подобное:

Если вы вызываете подпрограмму, которая не определена, вы обычно получаете немедленную фатальную ошибку с жалобой на то, что подпрограмма не существует. (Аналогично для подпрограмм, используемых в качестве методов, когда метод не существует ни в одном базовом классе пакета класса.) Однако, если подпрограмма AUTOLOAD определена в пакете или пакетах, используемых для поиска исходной подпрограммы, тогда эта подпрограмма AUTOLOAD вызывается с аргументами, которые были бы переданы исходной подпрограмме.

Что-то вроде:

#!/usr/bin/env perl

package Narf;
use Data::Dumper;
use strict;
use warnings;
our $AUTOLOAD;
my %conf = ( fish => 1, 
             carrot => "banana" ); 

sub AUTOLOAD { 
    print "Loading $AUTOLOAD\n";
    ##read config file
    my $target = $AUTOLOAD =~ s/.*:://gr; 
    print $target;
    return $conf{$target} // 0; 
}

sub boo {
    print "Boo!\n";
}

Вы можете назвать это OO-стилем или просто "нормально", но имейте в виду, что это создает подпрограммы, а не переменные, поэтому вам может потребоваться указать пакет (или иначе "форсировать" импорт / экспорт)

#!/usr/bin/env perl
use strict;
use warnings;

use Narf;

print Narf::fish(),"\n";
print Narf::carrot(),"\n";
print Narf::somethingelse(),"\n";
print Narf::boo;

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

Другие вопросы по тегам