序文: リレーショナル データベースを使用する MVC アーキテクチャでリポジトリ パターンを使用しようとしています。
最近、PHP で TDD の学習を始めましたが、データベースがアプリケーションの残りの部分と密接に結合されすぎていることに気付きました。リポジトリについて読み、IoC コンテナを使用してコントローラに「注入」しました。とてもクールなもの。しかし、ここでは、リポジトリの設計に関するいくつかの実際的な質問があります。次の例を考えてみましょう。
<?php
class DbUserRepository implements UserRepositoryInterface
{
protected $db;
public function __construct($db)
{
$this->db = $db;
}
public function findAll()
{
}
public function findById($id)
{
}
public function findByName($name)
{
}
public function create($user)
{
}
public function remove($user)
{
}
public function update($user)
{
}
}
問題 #1: フィールドが多すぎる
これらの検索方法はすべて、すべてのフィールドを選択 ( SELECT *
) アプローチを使用します。ただし、私のアプリでは、取得するフィールドの数を常に制限しようとしています。これにより、オーバーヘッドが追加され、処理が遅くなることがよくあります。このパターンを使用している人は、これにどのように対処しますか?
問題 #2: メソッドが多すぎる
このクラスは今のところ見栄えがしますが、実際のアプリではもっと多くのメソッドが必要であることを私は知っています。例えば:
- findAllByNameAndStatus
- 検索AllInCountry
- findAllWithEmailAddressSet
- findAllByAgeAndGender
- findAllByAgeAndGenderOrderByAge
- 等。
ご覧のとおり、可能なメソッドの非常に長いリストが存在する可能性があります。そして、上記のフィールド選択の問題を追加すると、問題は悪化します。以前は、通常、このすべてのロジックをコントローラーに正しく配置していました。
<?php
class MyController
{
public function users()
{
$users = User::select('name, email, status')
->byCountry('Canada')->orderBy('name')->rows();
return View::make('users', array('users' => $users));
}
}
私のリポジトリアプローチでは、これで終わりたくありません:
<?php
class MyController
{
public function users()
{
$users = $this->repo->get_first_name_last_name_email_username_status_by_country_order_by_name('Canada');
return View::make('users', array('users' => $users))
}
}
問題 #3: インターフェースを一致させることが不可能
リポジトリにインターフェイスを使用する利点があるので、実装を交換できます (テスト目的などで)。インターフェースについての私の理解では、インターフェースは実装が従わなければならないコントラクトを定義します。のような追加のメソッドをリポジトリに追加し始めるまでは、これは素晴らしいことですfindAllInCountry()
。ここで、インターフェイスを更新してこのメソッドも含める必要があります。そうしないと、他の実装にこのメソッドがない可能性があり、アプリケーションが壊れる可能性があります。これでは気が狂ったように感じます... 尻尾が犬を振っている場合。
仕様パターン?
これにより、リポジトリには固定数のメソッド ( save()
、、、、など)のみを含める必要があると思われます。しかし、特定のルックアップを実行するにはどうすればよいでしょうか? Specification Patternについて聞いたことがありますが、これは ( を介して) レコードのセット全体を削減するだけのように思えます。これは、データベースからプルしている場合、明らかにパフォーマンスに大きな問題があります。remove()
find()
findAll()
IsSatisfiedBy()
ヘルプ?
明らかに、リポジトリを扱うときは少し考え直す必要があります。これをどのように処理するのが最善かを誰かが教えてくれますか?