不純物と委任:「プラグイン」を実装することの利点と欠点

この記事では、プロジェクトに不純物または委任を使用して、クラスに新しい機能を追加する選択についての私の意見を提供します。



初期条件は次のとおりです。状態があり、アグリゲータークラスのすべてのメンバーにアクセスできる不純物を検討します。 不純物クラスのすべてのパブリックメンバーは、アグリゲーターの一部になります。 パフォーマンスの問題を舞台裏に残します。 架空のORMのモデルに新しい機能を追加する例を使用して、問題を調べます。



この記事では主にPHPについて説明していますが、多少の制限はありますが、何らかの方法で不純物を実装できる他の多くの動的言語にも適しています。







この記事は、何らかの形で、PHPでの不純物の実装に関するこの記事の論理的な続きです。 興味があるなら、それを読んでください。 そうでない場合、ここで提示されている資料を理解することは問題になりません。



コードサンプル



最初に、同じことを行うコードを使用して、2つのアプローチの違いを見てみましょう。



不純物



class Aggregator { } class Mixin { public function doSomething() {} } Mixins::mix("Aggregator", "Mixin"); $a = new Aggregator (); $a->doSomething();
      
      







代表団



 Class Aggregator {} class Mixin { public function doSomething() {} } class AggregatorMixed extends Aggregator { private $mixin; function __construct() { $mixin = new Mixin(); } public function doSomething() { $mixin->doSomething(); } } $a = new AggregatorMixed (); $a->doSomething();
      
      







Aggregatorクラスに直接委任されたメソッドを含めることができる場合、場合によっては継承を回避できることに注意してください。 しかし、これは常に可能というわけではありません。ORMプラグインの実装のコンテキストで不純物と委任を考慮するため、この形式の例を挙げました。



技術的な違い



技術的な観点からの2つのフラグメントの違いは何ですか? ご覧のように、それらは同じ機能を提供します。



1.不純物メソッドは名前によって動的に呼び出され、委任の場合、コンパイラはコードを実行する前に確認できます。



動的呼び出しは、プログラムに柔軟性をもたらします。これには、コンパイル時に型チェックが行われないという代償が伴います。 不純物を使用する場合は、追加の単体テストが役立ちます。



2.機能を追加するための不純な場合、いつでも同じクラスに単純に混合します。委任の場合、機能を追加するには、必要な機能を委任する新しいメソッドでサブクラスを作成する必要があります。



サブクラスの作成と保守にはある程度の作業が必要であり、独自のコードの量はわずかに増加しますが、最終的には、提供するすべての機能を確認できる全体的なクラスが表示されます。 不純物は追加のコーディングなしで非常に迅速にクラスに接続しますが、最終的には集合クラスとすべての不純物が別々に表示されます。



もう1つの小さな結果は、委任の場合、委任された機能の量の決定は、不純物の場合は不純物自体のアグリゲータークラスによって行われることです。



3.不純物は、アグリゲータークラスのすべてのメンバーに自動的にアクセスし、その仕組みを知っていれば、任意に操作できます。 委任の場合、このアクセスはそうではありません。



不純物からアグリゲータークラスのメンバーにアクセスすると、オブジェクトの内部状態を変更する機会が与えられます。 これは便利ですが、アグリゲータークラスの内部構造に関する知識の必要性を混合物に追加します。 一方、不純物を使用してアグリゲータークラスのインターフェイスを開発する場合、委任の場合に必要なように、動作を拡張するときにアグリゲータークラスの状態を操作する必要がある場合、クラスメンバーの可視性のレベルを計画する必要はありません。 ただし、この特権は不純物から簡単に削除されます。



次に、不純物と委任によって同じ機会がどのように実装されるかを見てみましょう。



例「ORMの動作」。



架空のフレームワーク上に小さなサイトを作成しました。 このサイトには記事のカタログがあります。 私たちのフレームワークにはORMが含まれており、ORMには「記事」のモデルがあります。 ORMには、ツリー、バージョン管理、ソフトリムーバブルなどの一般的な動作をサポートするクラスも含まれています。



