Weaknesses and forces of Doctrine 2 and Propel 1.6 [closed]
Asked Answered
T

1

13

I would like to know what are the forces and weaknesses of Doctrine 2 and Propel 1.6. For instance, Doctrine 2 is really user friendly but limits you if you want to go beyond conformism. Doctrine 2 documentation lack of updates ...

If possible you can share your experience on where Doctrine2 was doing good or where Propel was perfect.

Thanks in advance.

Tacit answered 19/8, 2012 at 11:10 Comment(3)
This question will lead in non-constructive answers. Just read the first answer and its first comment.Terrel
Here is a good explanation of the ActiveRecord evil programmers.stackexchange.com/questions/119352/…Gaytan
@WilliamDURAND I don't think so, it's clearly defined why Propel is not the way to go for middle size to large applications.Gaytan
G
18

EDITED

I've just joined the chat to get some insights on this question. Let's make a resume:

Single Responsibility Principle

  • only Doctrine 2.x uses some of the DataMapper ideas
  • Developers still think that ActiveRecord is the ambrosia from gods
  • The inability to test separately from DB
  • Dependency Injection enemy

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

Description

Propel is based on the ActiveRecord Pattern, and Doctrine, instead make use of Data Mappers and Virtual Proxies.

When I first learned about OOP with PHP, ActiveRecord was being widely used, most due the Ruby On Rails influence. Then the developers started realizing that ActiveRecord is a limited concept, specially for larger applications.

Why?

Think by yourself, is the responsibility of a domain model object to know how to save itself? Or even convert its data to the JSON format?

The answer is no, because it violates the Single Responsibility Principle (SRP) and the domain cohesion.

Martin defines a responsibility as a reason to change, and concludes that a class or module should have one, and only one, reason to change.

Let's say you have an Author entity. For which reasons would you change it? Well, if implemented using ActiveRecord, besides the need to change the object properties itself, you'll also need to change it if you implement a new type of persistence specific to that object, as we do when implementing cache strategies.

Also, let's say the Propel library changes the method of the model's base class (just a naive example). Now you have a reason to change other parts of your application that doesn't have nothing with persistence, since your entities are tight coupled with the ORM base class. In other words, your domain model objects should not depend on the specifics of each ORM Framework. You should be able to change your ORM letting your domain model objects untouched.

So active record requires your domain model to knows about the existence of a persistence layer. There are two responsibilities.

The worst thing when using Active Record, is that you "screw up" your domain model inheritance hierarchy. If you have a Human entity extending a base class for persistence purposes, and then a Man entity extending the Human entity, if for some reason you have another Woman entity extending the Human Entity without the ability to be persisted, then you will break the contract established by the base class which states that each entity needs to know how to save itself. You'll not be able to do $woman->save().

Strictly saying, it also leds to violations of the Liskov Substitution Principle

Finally, the ultimate reason to stop using ActiveRecord. Looking at the following code you'll be able to see that the ORM's responsibility of mapping objects to the storage during a transaction was delegated to a domain model entity:

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 You must update this new column every time you save or delete a Book object; this will make write queries a little slower, but read queries much faster. Fortunately, Propel model objects support pre- and post- hooks for the save() and delete() methods, so this is quite easy to implement

So, in a single model entity you have:

  1. Persistence
  2. Intercepting Filter Pattern for pre and post saving/deleting
  3. Validation (http://www.propelorm.org/documentation/05-validators.html)
  4. Cache
  5. And there you go...
Gaytan answered 19/8, 2012 at 22:42 Comment(9)
Even though i use and love Doctrine, i do not agree with you answer, because the only thing you use to compare doctrine/propel is the "Single Responsibility Principle". You just demonstrate 1 weakness of Propel, nothing more.Suffrage
Just to be clear: in a single model entity you have methods to persist the entity, and data. Nothing more. The validation is deprecated, and I don't know anyone who uses it. There is no cache, as Propel is fast enough, faster than Doctrine2 btw. [Disclaimer: propel lead]Terrel
@Suffrage Having to extend base classes is already a strong reason to stop using ActiveRecord. And it's not just the SRP principle, but also the LSP, module cohesion, domain model hierarchy, tight coupling. It does not makes sense at all, a model entity "is a" persistable object? It's what ActiveRecord states and simply doesn't scale well.Gaytan
@WilliamDURAND Sorry, whether to use cache or not will depend on your application needs not simply the ORM speed.Gaytan
Propel is not an ActiveRecord implementation, part of Symfony2 (bridge), part of the official documentation, used by Sensio Labs (company behind Symfony). Oh and it's used by companies like TF1, one of the largest media group in Europe. So please, stop. If you knew Propel, you would not say that. Propel2 removes inheritance too, so you deal with stupid PHP objects too. But yes you're right, Doctrine implements wonderful design patterns. Results? It's slow as hell, annoying, and hard to use. Sometimes you dont have the entity manager where you need it for example.Terrel
You may be interested by this blog post: propel.posterous.com/propel2-what-why-whenTerrel
@WilliamDURAND Don't take me wrong, Propel is a good ActiveRecord based ORM, as stated on the home page propelorm.org Propel implements all the key concepts of mature ORM layers: the ActiveRecord pattern, validators, behaviors, table inheritance, reverse engineering an existing database, nested sets, nested transactions, lazy loading, LOB, you name it.. Btw, looking forward to see the Propel 2 in action. Thank you for your thoughts :)Gaytan
@William's link above is broken, and is now this.Cupboard
Propel1 and Propel2 both have one major flaw and performance killer, when saving related objects they loads all related objects into memory and check them for already existing relation. Anyway Propel1 is no longer supported.Branscum

© 2022 - 2024 — McMap. All rights reserved.