171

私の開発作業で繰り返されるテーマは、社内プラグイン アーキテクチャの使用または作成です。構成ファイル (XML、.conf など)、継承フレームワーク、データベース情報、ライブラリなど、さまざまな方法でアプローチするのを見てきました。私の経験では:

  • データベースは、構成情報を保存するのに最適な場所ではありません。特に、データが混在している場合はそうです。
  • 継承階層でこれを試みるには、コーディングするプラグインに関する知識が必要です。つまり、プラグイン アーキテクチャはそれほど動的ではありません。
  • 構成ファイルは単純な情報を提供するのには適していますが、より複雑な動作を処理することはできません
  • ライブラリはうまく機能しているように見えますが、一方向の依存関係は慎重に作成する必要があります。

私は、これまで取り組んできたさまざまなアーキテクチャから学びたいと考えているため、コミュニティからの提案も求めています。SOLID プラグイン アーキテクチャをどのように実装しましたか? あなたの最悪の失敗 (またはあなたが見た最悪の失敗) は何ですか? 新しいプラグイン アーキテクチャを実装する場合、どうしますか? あなたが関わった SDK またはオープン ソース プロジェクトには、優れたアーキテクチャの最良の例がありますか?

私が自分で見つけたいくつかの例:

これらの例は、さまざまな言語の強みを発揮しているようです。優れたプラグイン アーキテクチャは必ず言語に結び付けられていますか? ツールを使用してプラグイン アーキテクチャを作成するのが最善ですか、それとも独自の次のモデルで行うのが最善ですか?

4

9 に答える 9

96

これは、潜在的に有用なコメント/例の束ほどの答えではありません。

  • アプリケーションを拡張可能にする効果的な方法の1つは、その内部をスクリプト言語として公開し、その言語ですべてのトップレベルのものを作成することです。これにより、非常に変更可能で、実質的に将来性があります(プリミティブが適切に選択および実装されている場合)。この種のサクセスストーリーはEmacsです。機能を拡張したい場合は、APIを学習して別のプラグインを作成/コンパイルする必要がないため、これはeclipseスタイルのプラグインシステムよりも好まれます。現在のバッファ自体に3行のスニペットを記述し、評価して使用することができます。非常にスムーズな学習曲線と非常に満足のいく結果。

  • 私が少し拡張したアプリケーションの1つは、Tracです。これにはコンポーネントアーキテクチャがあり、この状況では、タスクが拡張ポイントをアドバタイズするモジュールに委任されます。次に、これらのポイントに適合してフローを変更する他のコンポーネントを実装できます。上記のKalkieの提案に少し似ています。

  • もう1つ良いのはpy.testです。これは「最高のAPIはAPIではない」という哲学に従い、すべてのレベルで呼び出されるフックに完全に依存しています。規則に従って名前が付けられたファイル/関数でこれらのフックをオーバーライドし、動作を変更できます。サイトでプラグインのリストを確認して、プラグインをどれだけ迅速に/簡単に実装できるかを確認できます。

いくつかの一般的なポイント。

  • 拡張不可能/ユーザー変更不可能なコアを可能な限り小さく保つようにしてください。拡張性が向上するように、できる限りすべてを上位レイヤーに委任します。悪い選択の場合よりもコアで修正するものが少なくなります。
  • 上記の点に関連して、最初にプロジェクトの方向性についてあまり多くの決定を下すべきではないということです。必要最小限のサブセットを実装してから、プラグインの作成を開始します。
  • スクリプト言語を埋め込む場合は、アプリケーション専用のおもちゃの言語ではなく、一般的なプログラムを記述できる完全な言語であることを確認してください
  • ボイラープレートをできるだけ減らします。サブクラス化、複雑なAPI、プラグイン登録などを気にしないでください。簡単に拡張できるようにするだけでなく、シンプルに保つようにしてください。これにより、プラグインAPIをより多く使用できるようになり、エンドユーザーがプラグインを作成するようになります。プラグイン開発者だけではありません。py.testはこれをうまく行います。私の知る限り、Eclipseはそうではありません
