13

Doctrine 2 と Propel 1.6 の長所と短所を知りたいです。たとえば、Doctrine 2 は非常に使いやすいですが、順応性を超えたい場合は制限があります。Doctrine 2 ドキュメントの更新がない...

可能であれば、Doctrine2 のどこが良かったのか、Propel が完璧だったのかについて、あなたの経験を共有できます。

前もって感謝します。

4

1 に答える 1

18

編集済み

この質問についての洞察を得るためにチャットに参加しました。履歴書を作りましょう:

単一責任の原則

  • Doctrine 2.x のみが DataMapper のアイデアの一部を使用しています
  • 開発者は、 ActiveRecordが神からのアンブロシアであると今でも考えています
  • DB とは別にテストできない
  • 依存性注入の敵

参照: https://softwareengineering.stackexchange.com/questions/119352/does-the-activerecord-pattern-follow-encourage-the-solid-design-principles

説明

Propel はActiveRecordパターンと Doctrine に基づいており、代わりにData MappersVirtual Proxiesを利用します。

PHP で OOP について初めて知ったとき、ActiveRecord が広く使用されていましたが、これは主に Ruby On Rails の影響によるものです。その後、開発者は、ActiveRecord が限定された概念であり、特に大規模なアプリケーション向けであることに気付き始めました。

なんで?

自分で考えてみてください。それ自体を保存する方法を知るのは、ドメイン モデル オブジェクトの責任ですか? それとも、そのデータを JSON 形式に変換しますか?

単一責任の原則 (SRP)とドメインの結束に違反するため、答えはノーです。

Martin は責任を変更する理由として定義し、クラスまたはモジュールには変更する理由が 1 つだけあるべきだと結論付けています。

Authorエンティティがあるとしましょう。どのような理由で変更しますか? ActiveRecord を使用して実装する場合、オブジェクトのプロパティ自体を変更する必要があるだけでなく、キャッシュ戦略を実装するときに行うように、そのオブジェクトに固有の新しいタイプの永続性を実装する場合も変更する必要があります。

また、Propel ライブラリがモデルの基底クラスのメソッドを変更するとしましょう (単純な例です)。エンティティが ORM 基底クラスと密結合しているため、永続性を持たないアプリケーションの他の部分を変更する理由ができました。つまり、ドメイン モデル オブジェクトは、各 ORM フレームワークの仕様に依存するべきではありません。ORM を変更して、ドメイン モデル オブジェクトを変更しないようにする必要があります。

そのため、アクティブ レコードでは、ドメイン モデルが永続化レイヤーの存在を認識している必要があります。2 つの責任があります。

Active Record を使用する際の最悪の事態は、ドメイン モデルの継承階層を「台無しにする」ことです。Human永続化の目的で基本クラスを拡張するエンティティがあり、次にエンティティManを拡張するHumanエンティティがある場合、何らかの理由で、永続化する機能なしでエンティティをWoman拡張する別のエンティティがある場合、基本クラスによって確立されたコントラクトHumanを破ることになります。これは、各エンティティが自分自身を保存する方法を知る必要があることを示しています。できません。$woman->save()

厳密に言えば、リスコフ置換原理の違反にもつながります

最後に、ActiveRecord の使用をやめる究極の理由。次のコードを見ると、トランザクション中にオブジェクトをストレージにマッピングするという ORM の責任が、ドメイン モデル エンティティに委任されていることがわかります。

class Book extends BaseBook
{
  public function postSave(PropelPDO $con)
  {
    $this->updateNbBooks($con);
  }

  public function postDelete(PropelPDO $con)
  {
    $this->updateNbBooks($con);
  }

  public function updateNbBooks(PropelPDO $con)
  {
    $author = $this->getAuthor();
    $nbBooks = $author->countBooks($con);
    $author->setNbBooks($nbBooks);
    $author->save($con);
  }
}

http://www.propelorm.org/documentation/06-transactions.html Book オブジェクトを保存または削除するたびに、この新しい列を更新する必要があります。これにより、クエリの書き込みが少し遅くなりますが、クエリの読み取りははるかに高速になります。幸いなことに、Propel モデル オブジェクトは save() および delete() メソッドの pre- および post- フックをサポートしているため、これを実装するのは非常に簡単です。

したがって、単一のモデル エンティティには次のものがあります。

  1. 持続性
  2. 事前および事後保存/削除用のインターセプト フィルター パターン
  3. 検証 ( http://www.propelorm.org/documentation/05-validators.html )
  4. キャッシュ
  5. そして、そこに行きます...
于 2012-08-19T22:42:06.260 に答える