2

Misko Hevery によるGoogle のクリーン コード トークを見てきました。これらの話は次のように述べています: コンストラクターで依存関係を要求して、他のプログラマーが特定のオブジェクトのインスタンスをインスタンス化するために必要なものを事前に正確に確認できるようにします (デメテルの法則)。これにより、プログラマーは何をモックする必要があるかを正確に把握できるため、テストが容易になります。

例の時間
クラスがあり、データ アクセスを抽象化Customerするクラスもあるとします。CustomerDAO顧客オブジェクトを作成するときは、次のようにします。

database = new Database('dsn');
customerDao = new CustomerDAO(database);
customer = new Customer(customerDao);

これは私のコントローラーで発生する可能性があります。依存性注入コンテナを使用することで、このオブジェクトの構築を簡素化できます。以下では、DI コンテナーを使用してデータベース クラスのインスタンスを取得しました。これは、アプリケーション全体で広く使用されているためです。これにより、構築コードが 1 か所に減り、テスト用にモックできます。

ドメイン クラスの依存関係 (この場合は DAO オブジェクト) を DI コンテナーに追加する必要がありますか? アプリケーションが大きい場合、DI コンテナーは巨大になりますか?

DI コンテナーを使用すると、コードは次のようになります。

// container setup
container->dsn = '...';
container->dbh = function($c) {
    return new Database($c->dsn);
};
container->customerDao = function($c) {
    return new CustomerDAO($c->dbh);
};

// controller code
class ControllerCustomer extends ControllerBase {

    public function index() {
        container = this->getContainer();
        customer = new Customer(container->customerDao);
        view->customerName = customer->getName();
        view->render();
    }

}

別のプログラマーが をテストしたい場合はCustomer、 mock だけが必要CustomerDAOです。

この例をさらに一歩進めると、他のドメイン クラスに依存するドメイン クラスがある場合、私の DI コンテナーはすべてのドメイン クラスを構築する方法を知る必要がないはずです。例えば:

私の顧客は会社/機関であり、したがって多くのユーザーがいます。

class Customer {

  protected _dao;

  public function Customer(dao) {
    _dao = dao;
  }

  public function listUsers() {
    userIds = _dao->getAllUserIds();
    users = array();
    foreach (userIds as uid) {
      user = new User(new UserDAO(new Database('dsn')); // problem
      users[] user->load(uid);
    }
    return users;
  }

}

問題

  1. DI コンテナーをオブジェクトに渡していCustomerないため、データベース DSN への参照がないため、上記のようにユーザー オブジェクトを作成できません (ユーザーの作成方法を知る必要はありません)。
  2. 独自の依存関係を作成すると、モック用の継ぎ目がなく具体的​​であるため、このコードをテストできなくなります。
  3. コンテナを自分のCustomerクラスに渡すと、インターフェイスがCustomer嘘になりますか? (リンクされた Google ビデオの 9:15 を参照)。

オブジェクトCustomerを構築できるようにするには、ユーザー ファクトリを渡す必要がありますか?User

database = new Database('dsn');
userDao = new UserDAO(database);
userFactory = new UserFactory(userDao);
customer = new Customer(customerDao, userFactory);

の構造をUserFactoryDI コンテナに入れる必要がありますか?

4

1 に答える 1

0

私がこれを正しく解釈している場合、あなたの質問は実際にはエンティティの構築とライフサイクル管理に関するもののようです。

DDD は、このような問題に対処する方法について非常に規範的なガイダンスを提供する設計アプローチの 1 つです。あなたの場合、関連する概念はリポジトリと集約ルートです。DDD はおそらくあなたの質問に直接答えることはありませんが、要件に合ったパターンベースのソリューションを簡単に見つけられるようになります。

私は意図的に、DDD の一般的な説明や、私が言及した概念を説明しようとはしていません。SO や他の場所で利用できる十分な資料があります。

于 2011-05-29T20:08:36.613 に答える