2012-03-14 2 views
3

Я хотел бы иметь возможность создавать пакеты «призраки» и субтитры. У меня есть файл конфигурации (INI) с записями вроде этого:Реализация функции Toggle в Perl5

[features] 
sys.ext.latex = off 
gui.super.duper.elastic = off 
user.login.rsa = on 

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

if (MyApp::Feature->enabled ('user.login.rsa') { ... } 

(Вся идея основана на FeatureToggle Мартина Фаулера http://martinfowler.com/bliki/FeatureToggle.html)

Использование автозагрузку для ловли звонков в MyApp :: Характеристика и НАЧАТЬ блок для разбора INI файл, который мы можем предоставить этот API:

if (MyApp::Feature->user_login_rsa) { ... } 

Возникает вопрос: можно ли создать следующий API:

if (MyApp::Feature::User::Login::RSA) { ... } 

имея только MyApp :: Feature?

Нижняя, верхний регистр может быть изменен в файле конфигурации, это не проблема. И ясно, что реализация отделена от конфигурации, нет MyApp :: Feature :: User :: Login :: RSA и никогда не будет. Реализация этой функции заключается в том, что f.e. в MyApp :: Люди.

Мне известно, что установка MyApp :: Feature :: Foo :: Bar предполагает наличие такого Пакета. Но разработчики знают соглашение, что пакет Feature управляет переключением функций, и у них не было бы проблем с этим. Я считаю, первый пример (с использованием включен бит ($ строка) слишком сложный для чтения

if (package::package->method (string)) 

второй лучше:

if (package::package->method) 

третий будет еще проще:

if (package::package::package) 

Итак, можно ли моделировать AUTOLOAD на уровне упаковки?

Привет, Ro б.

+0

Дьявол в деталях: 'MyApp :: Характеристика :: Пользователь :: Вход :: RSA' не пройдите строго, это гобе. Вы можете сделать последнюю часть вызовом функции, таким образом: 'MyApp :: Feature :: User :: Login :: RSA()' – daxim

ответ

4

Похоже, что у вас есть список ключей с несколькими словами, которые вы хотите установить в пространство имен.

BEGIN { 
    my %states = (# the values that should be transformed 
     on => sub() {1}, 
     off => sub() {''}, 
    ); 
    sub install_config { 
     my ($package, $config) = @_; 
     for my $key (keys %$config) { 
      my @parts = map ucfirst, split /\./, $key; 
      my $name = join '::' => $package, @parts; 
      no strict 'refs'; 
      *{$name} = $states{$$config{$key}} # use a tranformed value 
        || sub() {$$config{$key}} # or the value itself 
     } 
    } 
} 

BEGIN { 
    my %config = qw(
     sys.ext.latex   off 
     gui.super.duper.elastic off 
     user.login.rsa   on 
     some.other.config  other_value 
    ); 
    install_config 'MyApp::Feature' => \%config; 
} 

say MyApp::Feature::Sys::Ext::Latex ? 'ON' : 'OFF';    # OFF 
say MyApp::Feature::Gui::Super::Duper::Elastic ? 'ON' : 'OFF'; # OFF 
say MyApp::Feature::User::Login::Rsa ? 'ON' : 'OFF';   # ON 
say MyApp::Feature::Some::Other::Config;      # other_value 

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

Вы можете сделать install_config немного проще в использовании, поместив его в функцию импорта пакета в:

BEGIN {$INC{'Install/Config.pm'}++} # fool require 

sub Install::Config::import {shift; goto &install_config} 

use Install::Config 'MyApp::Feature' => {qw(
    sys.ext.latex   off 
    gui.super.duper.elastic off 
    user.login.rsa   on 
    some.other.config  other_value 
)}; 
Смежные вопросы