ホームページ >バックエンド開発 >PHPチュートリアル >仮想プロキシのイントロ、パート2

仮想プロキシのイントロ、パート2

William Shakespeare
William Shakespeareオリジナル
2025-02-27 10:41:13707ブラウズ

An Intro to Virtual Proxies, Part 2

コアポイント

  • 多型に基づく仮想プロキシにより、クライアントコードを変更せずにコストのかかるオブジェクトグラフの構築/負荷を遅らせることができます。
  • エージェントは、単一のオブジェクトまたはオブジェクトのコレクションを使用して作業し、データの管理に柔軟性と効率を提供するように設計できます。
  • 仮想エージェントは、ストレージ内のドメインオブジェクトの怠zyなロードコレクションに特に効果的です(たとえば、データベースのオンデマンドから関連するコメントを抽出できるブログ投稿のバッチ)。
  • 実際のコメントコレクションの動作をシミュレートするプロキシは、データマッパーを通じて実現され、それにより持続性の無関係性が向上します。

仮想プロキシは、費用のかかるタスクの実行を遅らせるための効果的なツール(たとえば、ストレージ層の大量のデータの読み込みを遅らせる)、およびオブジェクト指向のアプリケーションでの一般的な剛性と脆弱性の問題を軽減するための効果的なツールです。

仮想エージェントの名前は派手に聞こえますが、おそらく、単なる退屈な独断的原理以上の「インターフェイス指向プログラミング」の概念の最も顕著な例の1つです。仮想プロキシは、単純な方法で実装された一時的な多型ではなく、動的な多型)に基づいており、クライアントコードを変更せずに費用のかかるオブジェクトグラフの構築/読み込みを遅らせることができるシンプルで信頼できる概念です。エージェントの大きな利点は、単一のオブジェクトまたはオブジェクトのコレクションを使用するように概念的に設計できることです(またはその両方が、懸念の分離を危険にさらす可能性があり、時間の経過とともに管理が困難です)。実用的な観点から、仮想プロキシによって提供される機能をどのように活用するかを実証するために、このシリーズの最初の部分で、基本プロキシを使用して単純なドメインモデルを満たすためにデータベースから集計を抽出する方法を示すいくつかの開発プロセスを紹介します。経験は有益であり、幸いなことに楽しいことですが、それの反対側は仮想エージェントの内と外を示すので少し欺cept的ですが、より現実的なシナリオでそれらを実装する方法を示していません。このプロキシは、レイジーロードストレージ内のドメインオブジェクトの収集という点で比類のないものです。この概念を理解するには、ブログ投稿のバッチを検討してください。関連するコメントの各セットをオンデマンドでデータベースから抽出できます。

通常、練習は最高の教師です。このセクションでは、プロキシをドメイン固有のオブジェクトのコレクションに接続する方法を示します。この典型的なシナリオを非常に基本的なレベルで再現して、その運転ロジックを簡単に理解できるようにします。

レルムオブジェクトのコレクションを作成前述のように、前述のように、仮想エージェントは通常、永続レイヤーから基礎となるレルムオブジェクトコレクションに結合した集計根を取得するときに作成されます。コレクションの性質により、多くの場合、コレクションの事前設定は高価であるため、データベースの往復のオーバーヘッドを削減するためにオンデマンドでロードするのに適した候補になります。さらに、ブログ投稿とそれに対応するコメントとの間の「1対多」の関係がこのユースケースに非常に忠実に反映されていることを考えると、特定のエージェントを扱う前に、いくつかの単純なドメインクラスを通じて関係を最初にモデル化することは有益です。物事を理解しやすくするために、テスト段階で追加する2人の参加者は、孤立したインターフェイスと基本的な実装者になります。これらの2つは、一般的なブログ投稿オブジェクトの契約と実装を定義するために組み合わせています:

<code class="language-php"><?php namespace Model;
use ModelCollectionCommentCollectionInterface;

interface PostInterface
{
    public function setId($id);
    public function getId();

    public function setTitle($title);
    public function getTitle();

    public function setContent($content);
    public function getContent();

    public function setComments(CommentCollectionInterface $comments);
    public function getComments();
}</code>
<code class="language-php"><?php namespace Model;
    use ModelCollectionCommentCollectionInterface;

class Post implements PostInterface
{
    protected $id;
    protected $title;
    protected $content;
    protected $comments;

