Active Record vs Data Mapper

Active Record

Active Record — этот шаблон проектирования представляет запись из базы данных в виде объекта. Главная особенность — простота использования, так как колонки в базе данных являются полями (свойствами, атрибутами, кому как нравится) объекта и легко понять что с ними нужно делать.

Данный шаблон берет на себя две ответственности: первая — сущность (например, пользователь, заказ, проект и т.д.) и вторая — взаимодействие с хранилищем данных (простыми словами, он умеет себя доставать из БД, обновлять и удалять). Для небольших приложений подходит как нельзя лучше, он быстро воссоздается, иногда даже генерируется утилитами за секунды и с ним можно сразу работать. Это плюс. Для больших приложений со сложной бизнес логикой, с большой командой и необходимостью писать модульные тесты плюсы конвертируются в минусы, так как классы с несколькими ответственностями сложнее тестировать и поддерживать.

Пример (код абстрактный):

<?php
 
class User
{
    private MyDatabaseConnector $db;
 
    public int $id;
    public string $name;
    public string $surname;
 
    public function __construct(MyDatabaseConnector $db)
    {
        $this->db = $db;
    }
 
    public function save()
    {
        if (empty($this->id)) {
            $sql = "INSERT INTO user (name, surname) VALUES (:name, :surname)";
            $statement = $this->db->prepare($sql);
            $statement->bindParam("name", $this->name);
            $statement->bindParam("surname", $this->surname);
            $statement->execute();
 
            $this->id = $this->db->getLastInsertID();
        } else {
            $sql = "UPDATE user SET name = :name, surname = :surname WHERE id = :id";
            $statement = $this->db->prepare($sql);
            $statement->bindParam("id", $this->id);
            $statement->bindParam("name", $this->name);
            $statement->bindParam("surname", $this->surname);
            $statement->execute();
        }
    }
}
 
$user = new User(new MyDatabaseConnector());
$user->name = 'Ivan';
$user->surname = 'Ivanov';
$user->save();

Как понять когда его следует использовать? Сделать это проще чем может показаться на первый взгляд. Если вы занимаетесь проектирование структуры БД до написания кода приложения, т.е. вы используете так называемый «Database First»-подход и для успешного решения задачи его хватает, то Active Record это лучшее решение для вас.

Data Mapper

Шаблон проектирования Data Mapper является прослойкой между сущностью и хранилищем данных. Он служит для облегчения сущности путем взятия на себя ответственности по работе с хранилищем данных. Другими словами, при использовании Data Mapper сущность (пользователь, заказ, проект и т.д.) работает только со своими данными и бизнес-логикой, а сохранять, обновлять и удалять её будет другая часть системы.

Использование Data Mapper позволяет облегчить модель и отдать обязанности другим частям системы, это обеспечит более простую поддержку бизнес-логики и её тестирование. Но ценой этому является усложнение и увеличение приложения, нужно будет писать больше кода.

Пример (код абстрактный):

<?php
 
class User
{
    public int $id;
    public string $name;
    public string $surname;
}
 
class UserMapper
{
    private MySqlConnector $db;
 
    public function __construct(MySqlConnector $db)
    {
        $this->db = $db;
    }
 
    public function save(User $user)
    {
        if (empty($user->id)) {
            $sql = "INSERT INTO user (name, surname) VALUES (:name, :surname)";
            $statement = $this->db->prepare($sql);
            $statement->bindParam("name", $user->name);
            $statement->bindParam("surname", $user->surname);
            $statement->execute();
 
            $user->id = $this->db->getLastInsertID();
        } else {
            $sql = " UPDATE user SET name = :name, surname = :surname WHERE id = :id";
            $statement = $this->db->prepare($sql);
            $statement->bindParam("id", $user->id);
            $statement->bindParam("name", $user->name);
            $statement->bindParam("surname", $user->surname);
            $statement->execute();
        }
    }
}
 
$user = new User();
$user->name = 'Ivan';
$user->surname = 'Ivanov';
 
$mapper = new UserMapper(new MySqlConnector());
$mapper->save($user);

Как понять когда его следует использовать? Первым маркером применимости данного шаблона является наличие сложных сущностей — с большим количеством логики и необходимостью хранить данные этой сущности в нескольких таблицах, а то и вообще в разных типах хранилищ, например, одна часть данных хранится в MySQL, другая в MongoDB. Второй маркер — вы и ваша команда сначала описываете бизнес-логику, а потом уже думаете над тем как её сохранить в подходящих хранилищах, т.е. используете практику «Code First».

Добавить комментарий