前回の
動的なモジュールロードで実現できること
動的なモジュールロードをすると実現できることを紹介します。
コード量が少なくなる
ロードするモジュールの名前を動的に生成できるため、use
でモジュールロードする場合と比べて書く必要のあるコード量が少なくなります。
たとえば次のように、 コード量が少なくなることの中でも特筆すべき点として、 項目の多いマスタデータや、 具体的な利用例として、 データベースにある大量のアイテムデータと、 モジュールロードするタイミングを、 依存関係を動的に解決できるので、 これらの動的なモジュールロードで実現できることが、 コード量を少なくするために活用されている事例を見てみましょう。 Module::Findは、 CatalystというPerl製のWAF 実際に このコードは 前述したとおり、 Catalystのコンテナ機能と似た事例にモデルモジュール専用のモジュールローダがあり、 簡単にプラグインの実装と追加ができるようになるため、 例としてTengのプラグイン機構を簡略化したコードでプラガブルなアーキテクチャの実装方法を紹介します。 次に、 プラグインモジュールを利用するには、 モジュール本体で直接プラグインを利用すると、 プラグインを利用したならば、 動的なモジュールロードを活用すると、 例として、 MojoliciousはPerl製のWAFで、 このように動的なモジュールロードを活用すると、 <続きの 2022年8月24日発売use Module::Load qw( load );
for my $module_
動的なディスパッチ
use Class::Load qw( load_class );
use String::CamelCase qw( camelize );
sub use {
my ($self, $user) = @_;
my $module =
'MyApp::ItemEffect::' . camelize($self->name);
load_class($module);
my $effect = $module->new(@_);
$effect->execute($user);
}
起動/
Moo
、Type::Tiny、
など、依存関係の動的な解決
動的なモジュールロードの活用
コード量を少なくする
Module::Findの事例──特定の名前空間に属するモジュールをすべて読み込む
usesub
で引数の名前空間直下に属するモジュールをロードし、useall
で引数の名前空間に属するモジュールを再帰的にロードします。use Module::Find qw( usesub useall );
# Foo::Bar, Foo::Baz, ...
my @sub_modules = usesub('Foo');
# Foo::Bar, Foo::Bar::Hoge, Foo::Baz, etc...
my @all_modules = useall('Foo');
Catalystのコンテナ──use忘れを防ぎ、
Catalyst
ではアプリケーションの起動時にすべてのモデルモジュールをロードし、use
忘れがなくなる、Catalyst
で作られたアプリケーションでどのようにモデルモジュールが使われるのかを見てみましょう。package MyApp::Controller::Root;
use Moose;
use namespace::autoclean;
BEGIN { extends 'Catalyst::Controller' }
__PACKAGE__->config(namespace => '');
sub foo :Local :Args(1) {
my ($self, $c, $name) = @_;
my $country =
$c->model('DB::Countries') ―(1)
->search({ name => $name }); ―(2)
$c->stash(
template => 'foo.tt',
country => $country,
);
}
Catalyst
のコントローラのコードになります。MyApp::Model::DB::Countries
のインスタンスを取得しています。search
メソッドを呼び出しています。Catalyst
とは別のWAFのプラグインなどで見受けられます。これは起動時にすべてのモデルモジュールのロードをするのではなく、プラガブルなアーキテクチャの実装──Tengの事例
Teng
は軽量なO/Teng::Plugin::Count
を使うと、プラグイン機構の実装
Teng
のようなプラグイン機構は、@EXPORT
で指定されたメソッド)package Module;
use Module::Load qw( load );
sub add_plugin {
my ($class, $plugin) = @_;
my $package = "Module::Plugin::${plugin}";
load($package);
{
no strict 'refs';
for my $method ( @{"${package}::EXPORT"} ){
*{$class . '::' . $method} =
$package->can($method);
}
}
}
プラグインモジュールの実装
Module::Plugin::${プラグイン名}
といった風に、@EXPORT
に追加します。package Module::Plugin::Hoge;
our @EXPORT = qw( do_something );
sub do_something {
my $class = shift;
warn 'Do something';
}
プラグインモジュールの利用
add_
メソッドにプラグイン名を渡します。package My::Module;
use parent 'Module';
__PACKAGE__->add_plugin('Hoge');
use My::Module;
My::Module->do_something();
フレームワークの実装──Mojoliciousのルーティングの事例
package SomeWebApp;
use Mojo::Base 'Mojolicious';
# アプリケーション起動時に呼ばれるメソッド
sub startup {
my $self = shift;
my $r = $self->routes;
$r->get('/')->to('Root#root'); ―(1)
my $user =
$r->any('/user')->to(controller => 'user'); ―(2)
$user->post('/add/:name')->to(action => 'add'); ―(3)
}
SomeWebApp::Controller::Root
クラスのroot
メソッドを呼び出す指定をしています。/user
にあらゆるメソッドでリクエストが来た際SomeWebApp::Controller::User
クラスのメソッドで処理することを指定しています。$user_
にはその状態を保持したルーティングオブジェクトが格納されているので、SomeWebApp::Controller::User
クラスのどのメソッドで処理を行うかの指定をするだけで簡潔にリクエストに応じた呼び出す処理を割り当てることができます。/user/
SomeWebApp::Controller::User
クラスのメソッドを指定しています。本誌最新号をチェック!
WEB+DB PRESS Vol.130
B5判/
定価1,628円
ISBN978-4-297-13000-8
イミュータブルデータモデルで始める
実践データモデリング
業務の複雑さをシンプルに表現!
いまはじめるFlutter
iOS/
作って学ぶWeb3
ブロックチェーン、