0

タイトルが、私がテーブルに置きたいこの質問にぴったり合っているかどうかはわかりません.

私は卒業論文として Web MVC フレームワークを作成することを計画しており、アドバイザーとの以前の会話で、いくつかの成果を定義しようとしており、彼はこのプロジェクトではモジュール設計を選択する必要があると確信しました。

私はそれまでにいくつかの開発を行っていましたが、それがどの程度モジュール化されるかを分析するためにしばらく停止しましたが、「モジュール化」の本当の意味がわからないため、実際には実行できませんでした。

たとえば、別のモジュールを参照するだけでシステムのモジュール性が爆発するなど、私には明確ではないことがありますか?

データベースアクセスモジュールがあり、複雑なクエリの結果を保存するためにオプションでキャッシュモジュールを使用できるとしましょう。誰でもわかるように、少なくともキャッシュ モジュールには名前付けの依存関係があります。

「モジュール設計」という私の概念では、各コンポーネントを個別に配布し、他の人が開発した他のコンポーネントと相互作用させることができます。この場合、誰かが私のデータベースアクセスモジュールを使用したい場合、参照/命名の目的で、使用しない場合でも、キャッシュも取得する必要があることを示しました。

それで、これが本当にモジュラー設計なのか疑問に思っていました。

その機能に絶対に必要ではない他のコンポーネントの存在についても知らずに、各コンポーネントを個別に作成するような代替案を思いつきました。機能を拡張するために、Decorators と Adapters に基づいた構造を作成できます。

物事を少し明確にするために、ここに例を示します(PHPで):

interface Cache {
    public function isValid();
    public function setValue();
    public function getValue();
}

interface CacheManager {
    public function get($name);
    public function put($name, $value);
}

// Some concrete implementations...

interface DbAccessInterface {
    public doComplexOperation();
}

class DbAccess implements DbAccessInterface {
    private $cacheManager;

    public function __construct(..., CacheManager $cacheManager = null) {
        // ...
        $this->cacheManager = $cacheManager;
    }

    public function doComplexOperation() {
        if ($this->cacheManager !== null) {
            // return from cache if valid
        } 
        // complex operation
    }
}

interface Cache {
    public function isValid();
    public function setValue();
    public function getValue();
}

interface CacheManager {
    public function get($name);
    public function put($name, $value);
}

// Some concrete implementations...

interface DbAccessInterface {
    public function doComplexOperation();
}

class DbAccess implements DbAccessInterface {
    public function __construct(...) {
        // ...
    }

    public function doComplexQuery() {
        // complex operation
    }
}

// And now the integration module

class CachedDbAcess implements DbAccessInterface {
    private $dbAccess;
    private $cacheManager;

    public function __construct(DbAccessInterface $dbAccess, CacheManager $cacheManager) {
        $this->dbAccess = $dbAccess;
        $this->cacheManager = $cacheManager;
    }

    public function doComplexOperation() {
        $cache = $this->cacheManager->get("Foo")
        if($cache->isValid()) {
            return $cache->getValue();
        }
        // Do complex operation...
    }
}

ここで私の質問は次のとおりです。これが最善の解決策ですか? 要件として一緒に動作しないすべてのモジュールに対してこれを行う必要がありますが、そうすることでより効率的になりますか?

誰かが別の方法でそれを行うでしょうか?

これに関するさらにいくつかの質問がありますが、これがスタックオーバーフローにとって受け入れられる質問であるかどうかはわかりません。

PS: 英語は私の第一言語ではありません。一部の部分が少し混乱する可能性があります。

4

3 に答える 3

1

私は、その機能に絶対に必要ではない他のコンポーネントの存在さえ知らずに、各コンポーネントを個別に作成するような代替案を思いつきました

このアイデアを自分で思いついたのは素晴らしいことです。ステートメント自体は、モジュラー プログラミングの鍵です。

拡張性の点ではプラグイン アーキテクチャが最適ですが、特にアプリケーション内でのメンテナンスは難しいと思います。また、プラグイン アーキテクチャの複雑さに応じて、プラグイン ロジックなどを追加することで、コードをより複雑にすることができます。

したがって、モジュール内設計の場合は、N 層のインターフェイス ベースのアーキテクチャを選択します。基本的に、アーキテクチャはこれらの層を中継します。

  1. ドメイン/エンティティ
  2. インターフェース [1に依存]
  3. サービス[1と2による]
  4. リポジトリ / DAL [1 と 2 に依存]
  5. プレゼンテーション層 [1,2,3,4 に依存]

