2010-06-16 127 views
2

处理彼此使用的模块的最佳方式是什么?处理彼此使用模块的最佳方式是什么?

比方说,我有这对于哈希函数模块:已分割出的名单

# Really::Useful::Functions::On::Hash.pm 

use base qw<Exporter>; 
use strict; 
use warnings; 

use Really::Useful::Functions::On::List qw<transform_list>; 

our @EXPORT_OK = qw<transform_hash transform_hash_as_list ...>; 

#... 
sub transform_hash { ... } 

#... 
sub transform_hash_as_list { 
    return transform_list(%{ shift() }); 
} 
#... 
1 

而另一个模块:

# Really::Useful::Functions::On::List.pm 

use base qw<Exporter>; 
use strict; 
use warnings; 

use Really::Useful::Functions::On::Hash qw<transform_hash>; 

our @EXPORT_OK = qw<transform_list some_func ...>; 

#... 
sub transform_list { ... } 

#... 
sub some_func { 
    my %params = transform_hash @_; 
    #... 
} 

#... 
1 

假设足够的这些实用功能足够方便我希望在BEGIN语句和导入函数中使用它们来处理参数列表或配置数据。

我一直在将子定义放入BEGIN块以确保它们随时可以使用,只要有人包含该模块。但是我已经进入了毛病的比赛条件,在BEGIN块中没有完成定义。

我将不断演变的代码习惯用法放入模块中,以便我可以重复使用任何习惯用法,我发现自己一次又一次地编码。例如:

sub list_if { 
    my $condition = shift; 
    return unless $condition; 
    my $more_args = scalar @_; 
    my $arg_list = @_ > 1 ? \@_ : @_ ? shift : $condition; 
    if ((reftype($arg_list) || '') eq 'ARRAY') { 
     return wantarray ? @$arg_list : $arg_list; 
    } 
    elsif ($more_args) { 
     return $arg_list; 
    } 
    return; 
} 

捕捉这两种习惯用法,我是有点累打字:

@{ func_I_hope_returns_a_listref() || [] } 

($condition ? LIST :()) 

我越在定义函数BEGIN块,越有可能我将使用这些成语砖来表达逻辑,BEGIN块中需要更多砖块。

人们是否有处理这种语言成语砖模型的标准方法?

我一直在做的主要是Pure-Perl; XS是否会缓解一些呢?

+2

替补在编译时被加载,无论它们是否在BEGIN块。你可以展示一个你需要在BEGIN块中定义的函数的例子吗? – mob 2010-06-16 15:58:19

+0

@mobrule:或许我不需要把它们放在BEGIN块中,但这就是工作,使用修补程序,直到你没有一个“解决”问题的错误方法。当我试图积累越来越多的这些成语砖以逐步提高编码和测试的速度时,哪种激励了长期存在的问题。 – Axeman 2010-06-16 16:16:19

回答

2

如果两个模块是相互依赖的,那么设计就会出现问题。如果我是你,我会考虑重构我的模块。

+0

这是一种可能性,但这些并不是真正的“设计”元素,但或多或​​少是代码习语的集合,这些习语本身在其他代码习语中很有用。 – Axeman 2010-06-16 16:34:24

2

您可以拥有两个模块,每个模块都可以调用另一个模块,因为这些调用是在运行时完成的,然后“所有”都将被加载。但是,(显然)这意味着您需要进入运行阶段而不会被炸掉。一种常用的方法是将其他模块包含在内,比这两个模块中的任何一个都早,包括use。直接删除直接use语句的结果是,您将失去这些导入,但是将符号从一个模块导入另一个模块并不是一个好主意。

看着你写的代码,我感到非常惊讶,你已经想出了许多处理数据的“新”方法,你觉得需要将这些数据提取到不同的库中。你看过标准库Hash::Util,List::UtilList::MoreUtils吗?我建议你使用标准库,以更习惯的Perlish方式退出你的库和代码。

+0

'List :: Util'和'List :: MoreUtils'肯定存在,但'Hash :: Util'作为散列的一般实用程序库几乎没有用处,除非您的问题是锁定键和其他一些处理哈希的硬结构,而不是它们作为通用实现的一般抽象:名称 - 值协会。具有讽刺意味的是,我想在CPAN上放置一个广义的散列实用程序,这部分激发了我对我的“解决方案”的担忧。 AFAIK,对于* OO *模块,进口主要是一个坏主意,因为它们会给出关于类能力和推断行为的误报。 – Axeman 2010-06-16 16:32:03

5

如果你想拥有相互依赖的模块,一个简单的方法来完成这项工作是使用具有完全限定名称的后期绑定子例程调用(换句话说,在子调用中使用parens)。原型不会工作,但Perl不会在意Somepackage::mysub()没有定义,直到你真的试图调用它。当我编写相互依赖的模块时,我通常将它们保存在同一个文件中,通过完全避免导入来简化情况。

而且,没有必要在一个BEGIN块来定义自sub name {...}子相同BEGIN {*name = sub {...}}

相关问题