13

我想知道 Doctrine 2 和 Propel 1.6 的力量和弱点是什么。例如,Doctrine 2 确实是用户友好的,但如果您想超越墨守成规,则会限制您。教义 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 则使用数据映射器虚拟代理

当我第一次使用 PHP 了解 OOP 时,ActiveRecord 被广泛使用,这主要是由于 Ruby On Rails 的影响。然后开发人员开始意识到 ActiveRecord 是一个有限的概念,特别是对于大型应用程序。

为什么?

自己想想,是不是域模型对象有责任知道如何自救?甚至将其数据转换为 JSON 格式?

答案是否定的,因为它违反了单一职责原则 (SRP)和域凝聚力

Martin 将责任定义为改变的理由,并得出结论认为一个类或模块应该有一个,而且只有一个改变的理由。

假设您有一个Author实体。你会因为什么原因改变它?好吧,如果使用 ActiveRecord 实现,除了需要更改对象属性本身之外,如果您实现特定于该对象的新类型的持久性,您还需要更改它,就像我们在实现缓存策略时所做的那样。

另外,假设 Propel 库改变了模型基类的方法(只是一个简单的例子)。现在您有理由更改应用程序的其他部分,因为您的实体与 ORM 基类紧密耦合。换句话说,你的领域模型对象不应该依赖于每个 ORM 框架的细节。您应该能够更改您的 ORM,让您的域模型对象保持不变。

所以活动记录需要你的领域模型知道持久层的存在。有两个责任

使用 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() 方法的前钩子和后钩子,所以这很容易实现

因此,在单个模型实体中,您拥有:

  1. 持久性
  2. 拦截过滤器模式,用于保存/删除前后
  3. 验证(http://www.propelorm.org/documentation/05-validators.html
  4. 缓存
  5. 你去...
于 2012-08-19T22:42:06.260 回答