Соответствует ли шаблон ActiveRecord / поддерживает принципы проектирования SOLID?

43

Меня интересует, поощряет или не поощряет ли шаблон ActiveRecord, известный благодаря Ruby on Rails, использование принципов проектирования SOLID .

Например, мне кажется, что объекты ActiveRecord содержат как доменную логику, так и логику персистентности, что является нарушением единой ответственности.

nicholaides
источник
6
Джим Вейрих, в конце своей SOLID Ruby Talk на конференции Ruby 2009 года, спрашивает аудиторию: «Объекты ActiveRecord реализуют концепцию домена и концепцию персистентности. Нарушает ли это SRP (принцип единой ответственности)?» Аудитория соглашается, что это нарушает ПСП. Джим спрашивает, беспокоит ли это их. Многие зрители говорят, что да. Зачем? Это делает тестирование сложнее. Это делает объект постоянства намного тяжелее.
Дэвид Дж.

Ответы:

56

Есть некоторая действительная критика на ActiveRecord. Как всегда, дядя Боб подводит итоги :

Проблема, с которой я столкнулся в Active Record, заключается в том, что она создает путаницу в этих двух очень разных стилях программирования. Таблица базы данных - это структура данных. Он выставил данные и не поведал. Но активная запись кажется объектом. У него есть «скрытые» данные и разоблаченное поведение. Я поместил слово «скрытый» в кавычки, потому что данные на самом деле не скрыты. Почти все производные ActiveRecord экспортируют столбцы базы данных через аксессоры и мутаторы. Действительно, Active Record предназначен для использования в качестве структуры данных.

С другой стороны, многие люди помещают методы бизнес-правил в свои классы Active Record; что заставляет их казаться объектами. Это приводит к дилемме. С какой стороны линии Active Record действительно падает? Это объект? Или это структура данных?

Википедия резюмирует критику в проблеме тестируемости :

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

Специально для реализации Ruby on Rails Гэвин Кинг пишет (выделено мое):

На данный момент, большинство разработчиков думают, ну, хорошо, так как, черт возьми, я должен знать, какие атрибуты у компании, глядя на мой код? И как мой IDE может автоматически завершить их? Конечно, у Rails есть быстрый ответ на этот вопрос. Просто запустите клиент базы данных и загляните в базу данных! Затем, предполагая, что вы знаете правила автоматической капитализации и плюрализации ActiveRecord / совершенно /, вы сможете угадать имена атрибутов вашего собственного класса Company и ввести их вручную.

Джон Янущак также пишет о реализации Ruby on Rails (выделено мной):

ПРОБЛЕМА № 1: СТАТИЧЕСКИЕ МЕТОДЫ

...

Кто-то скажет, что использование статических методов просто равноценно процедурному программированию и, следовательно, является плохим объектно-ориентированным проектированием. Другие сказали бы, что статические методы - смерть для тестируемости.

ПРОБЛЕМА № 2: НАСТРОЙКИ ГЛОБАЛЬНОЙ КОНФИГУРАЦИИ

...

Поэтому в моём примере и, соответственно, в экземплярах Account нет внедрения зависимости от класса Account. Как мы все должны знать, искать вещи очень, очень плохо!

Еще несколько ресурсов о том, почему ActiveRecord и ORM обычно считаются антишаблоном:

ActiveRecord всегда чувствовал себя как чрезвычайно полезный антишаблон , но я согласен, что он идет против SRP и, кроме того, он идет против принципа инверсии зависимостей.

Яннис
источник
ВАЖНОЕ обновление для rails 5+: «А как моя IDE может автоматически завершать их? Конечно, у пользователей Rails есть быстрый ответ на этот вопрос. О, просто запустите клиент вашей базы данных и посмотрите в базу данных!.» Недопустимо больше. С помощью атрибутов API вы можете определить все доступные столбцы на модели
Филипп Бартузи
6

(Я предполагаю, что класс ActiveRecord реализован без какой-либо возможности для внедрения зависимости).

Из личного опыта могу сказать, что шаблон ActiveRecord становится основным препятствием для написания юнит-тестов. Соединение персистентного уровня и бизнес-логики в одном «классе ActiveRecord» делает невозможным написание модульных тестов (если вы сначала не выполните рефакторинг). Поэтому единственный вариант - написание интеграционных тестов; и это не так эффективно, как юнит-тесты. Это становится серьезной проблемой, особенно если вы берете на себя проект с большим количеством классов ActiveRecord; это приводит к очень сложным интеграционным тестам, которые трудно поддерживать.

Итак, ActiveRecord в значительной степени идет против SRP и создает некоторую головную боль при обслуживании; кажется, отнимает способность писать юнит-тесты.

Guven
источник