1

来自 perlmonks 的交叉发布:

我必须在 $work 上清理一些粗糙的、古老的代码,在我尝试制作一个新模块之前,如果有人知道合适的东西,我很乐意使用现有的模块。

在运行时,我正在解析一个文件以确定我需要对一组数据进行哪些处理。

如果我要编写一个模块,我会尝试更通用(非 DBI 特定),但我的确切用例是这样的:

我阅读了一个 SQL 文件来确定要对数据库运行的查询。我解析顶部的评论并确定

  • A 列需要有 as/// 应用,
  • B 列需要转换为给定格式的日期,
  • C 列得到一种 tr///。
  • 此外,可以链接事物,以便 D 列可能 s///,然后说如果它不是 1 或 2,则将其设置为 3。

因此,当从数据库中获取数据时,程序会在返回数据之前应用各种(可能是堆叠的)转换。

目前,代码是一系列令人作呕的大而困难的 if 子句,处理极其难以阅读或维护的指令数组。

所以我想象的可能是一个对象,它将解析这些行(并另外公开一个功能接口),堆叠要应用的处理器列表,然后能够在传递的数据上执行它。

可选地,可以有一个名称/类别选项,以便可以动态地使用一个对象来仅为给定的名称/类别/列堆叠处理器。

一个传统人为设计的例子:

$obj = $module->new();  
$obj->parse("-- greeting:gsub: /hi/hello"); # don't say "hi"  
$obj->parse("-- numbers:gsub: /\D//"); # digits only  
$obj->parse("-- numbers:exchange: 1,2,3 one,two,three"); # then spell out the numbers  
$obj->parse("-- when:date: %Y-%m-%d 08:00:00"); # format like a date, force to 8am  
$obj->stack(action => 'gsub', name => 'when', format => '/1995/1996/'); # my company does not recognize the year 1995.  

$cleaned = $obj->apply({greeting => "good morning", numbers => "t2", when => "2010116"});  

每个处理器(gsub、date、exchange)都是一个单独的子程序。可以定义插件以按名称添加更多。

$obj->define("chew", \&CookieMonster::chew);  
$obj->parse("column:chew: 3x"); # chew the column 3 times  

所以显而易见的第一个问题是,有人知道我可以使用的模块吗?到目前为止,我唯一能找到的是 [mod://Hash::Transform],但由于我将确定在运行时动态执行哪些处理,所以我总是最终使用“复杂”选项,我d 仍然需要构建解析器/堆栈器。

有人知道我可能想要使用/包装的任何类似模块甚至是轻度相关的模块吗?

如果没有什么通用的可供公众消费(当然我的不是暗盘中唯一的),除了从 DBI 返回数据之外,是否有人对要记住的事情或接口建议或什至其他可能的用途有任何建议,文本::CSV 等?

如果我最终编写了一个新模块,是否有人有命名空间建议?我认为 Data:: 下的某些内容可能是合适的......“可插拔”这个词一直在脑海中浮现,因为我的用例让我想起了 PAM,但我真的没有什么好主意......

  • 数据::处理器::可插拔?
  • 数据::Munging::可配置?
  • 我::咀嚼::数据?
4

3 回答 3

0

首先,如果可能,我会尝试在 SQL 查询中放置尽可能多的格式。日期格式等绝对应该在 SQL 中处理。

在我的脑海中,我知道并且可以用于您的目的的模块是Data::FormValidator。虽然它的主要目的是验证 CGI 参数,但它具有您需要的功能:您可以定义过滤器和约束,并以各种方式将它们链接起来。并不意味着没有其他模块适合您,我只是不知道。

或者你可以做一些你已经暗示过的事情。您可以定义某种命令类并将它们链接到各种数据输入。我会按照这些思路做一些事情:

package MyDataProcessor;

use Moose;
has 'Transformations' => (
    traits => ['Array'],
    is => 'rw',
    isa => 'ArrayRef[MyTransformer]',
    handles => {
        add_transformer => 'push',
    }
);

has 'input' => (is => 'rw', isa => 'Str');

sub apply_transforms {  }


package MyRegexTransformer;

use Moose;

extends 'MyTransformer';

has 'Regex' => (is => 'rw', isa => 'Str');
has 'Replacement' => (is => 'rw', isa => 'Str');

sub transform {  }

# some other transformers
#

# somewhere else
#
#

my $processor = MyDataProcessor->new(input => 'Hello transform me');

my $tr = MyRegexTransformer->new(Regex => 'Hello', Replacement => 'Hi');

$processor->add_transformer($tr);

#...

$processor->apply_transforms;
于 2010-11-17T19:24:25.353 回答
0

我不知道有任何数据转换 CPAN 模块,所以我不得不自己动手工作。它比这复杂得多,但在类似的原理下运行;它基本上是一个穷人实现的 Informatica 风格的 ETL,没有花哨的 GUI……配置是 Perl 哈希(Perl 而不是 XML,因为它允许我实现某些复杂的规则作为子例程引用)。

至于命名空间,我会去Data::Transform::*

于 2010-11-17T19:43:51.347 回答
0

感谢大家的想法。

简短版本: 在尝试调整一些现有模块后,我最终抽象了自己的:Sub::Chain。它需要一些工作,但目前正在做我需要的事情。

长版:( 摘自 POD)

=head1 基本原理

这个模块最初是 Data::Transform::Named,一个围绕 Data::Transform(特别是 Data::Transform::Map)的命名包装器(如 Sub::Chain::Named)。

当模块快完成时,我意识到我使用的 Data::Transform 非常少(它的文档表明我可能不想使用 II 使用的唯一部分)。我还发现输出并不总是我所期望的。根据 Data::Transform 的可能用途,我认为这似乎是合理的,而这个模块只是需要有所不同。

所以我尝试更抽象地思考,并意识到模块的本质与数据转换无关,而只是简单的子程序调用的继承。

I then found and considered Sub::Pipeline but needed to be able to use the same named subroutine with different arguments in a single chain, so it seemed easier to me to stick with the code I had written and just rename it and abstract it a bit further.

I also looked into Rule::Engine which was beginning development at the time I was searching. However, like Data::Transform, it seemed more complex than what I needed. When I saw that Rule::Engine was using [the very excellent] Moose I decided to pass since I was doing work on a number of very old machines with old distros and old perls and constrained resources. Again, it just seemed to be much more than what I was looking for.

=cut

As for the "parse" method in my original idea/example, I haven't found that to be necessary, and am currently using syntax like

$chain->append($sub, \@arguments, \%options)

于 2011-01-07T19:15:54.417 回答