在Perl5中实现功能切换

时间:2012-03-14 22:59:50

标签: perl metaprogramming language-features featuretoggle

我希望能够创建“幽灵”包和潜艇。我有一个配置(ini)文件,其中的条目如下:

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

解析此文件,以后开发人员可以提出以下问题:

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

(整个想法基于Martin Fowler的FeatureToggle http://martinfowler.com/bliki/FeatureToggle.html

使用AUTOLOAD捕获MyApp :: Feature中的调用,使用BEGIN块解析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 :: Humans。

我知道把MyApp :: Feature :: Foo :: Bar建议必须有这样的Package。但是开发人员知道功能包管理功能切换的惯例,他们没有问题。我找到了第一个例子(使用enabled($ string)位太复杂而无法读取

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

第二个更好:

if ( package::package->method )

第三个会更容易:

if ( package::package::package )

那么,是否可以在包级别上模拟AUTOLOAD?

问候, 罗布。


1 个答案:

答案 0 :(得分: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 )}; 更容易使用:

{{1}}