フレームワークの次のバージョンでは、記事のディレクトリをツリーのようにする必要があるとします。 何してるの? 記事モデルクラスにツリーモデルを追加します。 この場合、不純物または委任を選択できます。 結果は、最初に検討した例に似ています。 1つの点に注意してください。 不純物を使用する場合、メインクラスの表示可能なインターフェイスはまったく変更されず、委任の場合、拡張するだけですが、互換性は維持されます。



フレームワークの次のバージョンでは、モデルにバージョン管理とソフト削除を追加する必要があります。 適切な不純物をモデルに混入するか、委任を使用してモデルクラスを拡張することにより、簡単に行うことができます。



この例では、不純物と委任の両方を使用できることに注意してください。



次に、同様の例を見てみましょう。モデルに機能を追加するだけですが、サードパーティの開発者によって書かれたフレームワークへのプラグインです。 プラグインをシステムに統合するために、ほとんどの部分を書き換える必要がないように、便利なAPIを提供するだけです。



プラグインは、モデルに機能を追加したいと考えています。 プラグインが不純物に基づいて構築されている場合は、モデルクラスに登録するだけです。 また、委任の場合、たとえば、モデルクラス名をレジストリに保存できます。 次に、ツリービューを記事に追加するためのプラグインは、フレームワークモデルの基本クラスからそれ自体を継承し、機能を追加し、元のモデルクラスの名前をモデルレジストリ内の独自のものに置き換えます。 または、プラグイン開発者は、システムのユーザーに、必要な方法でモデルクラスをプラグインに追加する方法に関する指示を提供します(ご存じのとおり、これは一般ユーザーにはあまり好ましくありません)。 スキームは少し複雑ですが、今のところ許容範囲です。 また、モデルクラスインターフェイスは互換性を維持しているため、フレームワークは両方のケースで機能し続けます(注意深い読者は、おそらくプロジェクトにモデルクラス機能を拡張する他のソリューションがあることに気づきました。しかし、それらの検討は別の記事のトピックになります)。



しかし、「バージョン対応」および「ソフトリムーバブル」プラグインの作成者は、これらの機能を記事モデルに「ではなく」ではなく「一緒に」追加することを望んでいます。 これはどのように実装できますか? 不純物の場合、すべてがまだ簡単です。 モデルクラスに新しい機能を追加します。 そして、委任とは? どうやら、ここでスキームはより複雑になり始めます。 相互に継承するプラグインクラスと、元のモデルクラスから継承する最初のプラグインのクラスが必要です。 特定のコストがかかると、そのような機能も追加できます。 あなたにとってどちらが望ましいかを決める必要があります。



この場合、選択は専門的なスキルと好みに基づいて行う必要があります。 本格的な非教育プロジェクトでは、あなたにとって最も親しみがあり、プロとしての意味でよく知られている手法(または、将来プロジェクトに取り組むほとんどのプログラマーにとって最も馴染みのある手法)のみを使用する必要があります。 この推奨事項を無視し、現在より便利だと思われるものを選択する場合は、なじみのないアプローチの使用がプロジェクトコードの健全性にとって重要にならないようにしてください。 不純物と委任の使用が同等に優れていると思われる場合は、両方を選択する際の考慮事項を上記に示します。 一番好きなものを決めてください。



上記の委任を使用したソリューションが複雑に見えることは明らかであるため、コードの制御を自分の手で取得する場合、明らかに、不純物に行くか、問題を解決する他の方法を探す必要があります。



テクノ愛好家を失望させてしまったことを残念に思います。テクノ愛好家は、私の母国の砦を擁護するアプローチの1つの強力な支持者の間で私に会うことを最も期待していました。 そうだとすみません。



人生の選択は常に、2つのことによって導かれることを忘れないでください。この問題で収集できる情報の最大量と自分の頭です。 最初のものを提供しようとしました。 2番目はあなたのものです。



PSこの記事が面白そうに思えたら、次のコメントのトピックを提案してください。



All Articles