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.
EDITED
I've just joined the chat to get some insights on this question. Let's make a resume:
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:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With