    public function __construct($title, $content, CommentCollectionInterface $comments = null)  {
        $this->setTitle($title);
        $this->setContent($content);
        $this->comments = $comments;
    }

    // ... (Post class methods remain largely unchanged) ...
}</code>
上記のポストクラスのロジックを理解することは簡単なプロセスであり、実際の説明は必要ありません。それにもかかわらず、ここに注目に値する関連する詳細があります。クラスは、コンストラクターで定義されていないコメントのコレクションに対する依存関係を明示的に宣言します。次に、投稿コメントを生成するクラスを作成しましょう:

<code class="language-php"><?php namespace Model;

interface CommentInterface
{
     public function setId($id);
     public function getId();

     public function setContent($content);
     public function getContent();

     public function setPoster($poster);
     public function getPoster();
}</code>
<code class="language-php"><?php namespace Model;

class Comment implements CommentInterface
{
    protected $id;
    protected $content;
    protected $poster;

    public function __construct($content, $poster) {
        $this->setContent($content);
        $this->setPoster($poster);
    }

    // ... (Comment class methods remain largely unchanged) ...
}</code>
これまでのところ、すべてが順調に進んでいます。基本ドメインモデルの薄いブロックとは別に、上記のドメインクラスについては何も言うことはありません。各ブログ投稿オブジェクトは、関連するコメントと「1対Many」関連を開きます。必要に応じて純粋主義者と呼ぶことができますが、モデルの現在の実装がコメントのコレクションで強化されていない場合、不完全で不器用に見えるように思えます。この余分なコンポーネントを追加することで、モデルをより豊かにしましょう:

<code class="language-php"><?php namespace ModelCollection;

interface CommentCollectionInterface extends Countable, IteratorAggregate
{
    public function getComments();
}</code>
<code class="language-php"><?php namespace ModelCollection;
use ModelCommentInterface;

class CommentCollection implements CommentCollectionInterface
{
    protected $comments = array();

    public function __construct(array $comments = array()) {
        // ... (CommentCollection class methods remain largely unchanged) ...
    }
}</code>
注意深く見て、コメントコレクションのクラスを閲覧すると、まず、ゴージャスな変装の後ろに隠された反復可能で数えられる配列ラッパーにすぎないことに気付くでしょう。実際、アレイコレクションにはさまざまな形やスタイルがありますが、ほとんどの場合、それらはイテレーターとArrayAccess SPLクラスの単純な使用法です。この場合、私はそのような退屈な仕事から自分自身(そしてあなた)を保存し、クラスをIteratorAggregateの実装者にしたいと思っています。コメントコレクションを使用すると、さらに一歩進んで、ドメインモデルが行うべきことを実行させることができます。ブログ投稿オブジェクトで操作するか、データベースから熱心に取得したコメントのバッチと相互接続することもできます。しかし、そうすることは、仮想プロキシによって提供される機能を最大限に活用することなく、自分自身をだますだけです。典型的な実装では、プロキシが実際のドメインオブジェクトと同じAPIを公開することを考慮すると、以前のコメントコレクションクラスと対話するプロキシは、問題のある条件付きステートメントの束を導入することなくクライアントコードとの契約を順守するためにコメントコレクションインターフェイスを実装する必要があります。

仮想エージェントを介したドメインオブジェクトのコレクションとの相互作用率直に言って、前述のように、ラッピングアレイのコレクションは、他の依存関係に頼らずに独立して存在する可能性があります。 (懐疑的な場合は、教義のコレクションが舞台裏でどのように機能するかを自由に確認してください。)それでも、実際のレビューコレクションの動作をシミュレートするプロキシを実装しようとしていることを忘れないでください。尋ねられるべき質問は、データベースからコメントを抽出し、以前のコレクションにどのように抽出するのですか?これを達成するにはいくつかの方法がありますが、最も魅力的なものは、持続性の無関係を改善するため、データマッパーを使用することだと思います。以下のマッパーは、ストレージからコメントのコレクションを取得するのを嬉しく思います。確認してください:

<code class="language-php"><?php namespace Model;
use ModelCollectionCommentCollectionInterface;

interface PostInterface
{
    public function setId($id);
    public function getId();

    public function setTitle($title);
    public function getTitle();

    public function setContent($content);
    public function getContent();

