Добавить в корзинуПозвонить
Найти в Дзене
KIT

Как не усложнить работу с ActiveRecord

В прошлом посте мы разобрали классический вариант реализации Active Record. Обсудили, когда стоит переходить от Transactional Script к Active Record. Сегодня обсудим: 📌 Внутри Active Record помещайте только простые инварианты: проверки статусов, ограничения значений, пересчет полей, базовые проверки. 📌 Не включайте сложную бизнес-логику: расчёты цен с кучей правил, сложные жизненные циклы. Для этого уже нужен Domain Model. 📌 Избегайте анемии: не делайте getters/setters публичными без необходимости. Лучше использовать методы вроде order.addItem(...), а не order.getItems().add(...). 📌 Не превращайте сущность в "божественный объект" (God object) — если методов больше 10-15 и большая часть из них не про состояние самого объекта, пора задуматься о вынесении логики. В классическом варианте Active Record содержит логику по сохранению и загрузке самого себя из и в базу данных. В настоящий момент использование такого подхода — уже не лучшая идея. Такая реализация нарушает принципы единой от
Оглавление

В прошлом посте мы разобрали классический вариант реализации Active Record. Обсудили, когда стоит переходить от Transactional Script к Active Record.

Сегодня обсудим:

  • Какую логику помещать в Active Record.
  • Стоит ли использовать классический вариант реализации Active Record.

Несколько важных правил, чтобы Active Record не превратился в монстра

📌 Внутри Active Record помещайте только простые инварианты: проверки статусов, ограничения значений, пересчет полей, базовые проверки.

📌 Не включайте сложную бизнес-логику: расчёты цен с кучей правил, сложные жизненные циклы. Для этого уже нужен Domain Model.

📌 Избегайте анемии: не делайте getters/setters публичными без необходимости. Лучше использовать методы вроде order.addItem(...), а не order.getItems().add(...).

📌 Не превращайте сущность в "божественный объект" (God object) — если методов больше 10-15 и большая часть из них не про состояние самого объекта, пора задуматься о вынесении логики.

Логика сохранения самого себя в базу: актуально ли?

В классическом варианте Active Record содержит логику по сохранению и загрузке самого себя из и в базу данных. В настоящий момент использование такого подхода — уже не лучшая идея. Такая реализация нарушает принципы единой ответственности и вносит дополнительные сложности в поддержку и развитие функциональности.

В настоящий момент лучше делегировать логику по сохранению и загрузке объектов репозиторию, а не оставлять ее в Active Record. Но это уже не будет классическим паттерном Active Record, а, скорее всего, что-то среднее между Active Record и Domain Model.

Если мы оставляем работу с БД внутри объекта, мы получаем следующие проблемы:

✘ Смешивание инфраструктуры и бизнес-логики: объект знает и о том, как посчитать скидку, и о том, как сгенерировать SQL-запрос (или обратиться к EntityManager).

✘ Сложность тестирования: вам придется использовать моки базы данных или поднимать Testcontainers даже для проверки простой математики.

✘ Связность (Coupling): доменная логика становится намертво привязана к конкретному ORM-фреймворку.

Когда стоит оставить Active Record и не переходить дальше:

  • Бизнес-логика остаётся небольшой — несколько проверок + расчёты.
  • Поддомен не основной (core), а вспомогательный (supporting) или общий (generic).
  • Важны скорость разработки и минимум абстракций.
  • Проект небольшой или средний, нет планов на очень сложную доменную модель.
  • Уже используете ORM, где Active Record — естественный стиль (Panache, Eloquent и т. п.).

В core-доменах с высокой скоростью изменений и большой ценой ошибки переходите к Domain Model. В остальном Active Record — это разумный компромисс между простотой и выразительностью.

А вы где чаще останавливаетесь — на Transactional Script, Active Record или сразу прыгаете в богатую модель?

Реализация Active Record с делегированием логики в репозитории в моем telegram-канале

#DomainDrivenDesign #DDD #systemdesign #SoftwareArchitecture