2

データベース内のテーブルにマッピングされるさまざまなサブクラスを持つ Moose BaseDBModel があります。サブクラスのすべてのメソッドは、さまざまな DB 操作を参照する「get_xxx」または「update_xxx」のようなものです。

今、私はこれらすべてのメソッドにキャッシュシステムを実装したいので、私のアイデアは「get_xxx」のような名前のすべてのメソッドの「前」にあり、メソッドの名前を memcache プールのキーとして値を検索します。値が見つかった場合は、メソッドではなく値を直接返します。

理想的には、私のコードは次のようになります

BaseDBModel

package Speed::Module::BaseDBModel;
use Moose;
sub BUILD {
  my $self = shift;

  for my $method ($self->meta->get_method_list()){
    if($method =~ /^get_/){
      $self->meta->add_before_method_modifier($method,sub {
        warn $method;
        find_value_by_method_name($method);
        [return_value_if_found_value]
      });
    }
  }
}

サブクラスの例 1

package Speed::Module::Character;
use Moose;

extends 'Speed::Module::BaseDBModel';
method get_character_by_id {
    xxxx
}

今私の問題は、私のプログラムが実行されているときに、メソッドを繰り返し変更していることです。次に例を示します。

  1. アパッチを再起動する

  2. get_character_by_id を呼び出すページにアクセスすると、1 つの警告メッセージが表示されます。

コード:

my $db_character = Speed::Module::Character->new(glr => $self->glr);
$character_state = $db_character->get_character_by_id($cid);

警告:

get_character_by_id at /Users/dyk/Sites/speed/lib/Speed/Module/BaseDBModel.pm line 60.

しかし、ページを更新すると、2 つの警告メッセージが表示されました

警告:

get_character_by_id at /Users/dyk/Sites/speed/lib/Speed/Module/BaseDBModel.pm line 60.
get_character_by_id at /Users/dyk/Sites/speed/lib/Speed/Module/BaseDBModel.pm line 60.

Apache で mod_perl 2.0 を使用しています。ページを更新するたびに、不要な get_character_by_id メソッドが変更されます。

4

2 に答える 2

0

この問題は、オブジェクトBUILDを作成するたびに (つまり、呼び出しごとに)実行されますが、修飾子をclass、つまりすべての objectに追加します。->new()add_before_method_modifier

シンプルなソリューション

毎回、使用されたパッケージからインポート関数をuse呼び出すことに注意してください。それが修飾子を追加したい場所です。

親:

package Parent;

use Moose;

sub import {
    my ($class) = @_;

    foreach my $method ($class->meta->get_method_list) {
        if ($method =~ /^get_/) {
            $class->meta->add_before_method_modifier($method, sub {
                warn $method
            });
        }
    }
}

1;

子 1:

package Child1;

use Moose;
extends 'Parent';

sub get_a { 'a' }

1;

子 2:

package Child2;

use Moose;
extends 'Parent';

sub get_b { 'b' }

1;

したがって、期待どおりに機能するようになりました。

$ perl -e 'use Child1; use Child2; Child1->new->get_a; Child2->new->get_b; Child1->new->get_a;'
get_a at Parent.pm line 11.
get_b at Parent.pm line 11.
get_a at Parent.pm line 11.

クリーナー ソリューション

100% 確実importに呼び出されるとは限らないため (使用されると確信できないuseため)、よりクリーンで簡単な解決策はuse My::Getter::Cacher、すべての派生クラスに次のようなものを追加することです。

package My::Getter::Cacher;

sub import {
    my $class = [caller]->[0];

    # ...
}

この場合、最初の行は継承に関するものであり、2 番目の行は before 修飾子の追加に関するものであるため、すべての派生クラスには両方extends 'Parent'を含める必要があります。use My::Getter::Cacher少し冗長だと思うかもしれませんが、私が言ったように、よりクリーンで簡単だと思います。

PS

たぶん、Memoizeモジュールを一瞥する必要があります。

于 2014-05-21T08:31:19.243 に答える
0

新しいインスタンスを構築するたびに BUILD が add_before を実行していませんか? それがあなたの望むものかどうかはわかりません。


まあ、簡単で不格好な方法は、パッケージレベルのフラグを設定して、一度だけ行うことです。

それ以外の場合は、Moose 独自の属性構築にフックする必要があると思います。これを見てください: http://www.perlmonks.org/?node_id=948231

于 2012-08-15T10:29:35.653 に答える