    public function setComments(CommentCollectionInterface $comments);
    public function getComments();
}</code>
コメントマッパークラスによって公開されたファインダーは通常、標準のデータマッパー実装で予想される可能性のあるAPIに固執していますが、fetchall()メソッドは最も説得力のある方法です。最初にストレージからすべてのブログ投稿のコメントを抽出し、それらをコレクションに入れ、最後にコレクションをクライアントコードに返します。あなたが私のようであれば、コレクションがメソッド内に直接インスタンス化されるため、あなたはあなたの心に目覚ましの呼びかけがあるかもしれません。実際、コレクションは実際には「注入可能な」カテゴリではなく、「作成された」カテゴリに該当する一般構造であるため、少なくともこの場合、工場の外に忍び寄る新しいオペレーターについてパニックに陥る必要はありません。とにかく、コレクションをマッパーのコンストラクターに注入することで少し罪悪感を抱いていると感じたら、気軽にそれをしてください。コメントMapperを使用すると、本物のエピファニーを体験し、前のセットで仲介するプロキシクラスを構築する時が来ました。
<code class="language-php"><?php namespace Model;
    use ModelCollectionCommentCollectionInterface;

class Post implements PostInterface
{
    protected $id;
    protected $title;
    protected $content;
    protected $comments;

    public function __construct($title, $content, CommentCollectionInterface $comments = null)  {
        $this->setTitle($title);
        $this->setContent($content);
        $this->comments = $comments;
    }

    // ... (Post class methods remain largely unchanged) ...
}</code>

ご想像のとおり、CommentCollectionProxyは、実際のコメントのコレクションと同じインターフェイスを実装します。ただし、そのgetComments()メソッドは、実際の作業を舞台裏で行い、コンストラクターに渡されたマッパーを介してデータベースからのコメントの負荷を遅らせます。このシンプルで効果的な方法では、過剰に仕入れなくても、コメントに対してあらゆる種類の巧妙なアクションを実行できます。どのような方法を見たいですか?データベースからの特定のブログ投稿にすべてのコメントを縛る必要があるとします。次のコードスニペットはこれを行うことができます:

<code class="language-php"><?php namespace Model;

interface CommentInterface
{
     public function setId($id);
     public function getId();

     public function setContent($content);
     public function getContent();

     public function setPoster($poster);
     public function getPoster();
}</code>

このアプローチの欠点は、コメントが最初にストレージから抽出され、次にポストオブジェクトの内側に注入されることです。逆の方法でそれを行う方法ですが、今回はクライアントコードをプロキシで「スプーフィング」することですか?

<code class="language-php"><?php namespace Model;

class Comment implements CommentInterface
{
    protected $id;
    protected $content;
    protected $poster;

    public function __construct($content, $poster) {
        $this->setContent($content);
        $this->setPoster($poster);
    }

    // ... (Comment class methods remain largely unchanged) ...
}</code>
コメントは、プロキシがforeachループに配置された後、データベースからの読み込みを透過的に遅らせるだけでなく、クライアントコードに公開されたAPIは、プロセス全体で元の構造を変えないようにします。私たちはあえてもっと良いものを求めようとさえしますか?あなたが非常に貪欲でない限り、私がそう考えるのは難しいです。どちらの場合でも、仮想エージェントの舞台裏の現実と、ドメインオブジェクトの運用効率と基礎となる永続性層を改善する能力を最大限に活用する方法を理解する必要があります。

<code class="language-php"><?php namespace ModelCollection;

interface CommentCollectionInterface extends Countable, IteratorAggregate
{
    public function getComments();
}</code>
結論

それは単純ですが、特にあなたがそれを生産環境で使用するのに十分に大胆である場合、それは単純ですが、前の例はいくつかの興味深い概念を簡単に示しています。第一に、仮想エージェントはセットアップと使用が容易であるだけでなく、実行時に異なる実装を混合して、コストのかかるタスクの実行を遅らせるのと比類のないものです(たとえば、ストレージ層の大量のデータの読み込みを遅らせたり、ヘビー級グラフを作成したりします)。第二に、それらは、多くのオブジェクト指向のアプリケーションが苦しむ一般的な剛性と脆弱性の問題を軽減する効果的なワクチンになる方法の典型的な例です。さらに、PHPのオブジェクトモデルはシンプルで閉鎖をサポートするため、これらの機能を巧みに混合し、根底にあるロジックが閉鎖の利点によって駆動されるプロキシを構築することができます。あなたがこの挑戦にあなた自身に対処したいなら、私はあなたが事前に最高のことを願っています。

(imredesiuk / shutterstockの写真)

以上が仮想プロキシのイントロ、パート2の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。