于 2010-05-07T12:29:43.003 に答える
27

私の経験では、実際には 2 種類のプラグイン アーキテクチャがあることがわかりました。

  1. Eclipse model自由を可能にすることを意図し、制限のないものに従います。
  2. narrow APIもう 1 つのプラグインは、通常、プラグインが特定の機能を満たすため、a に従う必要があります。

これを別の言い方をすると、一方はプラグインがアプリケーションにアクセスできるようにし、もう一方はアプリケーションがプラグインにアクセスできるようにします

区別は微妙で、区別がない場合もあります...アプリケーションには両方が必要です。

私は Eclipse の経験が豊富でなく、アプリケーションをプラグイン モデルに開放しています (Kalkie の投稿の記事は素晴らしいです)。私は日食が物事を行う方法について少し読んだことがありますが、それ以上のものはありません。

Yegge のプロパティ ブログでは、プロパティ パターンの使用によってプラグインと拡張性がどのように可能になるかについて少し説明しています。

私が行った作業のほとんどは、プラグイン アーキテクチャを使用して、アプリが時間/表示/地図データなどのプラグインにアクセスできるようにしました。

何年も前は、ファクトリ、プラグイン マネージャー、および構成ファイルを作成してすべてを管理し、実行時に使用するプラグインを決定できるようにしていました。

  • 今、私は通常DI framework、その作業のほとんどを行うだけです。

サードパーティのライブラリを使用するためにアダプターを作成する必要がありますが、通常はそれほど悪くはありません。

于 2010-05-07T16:28:26.977 に答える
14

私が見た中で最も優れたプラグイン アーキテクチャの 1 つは、Eclipse で実装されています。プラグイン モデルのアプリケーションを使用する代わりに、すべてがプラグインです。ベース アプリケーション自体がプラグイン フレームワークです。

http://www.eclipse.org/articles/Article-Plug-in-architecture/plugin_architecture.html

于 2010-05-04T20:38:06.493 に答える
12

私が過去に使用したかなり単純なテクニックについて説明します。このアプローチでは、C# リフレクションを使用して、プラグインの読み込みプロセスを支援します。この手法は、C++ に適用できるように変更できますが、リフレクションを使用できるという利便性が失われます。

インターフェイスは、IPluginプラグインを実装するクラスを識別するために使用されます。メソッドがインターフェイスに追加され、アプリケーションがプラグインと通信できるようになります。たとえばInit、アプリケーションがプラグインに初期化を指示するために使用するメソッドです。

プラグインを見つけるために、アプリケーションは .Net アセンブリのプラグイン フォルダーをスキャンします。各アセンブリがロードされます。リフレクションは、実装するクラスをスキャンするために使用されIPluginます。各プラグイン クラスのインスタンスが作成されます。

(または、Xml ファイルに、読み込むアセンブリとクラスをリストすることもできます。これはパフォーマンスを向上させる可能性がありますが、パフォーマンスの問題は見つかりませんでした)。

このInitメソッドは、プラグイン オブジェクトごとに呼び出されます。アプリケーション インターフェイスを実装するオブジェクトへの参照が渡されますIApplication(または、ITextEditorApplication など、アプリ固有の名前が付けられたもの)。

IApplicationプラグインがアプリケーションと通信できるようにするメソッドが含まれています。たとえば、テキスト エディターを作成している場合、このインターフェイスには、OpenDocumentsプラグインが現在開いているドキュメントのコレクションを列挙できるようにするプロパティがあります。

このプラグイン システムは、関数やアプリケーション インターフェイスを Lua スクリプトにLuaPlugin転送する派生プラグイン クラスを作成することで、Lua などのスクリプト言語に拡張できます。IPlugin

