|
1338 / 918 / 264
Регистрация: 08.08.2014
Сообщений: 2,759
|
||||||
God object?14.07.2021, 15:07. Показов 5920. Ответов 8
Метки нет (Все метки)
Есть всем известный анти-паттерн 'god object'.
И есть типовые примеры реализации stateless-сервисов, например, для размещения логики API на уровень ниже контроллеров. И получается какой-нибудь:
И, по сути, хоть это лишь кусочек логики всего приложения, но это ведь всё равно god-object получается. Более того - состояния у него нет, а все методы полностью независимы друг от друга в плане реализации. Ну и при вызове из контроллера всегда создаётся 'InvoiceService' со всем методами, но в рамках конкретного вызова всегда используется лишь один из них. И с зависимостями, внедряемыми через DI, тоже получается не очень удобно, т.к. либо они внедряются вообще все сразу в конструкторе (хотя конкретному методу они могут быть и не нужны), либо надо их в явном виде в параметрах метода передавать. И дело даже не в каком-то абсолютном количестве методов (хотя и это тоже, т.к. класс получается гигантский), дело в сути, даже если там будет лишь два не связанных метода. И в плане контроля версий эти большие файлы не очень удобны. ---- Вероятно, опять ищу усложнения на ровном месте, но, может, есть какие-нибудь паттерны/подходы, которые позволяют всё это как-то разбить физически на отдельные файлы, и чтобы это в C# нормально вписывалось?
0
|
||||||
| 14.07.2021, 15:07 | |
|
Ответы с готовыми решениями:
8
Ошибка: Object reference not set to an instance of an object Передача строки из GridView: Object reference not set to an instance of an object Ошибка: annot add object with apartment model behavior to the application intrinsic object. |
|
1338 / 918 / 264
Регистрация: 08.08.2014
Сообщений: 2,759
|
|
| 15.07.2021, 09:47 [ТС] | |
|
Нагуглил интересный подход - CQS. Вглубь пока особо не разбирался, но найденные реализации на C# выглядят очень удобно:
1. Все DTO делятся на 4 типа: 1.1. Query + QueryResult. 1.2. Command + CommandResult. 2. Для каждого Query и каждого Command на сервере реализуется отдельный Handler. Реализуется в виде самостоятельного класса, который реализует логику только конкретного запроса/команды и использует только нужные ему зависимости. 3. Если правильно реализовать базовые классы/абстракции, то можно обойтись вообще без контроллеров. Т.е. они будут, но будут типовыми, их можно будет генерировать динамически при старте хоста и регистрировать через 'IApplicationFeatureProvider<ControllerF eature>'. Правда, если чуток глубже посмотреть, то в этом CQS много странных ограничений, которые вряд ли возможно соблюсти на реальных проектах, по крайней мере в .NET: 1. Команды не должны ничего возвращать, т.е 'void'. А как тогда вернуть ID созданной сущности? Или вернуть подробные результаты не пройденной валидации? 2. Команды - это стек записи/изменения. И заявляется, если я правильно понял, что читать данные они не должны. Но как можно обновить сущность в базе, предварительно не вычитав её из базы для анализа/сравнения? К тому же, часть методов обновления сущностей на этапе предварительной валидации, требуют запроса дополнительных данных из БД. 3. Ну и обозначенный в соседней теме сценарий большого расчёта, когда надо на сервер отправить большой пак данных для обработки и получить в ответ результаты. При этом ничто никуда не пишется и ничто ни откуда не считывается, никаких сущностей нет. Это просто обработка данных. Т.е. это и не команда на изменение, и не запрос. Однако, если на все эти странности не заморачиваться, то чисто для организации структуры проекта в виде кучки маленьких классов весьма удобный подход. Добавлено через 3 минуты Более того, вероятно можно будет сделать так, чтобы для обработчиков команд использовался EF, а для обработчиков запросов - Dapper поверх рукописных SQL-запросов. В рамках одного проекта.
0
|
|
|
800 / 583 / 207
Регистрация: 21.02.2019
Сообщений: 2,095
|
|
| 15.07.2021, 10:37 | |
|
kotelok,
.. была у меня такая мысль (не уверен, что она полностью соотносится с вашей темой) разбить сервисы на универсальные с одним методом типа Get (by id), Get (filtered), Save и т.д., а данные передавать в них одним универсальным DTO на все случаи жизни ... Это, разумеется, очень частная задача, но в большинстве случаев в документообороте табличная часть и инвойсов, и ТТН, и актов выполненных работ - подобная, только поля разные ... Т.е. заполнять в контроллере универсальную DTO, а тип документа передавать отдельным параметром в сервис .. Другое дело, этот универсальный объект DTO тоже может выродиться в god object ....
0
|
|
|
1338 / 918 / 264
Регистрация: 08.08.2014
Сообщений: 2,759
|
|
| 15.07.2021, 14:01 [ТС] | |
|
carrotik,
Я наоборот стараюсь уходить от любой универсальности, т.к. это кучи if-else/switch-case, смешивание логики, сложная поддержка и непредсказуемые последствия во внезапных местах при незначительных изменениях. И для каждого запроса - свой комплект DTO, даже если он на 99% пересекается с каким-нибудь уже существующим. Это разные части логики и если использовать общий DTO или, как я иногда видел, наследовать "больший" от "меньшего", то потом при внесении изменений приходится перетестировать и тот функционал по которому была задачу, и тот, что к задаче отношения не имеет, но использует те же DTO, которые чуток поменялись. Ну и измнение внешнего контракта у метода, по которому не было изменений, тоже странно выглядит.
0
|
|
|
2773 / 2073 / 386
Регистрация: 22.07.2011
Сообщений: 7,820
|
|||||
| 15.07.2021, 20:00 | |||||
Сообщение было отмечено kotelok как решение
Решение
kotelok, можно команды делать , как выше написали . но когда становится 100500 команд , их иной раз удобно обьединить по смысловой нагрузке в один сервис , сами сервисы можно так же дробить на множество сервисов , в каждом набор команд обьедененных концепцией/зоной ответственности , грубо говоря QueryServiceA-B-C и CommandServiceA-B-C
Добавлено через 12 минут
в общем это все условно , основной посыл CQRS - не мешать в одной функции изменение данных и запрос данных. , и в целом эту концепцию можно масштабировать до уровня микросервисов , когда одни сервисы выполняют запросы , а другие команды.
1
|
|||||
|
1338 / 918 / 264
Регистрация: 08.08.2014
Сообщений: 2,759
|
|||
| 15.07.2021, 21:28 [ТС] | |||
|
С запретом на запись из 'Query' всё ок - даже при обычных хаотичных реализациях такого никто не делает. А вот почти все запросы на обновление данных, что у меня есть, так или иначе в процессе своей работы данные получают (и из хранилища, и от сторонних сервисов), т.к. на этом основана и логика проверок, и принимаемые командой решения. Но даже если так, обработчика команды для сохранения данных использует репозиторий, которые реализован через EF, а через EF весьма удобно использовать отслеживание изменений для оптимизации запросов к большим таблицам, а для этого EF запись вытягивает-таки из базы. Добавлено через 49 секунд Или допускается напрямую в CommandHandler заинжектить репозиторий/DAL, который умеет данные из хранилища получать в обход механизма Query?
0
|
|||
|
2773 / 2073 / 386
Регистрация: 22.07.2011
Сообщений: 7,820
|
||||||
| 17.07.2021, 10:17 | ||||||
|
kotelok,
да можно как угодно делать , главное что концепция команды соблюдается.
1
|
||||||
|
11 / 10 / 4
Регистрация: 27.01.2013
Сообщений: 15
|
|
| 23.07.2021, 16:09 | |
|
Если вернуться к первоначальному вопросу, то разбив логику god объект на более мелкие подсистемы(репозиорий, более специфичные сервисы), то в итоге InvoiceService уже будет реализовывать facade pattern
1
|
|
|
1338 / 918 / 264
Регистрация: 08.08.2014
Сообщений: 2,759
|
|
| 23.07.2021, 17:32 [ТС] | |
|
Epic,
Не, тут не об этом речь. Репозитории, доменные сущности/сервисы, инфраструктура - это, разумеется, всё отдельно в своих сборках и классах. Тут же вопрос был как отдельный сервис организовать внутри своего слоя, чтобы он не разрастался на 2000 строк. Собственно, подход через команды/запросы очень хорошо подошёл - и дерево проекта стало более информативное, и каждый класс отвечает только за свой маленький кусок функционала, и коммиты в гите читать проще, и риск конфликтов при коммите ниже. Ну и если вдруг потребуется, то в будущем это немного упростит физическое разделение систем чтения/записи.
0
|
|
| 23.07.2021, 17:32 | |
|
Помогаю со студенческими работами здесь
9
God Mode light scattering или god rays своими руками
Создать перечисляемый тип данных GOD – лето, осень, зима, весна Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
||||
|
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта
Симптом:
После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
|
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
|
Новый ноутбук
volvo 07.12.2025
Всем привет.
По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне:
Ryzen 5 7533HS
64 Gb DDR5
1Tb NVMe
16" Full HD Display
Win11 Pro
|
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
|
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
|
|
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов
На странице:
https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/
нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
|
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов.
. . .
|
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
|
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
|
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут.
В век Веб все очень привыкли к дизайну Single-Page-Application .
Быстренько разберем подход "на фреймах".
Мы делаем одну. . .
|