用于执行推迟的初始化代码的模块

时间:2014-11-20 12:37:04

标签: perl

在哪里放置初始化代码(连接到数据库,生成内容,加载数据文件等)?

以下是一些现有选项:

  1. 将其放入相关模块中。当模块为BEGIN{} d
  2. 时,这将执行use中的代码

    (+)良好的封装。

    ( - )一切都与数据库,配置,特定文件位置等有关。难以隔离单元测试,更难以运行代码片段来查找错误,如perl -MFoo -d -we 'Foo->new'

    1. 将其放入单独的脚本(startup.pl等)
    2. ( - )代码远离它使用的地方,容易忘记一些东西。

      ( - )初始化全有或无。

        项目中每个模块中的
      1. startup()(或其他名称)例程。
      2. ( - )仍然很容易忘记运行它。

        1. 使用Perl内置的INIT块。
        2. 这就是问题(当然,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
          

          有这样的模块吗?如果没有,是否需要?还是有一种我忽略的简单方法?

1 个答案:

答案 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()子,或者只是让事物初始化当它发射时它本身。