この手法を使用すると、開発中IPluginIApplicationやその他のアプリケーション固有のインターフェイスを繰り返し実装できます。アプリケーションが完成し、適切にリファクタリングされたら、公開されたインターフェースを文書化でき、ユーザーが独自のプラグインを作成できる優れたシステムが完成するはずです。

于 2010-05-13T12:38:19.327 に答える
7

私はかつて、各顧客がシステムをセットアップできるように非常に柔軟でなければならないプロジェクトに取り組んでいましたが、私たちが見つけた唯一の良い設計は、顧客に C# コンパイラを出荷することでした!

仕様が次のような単語で満たされている場合:

  • フレキシブル
  • プラグイン
  • カスタマイズ可能

私の経験のように、システムをどのようにサポートするか (および、各顧客は自分のケースは通常のケースであり、プラグインは必要ないと考えるため、サポートの料金はどのように請求されるか) について多くの質問をしてください。

プラグインを作成する顧客 (またはファウンドライン サポート担当者) のサポートは、アーキテクチャよりもはるかに困難です。

于 2010-05-10T12:42:36.317 に答える
6

普段はMEFを使っています。Managed Extensibility Framework (略して MEF) は、拡張可能なアプリケーションの作成を簡素化します。MEF は、アプリケーション拡張機能をロードするために利用できる検出および構成機能を提供します。

興味のある方は続きを読む...

于 2010-05-04T19:13:18.070 に答える
5

私の経験では、柔軟なプラグイン アーキテクチャを作成するための 2 つの最良の方法は、スクリプト言語とライブラリです。これら 2 つの概念は、私の考えでは直交しています。この 2 つは、関数型プログラミングとオブジェクト指向プログラミングのように、任意の割合で混在させることができますが、バランスがとれたときに最大の強みを発揮します。ライブラリは通常、動的な機能を備えた特定のインターフェイスを満たす責任がありますが、スクリプトは動的なインターフェイスを備えた機能を強調する傾向があります。

ライブラリを管理するスクリプトに基づくアーキテクチャが最適に機能するように思われることがわかりました。スクリプト言語を使用すると、低レベルのライブラリを高レベルで操作できるため、ライブラリは特定のインターフェイスから解放され、アプリケーション レベルの対話はすべて、より柔軟なスクリプト システムの手に委ねられます。

これを機能させるには、スクリプト システムに、アプリケーション データ、ロジック、および GUI へのフックを備えたかなり堅牢な API と、ライブラリからコードをインポートして実行する基本機能が必要です。さらに、スクリプトは通常、アプリケーションが不適切なスクリプトから正常に回復できるという意味で安全である必要があります。スクリプティング システムを間接レイヤーとして使用すると、Something Bad™ が発生した場合に、アプリケーションをより簡単に切り離すことができます。

プラグインをパッケージ化する方法は、個人の好みに大きく依存しますがPluginName.ext、ルート ディレクトリなどの単純なインターフェイスを備えた圧縮アーカイブを使用すれば、間違いはありません。

于 2010-05-12T16:54:44.017 に答える
3

最初に質問に答える必要があると思います:「どのコンポーネントがプラグインであると予想されますか?」この数を最小限に抑えるか、テストする必要がある組み合わせの数を爆発的に増やしたいと考えています。プラグイン機能からコア製品 (柔軟性が高すぎてはいけません) を分離するようにしてください。

IOC (Inversion of Control) プリンシパル (Springframework を参照) は、プラグイン開発を簡素化するために特殊化を追加できる柔軟なベースを提供するのに適していることがわかりました。

  • 「プラグイン タイプのアドバタイズメントとしてのインターフェイス」メカニズムについてコンテナをスキャンできます。
  • コンテナーを使用して、プラグインが必要とする可能性のある共通の依存関係 (つまり、ResourceLoaderAware または MessageSourceAware) を注入できます。
于 2010-05-12T16:33:36.860 に答える