📜 ⬆️ ⬇️

Active Record vs. Data Mapper to save data

These 2 design patterns are described in the Martin Fowler book "Corporate Application Templates" and are ways to work with data storage in object-oriented programming.

Sample Active Record Template


class Foo { protected $db; public $id; public $bar; public function __construct(PDO $db) { $this->db = $db; } public function do_something() { $this->bar .= uniqid(); } public function save() { if ($this->id) { $sql = "UPDATE foo SET bar = :bar WHERE id = :id"; $statement = $this->db->prepare($sql); $statement->bindParam("bar", $this->bar); $statement->bindParam("id", $this->id); $statement->execute(); } else { $sql = "INSERT INTO foo (bar) VALUES (:bar)"; $statement = $this->db->prepare($sql); $statement->bindParam("bar", $this->bar); $statement->execute(); $this->id = $this->db->lastInsertId(); } } } //Insert $foo = new Foo($db); $foo->bar = 'baz'; $foo->save(); 

In this simplified example, a database descriptor is entered in the constructor of Foo (Using dependency injection here allows you to test an object without using a real database), and Foo uses it to save its data. Do_something is just a stub method that replaces business logic.

Benefits of Active Record



Disadvantages of Active Record



Data Mapper Example


 class Foo { public $id; public $bar; public function do_something() { $this->bar .= uniqid(); } } class FooMapper { protected $db; public function __construct(PDO $db) { $this->db = $db; } public function saveFoo(Foo &$foo) { if ($foo->id) { $sql = "UPDATE foo SET bar = :bar WHERE id = :id"; $statement = $this->db->prepare($sql); $statement->bindParam("bar", $foo->bar); $statement->bindParam("id", $foo->id); $statement->execute(); } else { $sql = "INSERT INTO foo (bar) VALUES (:bar)"; $statement = $this->db->prepare($sql); $statement->bindParam("bar", $foo->bar); $statement->execute(); $foo->id = $this->db->lastInsertId(); } } } //Insert $foo = new Foo(); $foo->bar = 'baz'; $mapper = new FooMapper($db); $mapper->saveFoo($foo); 

In this case, the Foo class is much simpler and should only worry about its business logic. Not only does he not have to save his own data, he does not even know and does not care about whether all his data has been saved.
')

Advantages of Data Mapper



Disadvantages Data Mapper



Service Objects


When using the Data Mapper design pattern, the calling code must select the Mapper and the business object and link them together. If this is the call code in the controller, then ultimately your model “leaks” into the controller, which can cause major problems with support and unit testing. This problem can be solved by introducing a service object. The service is the gateway between the controller and the model and connects the domain object with the Mapper as needed.

It should be remembered that M in MVC is a model abstraction layer, not a model object. So there can be several types of objects in one model (in the example above, you can have a service object, a domain object, and a Mapper object acting as a single model). On the other hand, if you use Active Record models, your model can be represented by only one object.

Use cases


Active Record objects have historically been very popular due to the fact that they are simpler, easier to understand and faster to write, so many frameworks and ORM use Active Record by default.

If you are sure that you will never need to change the data retention layer (if you are dealing with an object that is an INI file, for example), or you are dealing with very simple objects that do not have much business logic, or just prefer to keep everything in a small number of classes, then the Active Record template is what you need.

Using the Data Mapper, although it leads to cleaner code, easier to test and maintain, and provides more flexibility — the price to it — increases complexity. If you have not tried it yet, then give it a chance - you should like it.

This is a translation of the article by Russell Volcker .

Source: https://habr.com/ru/post/198450/


All Articles