在哪里放置初始化代码(连接到数据库,生成内容,加载数据文件等)?
以下是一些现有选项:
BEGIN{}
d use
中的代码
醇>
(+)良好的封装。
( - )一切都与数据库,配置,特定文件位置等有关。难以隔离单元测试,更难以运行代码片段来查找错误,如perl -MFoo -d -we 'Foo->new'
startup.pl
等)( - )代码远离它使用的地方,容易忘记一些东西。
( - )初始化全有或无。
startup()
(或其他名称)例程。( - )仍然很容易忘记运行它。
这就是问题(当然,Apache也是如此):
bash$ plackup -e 'use warnings; INIT{ warn "foo"; }; sub { warn "here"; return [200, [], []] };'
Too late to run INIT block at (eval 7) line 1.
HTTP::Server::PSGI: Accepting connections at http://0:5000/
here at (eval 7) line 1.
127.0.0.1 - - [20/Nov/2014:14:18:08 +0200] "GET / HTTP/1.1" 200 - "-" "Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:33.0) Gecko/20100101 Firefox/33.0"
请注意Too late to call INIT
警告,输出中没有“foo”的迹象。
现在我想要一个如下使用的模块:
在项目模块中:
use Init::Queue sub {
get_dbh();
load_file();
build_cache();
}; # postpone till explicitly called
在生产/初始化代码中:
Init::Queue->startup();
# this executes all startup blocks,
# in order of appearance
有这样的模块吗?如果没有,是否需要?还是有一种我忽略的简单方法?
答案 0 :(得分:1)
嗯,答案是'它取决于'。但就个人而言,我倾向于在第一次使用时使用初始化'做法。当你进行面向对象时,这相对容易 - 挂钩构造函数并让它进行设置。
对于非OO perl,我实际上倾向于做类似的事情:
{
my $thing_to_init;
sub init {
$thing_to_init = 1;
}
sub call_some_function {
init() unless defined $thing_to_init;
#do everything else
}
}
因为它位于闭包内,$thing_to_init
无法从模块命名空间访问,但您可以:手动调用init()
子,或者只是让事物初始化当它发射时它本身。