web-dev-qa-db-ja.com

Webアプリのプラグインアーキテクチャ(例またはコードスニペット)

プラグインを介して高度に拡張可能でカスタマイズ可能なWebアプリケーション(できればNodeJS/MongoDBを使用しましたが、PHPおよびPython以前)を使用しましたが)無効な機能を有効にします。

可能なオプションの1つは、Wordpressをフックするプラグインとウィジェットのフックとともに使用することですが、ビューとロジックコードの適切な分離が欠けています。これは、学ぶべき1つのオプションです。他のオプション?

学習できるコードスニペットまたはサンプルアプリケーションはありますか?言語やフレームワークはそれほど重要ではありません。おそらく背後にある概念を大まかに理解することができます。

38
Jiew Meng

優れたプラグインアーキテクチャをゼロから実現することは困難ですが、独自の報酬を提供します。複雑さをローカライズすることにより、ソフトウェアを柔軟かつ簡単に維持できます。それが必要とする一番のスキルは、 疎結合コード を書く能力です。これには、多型の非常に強固な把握が必要です Demeterの法則 および関連する ハリウッドの原理

最初にそれらをよく理解し、次に次の設計パターンを習得することをお勧めします。

  • コマンドパターン :プラグインモジュールに一貫したエントリポイントを提供し、それらを容易に交換できるようにします。 IBMのWebベースの例
  • Memento :カプセル化に違反することなく状態をキャプチャ、ホールド、外部化して、コンテナがプラグインを設定できるようにします。
  • コールバック :プラグインモジュールがコンテナ/環境から「サービス」にアクセスできるようにします。
  • 依存性注入 :プラグインモジュールの環境からのカップリングを緩める方法。
  • Abstract Factory Pattern :環境にプラグインをインストールしてインスタンス化します。
  • Builderパターン :プラグインモジュールが相互に依存している自明でないプラグインアーキテクチャに必要です。

これらを把握したら、既存のプラグインフレームワークの実装とアーキテクチャのいくつかを調べて、それらがどのように使用されているかを確認してください。 Apacheには、 StrutsGeronimoカスタムサーバーアセンブリ 、および Tomcat JNDIリソース にいくつかあります。 Eclipseプラグインフレームワーク も。

72
Martin Spamer

プラグインアーキテクチャ自体はありませんが、クライアントコードを疎結合にしておく方法を説明します。

Asp.netを使用しています。 main.aspxページを提供します。このページには、最初にメディエーターjavascriptファイルが含まれています。それはグローバルオブジェクトを定義します-それをメディエータと呼びます-これは私たちが定義する唯一のグローバルオブジェクトです。

メディエーターは、パブリッシュおよびサブスクライブのメッセージを含む単純なインターフェースを公開します。

mediator.subscribe(messageName, callback);
mediator.publish(messageName);

Mediator.jsファイルの後、メインページには他の多くのjavaScriptファイルが含まれています。各ファイルは、メディエーターに機能を登録する即時関数で構成されています。このパターンの詳細については、 here を参照するか、以前の私の質問 here を参照してください。

同様のアプローチに従うことができます-プラグインの機能を登録するためのインターフェースを提供する単一のグローバルオブジェクト(例:pluginFramework)を定義します。クライアントに配信するhtmlページを作成する場合、最初にpluginFrameworkファイルを含めてから、ユーザーまたはデバイスに依存する可能性のある目的のJavaScriptプラグインファイルを動的に含めます(たとえば、デバイスがタッチ対応の場合は異なるプラグインですか?)。これらのプラグインファイルは、即時機能でpluginFrameworkに機能を追加します。

プラグインがUIのメニューに機能を追加できるようにする方法の例を次に示します。

pluginFramework.js:

var pluginFramework = (function() {
    var menuItems = [];
    function addMenuItemPrivate(itemName, callback) {
        // e.g. add itemName and callback to menuItems
    }
    return {
        addMenuItem: addMenuItemPrivate;
    }
})());

photoPlugin.js:

(function() {
    function addPhoto() {
        //...
    }
    pluginFramework.addMenuItem('add photo', addPhoto)
})());

これが何らかの形で役立つことを願っています!

6
GarethOwen

あなたのコメントは、あなたが構築しているのは マルチテナントアーキテクチャ であることを示唆しています。

これは複雑な要件であり、通常、レトロフィットするのは非常に困難です。それはどこから始めているかに大きく依存します。

最初に、まず最初にきちんとファクタリングされたWebアプリケーションが必要です。 MVCフレームワークを使用している場合は、出発点があります。

次に、拡張機能をサポートする場所を決定する必要があります。インスタンスの場合、クライアントはUIの完全に別個のスキンを使用できますか?その場合、スキニングフレームワークが必要です。クライアントはすべてを変更できますか、またはキーポイントで異なるコンポーネントをプラグインするだけです(カスタム支払いプロバイダー、カスタム認証スキームなど)。何でも拡張できるフレームワークを設計するよりも、限られた拡張ポイントのセットをサポートする方がはるかに簡単です。

次に、データ戦略。 MSDNのマルチテナンシーに関する良い記事 ;リレーショナルデータベースを対象としていますが、Mongoに適用できるアイデアを提供します。

最後に、必要な拡張ポイントをサポートするコンポーネントアーキテクチャを考え出す必要があります。 Webアプリケーションを扱う場合、モデル、ビュー、コントローラー、および永続性を変更できる必要があります。最適な解決策は、MVCフレームワークが機能する方法を使用し、「テナントxに対してはy、テナントzに対してはw」ロジックをコントローラーレイヤーに配置することです。これを試して、必要ないくつかのケースで機能するようにし、それから何が問題なのかを解決して修正します。

4
Neville Kuyt

あなた自身がクライアントのカスタマイズを行っている場合、Djangoはこれに理想的です。あなたが望むすべての基本的な機能を処理するコアアプリケーションを作成します。設定でインストール済みのアプリにそのアプリを追加するだけで、メインのアプリにプラグインできる新しいアプリを作成します。

これにより、スキニング(新しいbase_site.htmlテンプレートを作成し、他のすべてのテンプレートを継承する)、複数のデータベースのサポート、プラグインを処理し、新しいプラグイン/機能を非常に迅速に開発および展開できます。

内部システムの可能性のあるより一般的な例については、 メレンゲ または pinax を参照してください。

1
Murph