勝手に添削: Test::mysqldとTeng::Schema::Dumperを使ってTengのSchemaクラスを自動生成する 〜Daiku編〜
http://masteries.papix.net/entry/2014-05-19-teng-schema-dumper.html
Daikuをご利用いただきありがとうございます。上記のエントリーに関して以下の様な点が気になりました。
- Daikufileを太らせるのは良くない
- せっかくのDSLなのにコードがゲロっと書かれてしまうのは残念な感じがする
あくまでコード例なので、対策はしているのかも知れませんが、僕だったらこうするというのを書きます。
概要は以下のとおりです。
- task用のパッケージをつくる
- Daikufileからはそれを利用する
パッケージは以下のようになります。
package MyApp::CLI::DumpSchema;
use strict;
use warnings;
use DBI;
use Path::Tiny;
use Teng::Schema::Dumper;
use Test::mysqld;
sub run {
my $MYSQLD = Test::mysqld->new( my_cnf => { 'skip-networking' => '' })
or die $Test::mysqld::errstr;
my $dbh = DBI->connect($MYSQLD->dsn);
my $file_name = 'sql/mysql.sql'; # テーブル定義のファイル
my $source = path($file_name)->slurp_utf8;
for my $stmt (split /;/, $source) {
next unless $stmt =~ /\S/;
$dbh->do($stmt) or die $dbh->errstr;
}
my $schema_class = 'lib/MyApp/DB/Schema.pm'; # 出力先となるSchemaクラス
open my $fh, '>', $schema_class or die "$schema_class \: $!";
print $fh Teng::Schema::Dumper->dump(
dbh => $dbh,
namespace => 'MyApp::DB',
base_row_class => 'MyApp::DB::Row',
inflate => { },
);
close $fh;
}
Daikufileは以下のように非常に短くなります
% cat Daikufile
task dump_schema => sub {
require MyApp::CLI::DumpSchema;
MyApp::CLI::DumpSchema->run;
};
このようにすることで、
- MyApp::ClI::DumpSchemaを別の場所(バッチなど)からも再利用能
- MyApp::CLI::DumpSchemaのテストが書きやすい
- Daikufileの見通しが良くなる
- 1つのタスクを実行するときに最低限のモジュールしか読み込まれない
などのメリットがあります。Daikufileに限らず、plファイルなども処理をベタッと書いてしまいがちですが、このようにpmファイルを適切に作り、メインの処理はそっちに書くのがベストプラクティスです。
ちなみに、require等を使ってモジュールを遅延ロードさせて最低限のモジュールしか読み込ませないみたいなテクニックは、このようなコマンドラインツールや CGI環境等でしかでしか使うべきではありません。たまに永続環境でそういうことをやってしまっている人がいますが、逆効果なので注意。
また、以前自分のエントリでDaikufileの冒頭に#!perl
と書いていたのはエディタのシンタックスハイライトを効かせたかったからですが、cpanfile同様、
書かなくてもハイライトが効くように設定したので書くのをやめました。cpanfileの冒頭に#!perl
とか書いてあったらカッコ悪いので。
同様に、use strict;
, use warnings;
, use utf8;
もDaikufile内に書く必要はありませんが、気になる人は書いても害はないので書いても良いとは思います。