Re[5]: Как определить где размещать бизнес-логику
От: Sinclair Россия https://github.com/evilguest/
Дата: 10.06.21 07:21
Оценка:
Здравствуйте, Nikita Lyapin, Вы писали:

NL>Ничего нового. Такой подход мне знаком и я бы не сказал, что он меня как-то впечатляет. И да, он все таки больше процедурный. Вы попытались реализовать логику формирования запросов с помощью ООП. Но сама бизнес-логика и сами бизнес правила явно не выделены.

Как это не выделена? Вполне себе выделена. В совершенно явном и понятном виде: вот есть правило про проверку разрешений, вот реализация этого правила.
Некуда делать это более ООПшным.

NL>1. Признак это переменная db. Это что? Статическая переменная? Ну или контекст? — сути не меняет — привет глобальное состояние.

В данном примере это статическая переменная. В этом нет никакой проблемы, т.к. у этой "переменной" нет состояния; но если по-вашему тут недостаточно паттернов, то можете сделать эту переменную параметром.

NL>2. Все это больше похоже на попытку мыслить в функциональном стиле. У вас есть функции и есть данные, далее поверх этих данных вы пытаетесь навесить поведение. Но опять же делаете это не явно и у вас функции с состоянием. Тогда уж лучше разнести. Например, CheckPermissions — у вас items принимается как параметрю. А вот Permissions нет.

NL>3. На самом деле большую опасность здесь несут неявные связи. SQL может в мгновение ока построить вам связь между сущностями. Это как спор между языками с статической типизацией и динамической. Вот вы говорите, что теперь у пользователей есть права и они мапятся по Id для всех у кого такой-то признак. И бац — оформили это в вашем запросе как джойн. В случае с мапингом на доменные сущности вам нужно заморочиться. Обьявить коллекцию, заполнить ее данными и т.п. — дофига кода. Это и плюс и минус одновременно.
Нет, это чистый минус.
NL>Если мы работаем с несложной бизнес-логикой где пару тройку доменных сущностей. Ну 10, 15. Данное свойство SQL и как следствие LINQ2DB не оказывает влияния.
Оказывает. Объём кода — это прямые расходы на разработку, тестирование, и поддержку. Даже если у вас доменных сущностей две. Просто вам кажется, что написать лишние 200 строк кода — это малозначимая фигня, а вот если бы их было 200 тысяч, тогда решение становится важным. На практике вы не пишете сразу 200000 строк, вы получаете их в результате тысячи доработок, в каждой из которых дописывается по 200 строк.

NL>С другой стороны мапинг на доменные сущности дает лишь оверхэд. Но в сложных доменах обьявление класса уже является и документацией.

Всё верно. Вот мы объявили Vehicle: ISecurable и сразу этим показали, что права доступа к нему контролируются через таблицу Permissions.
NL>По этому коду можно понимать модель. В SQL нужно прошерстить и держать в голове все запросы и какие они связи образуют.
И опять это зависит от того, как вы пишете этот SQL. В чистом SQL, написанном в процедурном стиле — именно так. Понять, нужно ли контролировать доступ к какой-либо сущности по таблице разрешений, можно только путём вдумчивого копания в текстах параметризованных view и хранимых процедур.
В рамках полноценного фреймворка вроде Linq вы видите эти связи прямо на уровне деклараций.

NL>4. По тому коду, что вы привели — крайне сложно отслеживать зависимости между сущностями. Вот CheckPermissions я вижу использует items и Users. Но то что он использует Permissions можно догадаться только из названия. А если я добавляю еще одну зависимость мне что метод переименовывать? Хочется верить, что нет.

Что здесь вы называете "сущностями"? То, что хранится в базе? Или те объекты, которые реализуют бизнес-логику?
В нашем примере есть некоторая реализация интерфейса IAccessPolicy (которого мы выделяем только если это вообще нужно — в простых моделях такой нужды нет, и можно просто реализовывать CheckPermissions как метод-расширение к DatabaseContext). Напимер, ACLBasedAccessPolicy. У неё будет вполне явная зависимость от IQueryable<Permission> Permissions.
У какой-то другой реализации IAccessPolicy такой зависимости может и не быть — это не свойство модели данных, а свойство бизнес-логики. Которая сегодня — одна, а завтра — совсем другая (например, заменяем ACL на RBAC).

NL>5. Тесты вы как пишите? Они у вас быстрые? Или тесты для слабаков? \

А что именно вы хотите тестировать? Видите ли, когда вы врукопашную велосипедите стандартный набор репозиториев и прочего хлама, вам придётся тестировать код репозиториев и прочего хлама.
Когда вы пишете код в указанном стиле, вам не нужно тестировать linq2db — его тестируют другие люди. Вам нужно только протестировать, что результатом конкретной реализации IAccessPolicy.CheckPermissions является наложение требуемого предиката.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.