残念ながら、各層で個別のプロジェクト/dll 参照が必要なため、php プロジェクトでこれをきちんと達成できるとは思いません。ただし、アーキテクチャに従うと、アプリケーションのモジュール化に役立ちます。

モジュールごとに、インターフェースベースの設計を行う必要があります。後で実装を変更できるため、コードのモジュール性を強化するのに役立ちますが、コンシューマは同じままです。

このスタックオーバーフローの質問で、このインターフェースベースの設計に似た回答を提供しました。

最後になりましたが、アプリケーションを UI に合わせてモジュール化する場合は、Service Oriented Architecture. これは、アプリケーションを一連のサービスとして作成し、そのサービスを使用する UI を作成するだけです。この設計は、UI とロジックを分離するのに役立ちます。後でデスクトップ アプリなどの別の UI を使用できますが、同じロジックを引き続き使用できます。残念ながら、SOA に関する信頼できる情報源はありません。

編集:

私は質問を誤解しました。これがモジュラー フレームワークに関する私の見解です。残念ながら、私は Zend についてあまり知らないので、C# で例を示します。

  • 最小のモジュールから大きなモジュールまで、モジュールで構成されています。C# の例ではForm、アプリケーションで Windows (大きい) を使用し、Graphic(小さい) クラスを使用して画面にカスタム形状を描画できます。
  • 基本クラスを変更せずに拡張可能または置換可能です。C# では、FormLoadイベント (拡張可能) を Form クラスに割り当てたり、FormまたはListクラス (拡張可能) を継承したり、フォーム描画メソッドをオーバーライドして、カスタム ウィンドウ グラフィック (置換可能) を作成したりできます。
  • (オプション) 使いやすいです。通常の DI インターフェイス設計では、通常、小さなモジュールを大きな (高レベルの) モジュールに挿入します。これには IOC コンテナーが必要です。詳細については、私の質問を参照してください。
  • 設定が簡単で、 などの魔法のようなロジックは必要ありませんService Locator PatternService Locator is an Anti Patternグーグルで検索。

Zend についてはよくわかりませんが、Zend のモジュール性は、フレームワーク内のコアを変更する (コードを置き換える) ことなく拡張できることを意味すると思います。

あなたがそれを言った場合:

誰かが私のデータベース アクセス モジュールを使用したい場合は、参照/名前付けの目的で、使用しない場合でも、キャッシュも取得する必要があります。

それからそれはモジュラーではありません。統合されているため、データベース アクセス モジュールはキャッシュなしでは機能しません。C# コンポーネントを参照して、さまざまな機能を提供することを選択しList<T>ますBindingList<T>。あなたの場合、提供する方が良いと思いCachedDataAccessますDataAccess.

于 2013-05-20T04:58:08.777 に答える
1

別のモジュールを参照するだけで、システムのモジュール性が損なわれますか?

必ずしも。それは依存関係です。依存関係を持つことは完全に正常です。依存関係がないと、モジュールは相互に対話できません (依存関係を隠してコードを複雑にするため、一般的に悪い習慣であるような間接的な対話を行う場合を除きます)。モジュール設計とは、依存関係を削除するのではなく、管理することを意味します。

1 つのツール - インターフェイスを使用しています。インターフェイスを介してモジュールを参照すると、いわゆるソフト依存関係が作成されます。このようなモジュールは、インターフェイスの実装を依存関係として受け入れることができるため、より独立しており、その結果、より保守しやすくなります。

もう 1 つのツールは、単一の責任しか持たないモジュール (およびそのインターフェース) を設計することです。これにより、よりきめ細かく、独立し、保守しやすくなります。

しかし、越えてはならない一線があります。これらのツールをやみくもに適用すると、あまりにもモジュール化され、あまりにも一般的な設計につながる可能性があります。物事を細かくしすぎると、システム全体がより複雑になります。すべての開発者が使用できる汎用モジュールを作成して、ユニバースの問題を解決するべきではありません (それが目的でない限り)。まず第一に、システムはドメイン タスクを解決し、物事を十分に一般化する必要がありますが、それ以上ではありません。

于 2013-05-20T12:14:08.660 に答える
1

いくつかのリソース (理論的ではありません):

于 2013-05-20T00:22:17.320 に答える