Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Почему считается, что модели eloquent имеют минимум две ответсвенности? #5

Open
antonprogz opened this issue Feb 12, 2020 · 6 comments

Comments

@antonprogz
Copy link

antonprogz commented Feb 12, 2020

В главе "Внедрение зависимостей" встретил следующую фразу:

Классы Eloquent моделей содержат как минимум две ответственности: хранение состояния сущности и выборку/сохранение/удаление сущностей из базы

В связи с этим, у меня возникли следующие вопросы:

  1. Взаимодействие с базой это не часть ответственности по хранению данных? Я думаю хранение данных должно предусматривать взаимодействие с каким-либо персистентным хранилищем, иначе это не хранение.
  2. Почему тогда, например, обязанности класса Request не определить как:
  • хранение данных HTTP запроса
  • парсинг HTTP запроса

Я считаю, что иметь состояние для класса в ООП это не обязанность. Все объекты в ООП (даже т.н. stateless сервисы) имеют состояние, взять хотя бы внутренний идентификатор, зависимости, конфигурацию. Почему наличие атрибутов с данными в моделях Eloquent считаются отдельной ответственностью?

@adelf
Copy link
Owner

adelf commented Feb 12, 2020

Привет, Антон.
В главе про доменный слой я разовью мысль, что персистить данные - это просто необходимое зло) и для некоторых приложений логика в классах-моделях намного сложнее логики хранения их в базе данных.
Это две разные логики, но элоквент соединяет их в одну и получаются фактически строчки в базе данных, которые с собой какую-то логику несут. Эти две ответственности и назвал. Но, вероятно, надо исправить немного это предложение как-нибудь.

@githubjeka
Copy link

Классы Eloquent моделей содержат как минимум две ответственности: хранение состояния сущности и выборку/сохранение/удаление сущностей из базы

Вопрос в том, что нарушается SRP?

Я не вижу тут беспокойств. Причина внесения изменений в Eloquent одна - может поменяться что-то в базе данных. Со связностью (cohesion) всё впорядке, все методы сконцентрированы одной цели - работа с данными из базы данных. А вот если бизнес логика начинает появляться в Eloquent - вот тогда плохо...

@adelf
Copy link
Owner

adelf commented Feb 18, 2020

Евгений, я говорил ещё и о выборках из базы и методах сохранения/удаления. Все эти Soft delete, скоупы люди часто суют в классы моделей. И если скоупы ещё можно как-то отдельно держать (хотя это и не модно), то глобальные скоупы, такие как софт делит - не получится. Это немного другая логика, чем представление строки из бд.

@mikield
Copy link

mikield commented Aug 4, 2021

А вот если бизнес логика начинает появляться в Eloquent - вот тогда плохо...

@githubjeka Много раз видел как используют подход "Тонкие Контроллеры -> Толстые Модели".

Скоупы получения данных где уже вшита бизнес логика, с (например) той же фильтрацией по типу пользовательского аккаунта (простой/премиум).
Скоупы которые являются не продолжением Eloquent\Builder а которые вызывают get() и возвращают результат.

Так что в реальных проектах, тезис

Причина внесения изменений в Eloquent одна - может поменяться что-то в базе данных.
получается не всегда правдивым.

И причиной изменения моделей становится банальное изменение бизнес логики.

Приведу пример с скоупом.

$users = User::onlyActive()->get();

И тут уже зарыта собака, ведь сегодня только активные пользователи это те у кого email_verified_at != NULL а завтра уже и у кого phone != null и profile()->exists() и т.д.

Удобно же правда, вроде KISS а вроде уже смешивание слоев, и в будущем, лично я, побоюсь добавить или изменить этот скоуп, ведь потому что PHPStorm и магия Laravel не дает мне интуитивно найти места где используется этот метод.
Да через глобальный поиск можно, но скоупы же не всегда вызываются статично, однажды это из инстанца, а иногда вообще из Builder.
Пример:

$user = new App\Models\User;
return $user->onlyActivated()->get();
# Файл App\Models\User.php
//...
public function scopeOnlyActive($builder) {
   return $builder->whereNotNull('email_verified_at');
}

public function scopeOnlyActivated($builder){
   return $builder->onlyActive();
}

пы. сы. В определённых кругах, за то что в Laravel используется Active Record и Model - архитекторы настаивают на замене его на Doctrine :)
пы. сы. сы С последним примером скупов я сомневался, и попробовав я, честно говоря, удивлен что оно работает.

@githubjeka
Copy link

В вашем примере "собака зарыта" не в Active Record , а в том, что нет единого АPI получения активных пользователей.

@mikield
Copy link

mikield commented Aug 6, 2021

... что нет единого АPI получения активных пользователей.

Вы правы, собака зарыта в разработчиках которые так пишут как у меня в примере.
В тех кто вставляет бизнес валидацию и логику в модель данных.

С одной стороны они то правы, любой обучающий ресурс им так диктует.
Мол: тут мы "отфильтруем" данные с помощью "скоуп функций".
А тут пользователь сам себе вышлет новый эмелй.

Я просто хотел своим сообщением вам показать что утверждение

Причина внесения изменений в Eloquent одна - может поменяться что-то в базе данных.
получается не всегда правдивым.
Не так верно как кажется.

И я согласен с вами, я бы тоже хотел изменять модель в соотвествии только с изменениями в схеме.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants