EntityFramework: (анти)паттерн Repository
От: Shmj Ниоткуда  
Дата: 18.08.17 03:55
Оценка: +1
Приглашаю высказать свое фи: https://habrahabr.ru/post/335856/
Re: EntityFramework: (анти)паттерн Repository
От: igor-booch Россия  
Дата: 18.08.17 09:26
Оценка:
Применение спецификаций не исключает использование Repository, можно и то и другое использовать. Только в этом случае спецификации должны быть инкапсулированы в Repository.
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания
http://rsdn.ru/Info/rules.xml
Отредактировано 18.08.2017 11:58 igor-booch . Предыдущая версия . Еще …
Отредактировано 18.08.2017 11:56 igor-booch . Предыдущая версия .
Re: EntityFramework: (анти)паттерн Repository
От: Danchik Украина  
Дата: 18.08.17 13:16
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Приглашаю высказать свое фи: https://habrahabr.ru/post/335856/


Практически со всем согласен. Спецификации, сомнительно, опять черт ногу в дебаге сломает.
Re: EntityFramework: (анти)паттерн Repository
От: hardcase Пират http://nemerle.org
Дата: 18.08.17 15:20
Оценка: +1
Здравствуйте, Shmj, Вы писали:

S>Приглашаю высказать свое фи: https://habrahabr.ru/post/335856/


https://developerslife.ru/8729
/* иЗвиНите зА неРовнЫй поЧерК */
Re: EntityFramework: (анти)паттерн Repository
От: Vladek Россия Github
Дата: 20.08.17 22:07
Оценка: 4 (1)
Здравствуйте, Shmj, Вы писали:

S>Приглашаю высказать свое фи: https://habrahabr.ru/post/335856/


Прочитал по диагонали. Подход знаком, это просто очень тонкая обёртка на ORM. Надо либо перестать стесняться и использовать ORM везде напрямую или прятать его глубже. Обёртка — это просто лишний код, который только мешается. В статье TL;DR написан правильный, однако самой статье он противоречит.

Использую следующий подход и написанный код продолжает мне нравится даже недели и месяцы спустя после написания.

Репозитории хранят главные объекты предметной области (агрегаты) между запусками программы. Агрегаты достаются из репозитория только для внесения изменений (запись). Агрегаты сами себя умеют записывать в бд или куда им это надо. Для чтения вся эта лабуда не используется, а используются шлюзы, возвращающие простые структуры данных, пригодные для показа пользователю, отправке через сеть, ещё куда; самые настоящие DTO, они же Model в MVC-фреймворье.

ORM используется на самом нижнем уровне, не вылезая за пределы репозиториев, шлюзов и конкретных экземпляров агрегатов (наследников знающих про ORM). Никакие IQueryable наружу не торчат, каждый LINQ-запрос к ORM встречается один раз и весь сразу, ничего там позже динамически не подгружается, не модифицируется, никаких сюрпризов. Вот запрос, с любыми нужными джойнами и условиями, вот его результат здесь же маппится в DTO или ещё как используется. Не нужно запускать отладчик и прыгать по всему проекту, выясняя почему запрос не такой как надо.

Писал я про этот подход тут много раз (последний раз тут: http://rsdn.org/forum/design/6817203.1
Автор: Vladek
Дата: 21.06.17
), по дурости вступая в споры с какими-то людьми, кода которых я не видел и они сами его не показывали. Нет кода, нечего и обсуждать. Простой пример описанного подхода (без модели предметной области, только шлюзы): https://github.com/vborovikov/rsdn

Весь код работы с бд тут: https://github.com/vborovikov/rsdn/tree/master/src/RsdnFoundation/Client/Data (и наружу не торчит, все классы ORM internal).

Подход позволяет одним относительно небольшим коммитом совершать подобные эксперименты: http://rsdn.org/forum/dotnet/6872443.1
Автор: Vladek
Дата: 14.08.17
Re[2]: EntityFramework: (анти)паттерн Repository
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 21.08.17 19:40
Оценка: +3
Здравствуйте, Vladek, Вы писали:

V>Репозитории хранят главные объекты предметной области (агрегаты) между запусками программы.


Почему главные объекты предметной области обязательно агрегаты?

V> Агрегаты достаются из репозитория только для внесения изменений (запись).


Зачем что то сперва доставать для внесения изменений?

V> Агрегаты сами себя умеют записывать в бд или куда им это надо.


Поштучно?

V> Для чтения вся эта лабуда не используется, а используются шлюзы, возвращающие простые структуры данных, пригодные для показа пользователю, отправке через сеть, ещё куда; самые настоящие DTO, они же Model в MVC-фреймворье.


А если вдруг транзакция и на чтение и на запись вместе?

V>ORM используется на самом нижнем уровне, не вылезая за пределы репозиториев, шлюзов и конкретных экземпляров агрегатов


Т.е. на каждую операцию дравствую полная тележка boilerplate кода?

V>Никакие IQueryable наружу не торчат, каждый LINQ-запрос к ORM встречается один раз и весь сразу


Т.е. на каждый запрос заводим как минимум один метод?
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[3]: EntityFramework: (анти)паттерн Repository
От: Vladek Россия Github
Дата: 22.08.17 14:17
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, Vladek, Вы писали:


V>>Репозитории хранят главные объекты предметной области (агрегаты) между запусками программы.


AVK>Почему главные объекты предметной области обязательно агрегаты?


Потому что, как правило, они моделируют некую относительно сложную сущность, состоящую из отдельных малых частей. Следовательно, агрегат.

V>> Агрегаты достаются из репозитория только для внесения изменений (запись).


AVK>Зачем что то сперва доставать для внесения изменений?


Я использую фабрики или оператор new, чтобы создать объект, которого раньше не существовало, и репозитории, чтобы достать объект, который уже где-то есть. Это просто, это логично, это работает.

V>> Агрегаты сами себя умеют записывать в бд или куда им это надо.


AVK>Поштучно?


Поштучно, с помощью репозитория пучком если именно так надо.

V>> Для чтения вся эта лабуда не используется, а используются шлюзы, возвращающие простые структуры данных, пригодные для показа пользователю, отправке через сеть, ещё куда; самые настоящие DTO, они же Model в MVC-фреймворье.


AVK>А если вдруг транзакция и на чтение и на запись вместе?


Радуюсь, что мне никогда такое не встречалось. Нужен конкретный пример, где действия пользователя нельзя чётко разделить на запросы и команды.

V>>ORM используется на самом нижнем уровне, не вылезая за пределы репозиториев, шлюзов и конкретных экземпляров агрегатов


AVK>Т.е. на каждую операцию дравствую полная тележка boilerplate кода?

AVK>Т.е. на каждый запрос заводим как минимум один метод?

Стереотипный код писать я тоже не люблю. Любой репозиторий и любой объект предметной области использует ORM целиком и делает столько запросов сколько ему надо. Мне важнее другое — вот папка, где лежит код работы с ORM. Я могу его прочитать весь сразу, я могу его поменять как угодно, и мне не надо особо трогать файлы и классы за пределами этой папки.
Re[4]: EntityFramework: (анти)паттерн Repository
От: sergeya Ниоткуда http://blogtani.ru
Дата: 22.08.17 15:04
Оценка: +4
Здравствуйте, Vladek, Вы писали:

V>>> Агрегаты достаются из репозитория только для внесения изменений (запись).

AVK>>Зачем что то сперва доставать для внесения изменений?
V>Я использую фабрики или оператор new, чтобы создать объект, которого раньше не существовало, и репозитории, чтобы достать объект, который уже где-то есть. Это просто, это логично, это работает.

Но вопрос то был в другом. Неужели тяжелые ORM так затуманивают взгляд, что даже очевидные проблемы ускользают от внимания?

Теперь я кажется понял, почему в соседнем топике не захотели видеть проблему в том, что ради одного поля из БД достается целая сущность.
Пользователи тяжелых ОРМ похоже просто не понимают, что можно сделать иначе.
Мобильная версия сайта RSDN — http://rsdn.org/forum/rsdn/6938747
Автор: sergeya
Дата: 19.10.17
Re[5]: EntityFramework: (анти)паттерн Repository
От: Vladek Россия Github
Дата: 23.08.17 06:09
Оценка:
Здравствуйте, sergeya, Вы писали:

S>Здравствуйте, Vladek, Вы писали:


V>>>> Агрегаты достаются из репозитория только для внесения изменений (запись).

AVK>>>Зачем что то сперва доставать для внесения изменений?
V>>Я использую фабрики или оператор new, чтобы создать объект, которого раньше не существовало, и репозитории, чтобы достать объект, который уже где-то есть. Это просто, это логично, это работает.

S>Но вопрос то был в другом. Неужели тяжелые ORM так затуманивают взгляд, что даже очевидные проблемы ускользают от внимания?

S>Теперь я кажется понял, почему в соседнем топике не захотели видеть проблему в том, что ради одного поля из БД достается целая сущность.

А как ты видишь эту проблему? Запускаешь профайлер, видишь по логам проседание производительности? Пользователи жалуются? Или тебе просто кажется, что вот этот кусок кода "неэффективный"? Если последнее, то рекомендую пить успокоительное. Если другое — код конечно надо переписывать. Ниже выделено жирным — почему.

S>Пользователи тяжелых ОРМ похоже просто не понимают, что можно сделать иначе.

Можно делать как угодно. Руководствоваться надо здравым смыслом. Ни один подход не работает везде.

Смысл использования фабрик и репозиториев в создании переносимого ядра приложения. Под переносимостью я тут понимаю способность написанного кода работать в разных окружениях — в вебе, в консоли, на десктопе, в службе на сервере. Детали реализации будут меняться, а бизнес-логика (код в ядре) будет оставаться прежним.
Re[6]: EntityFramework: (анти)паттерн Repository
От: Sinclair Россия https://github.com/evilguest/
Дата: 23.08.17 06:57
Оценка: +5 -1
Здравствуйте, Vladek, Вы писали:

V>А как ты видишь эту проблему? Запускаешь профайлер, видишь по логам проседание производительности? Пользователи жалуются? Или тебе просто кажется, что вот этот кусок кода "неэффективный"? Если последнее, то рекомендую пить успокоительное.

)
Вот, к примеру, какое-нибудь матёрое приложение выполняет апгрейд базы со старой на новую версию 30 часов у кастомера приличного объёма. Вице-президент волевым усилием выдвигает требование: "вы должны уложиться в 8 часов!"
Ну, потому что инженерам поддержки неудобно, когда апгрейд начинает одна смена, а заканчивает другая.
Профайлер, есессно, никто не подключает — к чему его подключать? Мы и так знаем, чем занимается система — поднимаем объекты в память, подправляем, записываем обратно. И так 20 миллионов раз.
Пользователи — не жалуются. "Чо ж вы хотели — 30 гигов, как-никак!" Сравнить им, бедняжкам, не с чем — переезд на другую систему будет стоить полгода и пару миллионов долларов. Не то, чем хочется заняться в выходные.

В итоге инженеры, поохав про то, что "ну никак невозможно! Мы там процентов 10 сможем отжать, и всё!" выкидывают нахрен ORM из апгрейд-процесса, аккуратно переписывают всё на SQL, и апгрейд укладывается в 1 час 40 минут.
Конечно, после такого приходится пить успокоительное. Ну, чтоб в табло не заехать тем, кто уверял про "никак невозможно".

V>Смысл использования фабрик и репозиториев в создании переносимого ядра приложения. Под переносимостью я тут понимаю способность написанного кода работать в разных окружениях — в вебе, в консоли, на десктопе, в службе на сервере. Детали реализации будут меняться, а бизнес-логика (код в ядре) будет оставаться прежним.

Проект, в котором было нужно переносить бизнес-логику между сервером, десктопом, и консолью, я встречал в последний раз... дайте вспомнить... ага, точно: никогда.
Я системы автоматизации бизнеса за деньги, если чо, пишу с 1991 года. Работал и в бодишопе, где каждые два месяца — новый проект. То есть не то, чтобы у одного станка 25 лет простоял.
Всё жду: может встретится когда-нибудь такая штука?

А вот неэффективностей на ровном месте я встречаю ежедневно.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: EntityFramework: (анти)паттерн Repository
От: Vladek Россия Github
Дата: 23.08.17 08:00
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Vladek, Вы писали:


V>>А как ты видишь эту проблему? Запускаешь профайлер, видишь по логам проседание производительности? Пользователи жалуются? Или тебе просто кажется, что вот этот кусок кода "неэффективный"? Если последнее, то рекомендую пить успокоительное.

S>)
S>Вот, к примеру, какое-нибудь матёрое приложение выполняет апгрейд базы со старой на новую версию 30 часов у кастомера приличного объёма. Вице-президент волевым усилием выдвигает требование: "вы должны уложиться в 8 часов!"
S>Ну, потому что инженерам поддержки неудобно, когда апгрейд начинает одна смена, а заканчивает другая.
S>Профайлер, есессно, никто не подключает — к чему его подключать? Мы и так знаем, чем занимается система — поднимаем объекты в память, подправляем, записываем обратно. И так 20 миллионов раз.
S>Пользователи — не жалуются. "Чо ж вы хотели — 30 гигов, как-никак!" Сравнить им, бедняжкам, не с чем — переезд на другую систему будет стоить полгода и пару миллионов долларов. Не то, чем хочется заняться в выходные.

S>В итоге инженеры, поохав про то, что "ну никак невозможно! Мы там процентов 10 сможем отжать, и всё!" выкидывают нахрен ORM из апгрейд-процесса, аккуратно переписывают всё на SQL, и апгрейд укладывается в 1 час 40 минут.

S>Конечно, после такого приходится пить успокоительное. Ну, чтоб в табло не заехать тем, кто уверял про "никак невозможно".

И что? Я тут должен защищать использование ORM? Я уже написал, повторяю:

Можно делать как угодно. Руководствоваться надо здравым смыслом. Ни один подход не работает везде.


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

V>>Смысл использования фабрик и репозиториев в создании переносимого ядра приложения. Под переносимостью я тут понимаю способность написанного кода работать в разных окружениях — в вебе, в консоли, на десктопе, в службе на сервере. Детали реализации будут меняться, а бизнес-логика (код в ядре) будет оставаться прежним.

S>Проект, в котором было нужно переносить бизнес-логику между сервером, десктопом, и консолью, я встречал в последний раз... дайте вспомнить... ага, точно: никогда.

А я встречал. Зато никогда не приходилось возиться с бд в 30 Гб. Делает это мой опыт менее ценным? Нет, не думаю — кому-то пригодится. Делает это твой опыт более ценным — не знаю, ты им не делишься.

Show me the source.


S>Я системы автоматизации бизнеса за деньги, если чо, пишу с 1991 года. Работал и в бодишопе, где каждые два месяца — новый проект. То есть не то, чтобы у одного станка 25 лет простоял.

S>Всё жду: может встретится когда-нибудь такая штука?

У тебя код программ в публичном доступе есть? Почитаю на досуге, поучусь у мэтра.

S>А вот неэффективностей на ровном месте я встречаю ежедневно.


В коде я в первую очередь стараюсь уменьшить сложность, тогда и с неэффективностью бороться легче будет.
Re[8]: EntityFramework: (анти)паттерн Repository
От: Sinclair Россия https://github.com/evilguest/
Дата: 23.08.17 09:29
Оценка: +1
Здравствуйте, Vladek, Вы писали:

V>И что? Я тут должен защищать использование ORM?

Не, не должен.
V>Предлагаешь подход к архитектуре типичного корпоративного софта, вылезают какие-то ветераны, начинают критиковать, ничего интересного взамен не предлагают, кода своего почитать не дают. Что я должен полезного из этого извлечь? Ничего я не извлекаю.
Эпик срач Рич vs Анемик поднимается тут каждые три года. Лично я все "взамен" привёл ещё в предыдущих двух, в третий раз уже не хватает усердия.
V>А я встречал. Зато никогда не приходилось возиться с бд в 30 Гб. Делает это мой опыт менее ценным? Нет, не думаю — кому-то пригодится. Делает это твой опыт более ценным — не знаю, ты им не делишься.
Ну почему же не делюсь? Делюсь. Вот прямо в топике и делюсь. Подобных историй я могу привести не одну.
V>У тебя код программ в публичном доступе есть? Почитаю на досуге, поучусь у мэтра.
Нет, я работаю за деньги. Мои труды никто в open source пока не переводит.
S>>А вот неэффективностей на ровном месте я встречаю ежедневно.
V>В коде я в первую очередь стараюсь уменьшить сложность, тогда и с неэффективностью бороться легче будет.
Это хорошо. Но заменить код, написанный через "агрегаты" и Lazy Load (ну, это где User сам себе скидку начисляет и письмо отправляет по SMTP) на нормальный — очень тяжко.
Единственный плюс в такой "компактной бизнес-логике" — в том, что её не так жалко выкидывать, когда целый кусок переезжает в анемик.
Ну, как в примере с инсталлятором апдейта — там кода, который тратил 90% времени, было совсем немного.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: EntityFramework: (анти)паттерн Repository
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 23.08.17 18:00
Оценка:
Здравствуйте, Vladek, Вы писали:

AVK>>Почему главные объекты предметной области обязательно агрегаты?

V>Потому что, как правило, они моделируют некую относительно сложную сущность, состоящую из отдельных малых частей. Следовательно, агрегат.

А как быть с SRP?

AVK>>Зачем что то сперва доставать для внесения изменений?

V>Я использую фабрики или оператор new, чтобы создать объект, которого раньше не существовало, и репозитории, чтобы достать объект, который уже где-то есть.

Вопрос был в том зачем это делать, если нужно внести изменения.

V> Это просто, это логично, это работает.


Считывать данные из БД чтобы их поменять? Нет, это совсем не логично и не просто.

V>>> Агрегаты сами себя умеют записывать в бд или куда им это надо.

AVK>>Поштучно?
V>Поштучно, с помощью репозитория пучком если именно так надо.

Подожди. Вот есть у тебя предикат, по которому, к примеру, надо изменить определенное поле. Т.е. нужны, в итоге, примерно такие запросы:
UPDATE Log SET DeletedOn = GETDATE() WHERE CreatedOn < DATEADD(-30, D, GETDATE())
...
UPDATE Tasks SET CaptureCount = CaptureCount + 3 WHERE Type = 4

Как это выразить в твоей модели?

AVK>>А если вдруг транзакция и на чтение и на запись вместе?

V>Радуюсь, что мне никогда такое не встречалось.

Ээээ, я вот даже не знаю как прокомментировать. Пожалуй, тогда вообще воздержусь.

V> Нужен конкретный пример, где действия пользователя нельзя чётко разделить на запросы и команды.


Списываем баланс с одного счета, начисляем на другой. Последовательность действий: считать операции по исходному счету, просуммировать, получить баланс, вычислить корректирующую сумму, записать сумму с минусом на старый счет, с плюсом на новый. Все, разумеется, в одной транзакции. Вычисление баланса, разумеется, нужно более чем в одном месте.
Достаточно конкретный пример или еще что то уточнить нужно?

AVK>>Т.е. на каждую операцию дравствую полная тележка boilerplate кода?

AVK>>Т.е. на каждый запрос заводим как минимум один метод?
V>Стереотипный код писать я тоже не люблю.

Зачем тогда советуешь? Особенно это касается рассказов про CQRS, чтоб Фаулеру икалось.

V> Мне важнее другое — вот папка, где лежит код работы с ORM. Я могу его прочитать весь сразу, я могу его поменять как угодно, и мне не надо особо трогать файлы и классы за пределами этой папки.


Зато появляется стадо контрактов, которое таки влияет на остальной проект. А, учитывая что все нормальные ORM умеют работать с POCO, получается куча развлечений по написанию кода без какого либо смыслового наполнения. Зато красивого и простого, да.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[5]: EntityFramework: (анти)паттерн Repository
От: Vladek Россия Github
Дата: 24.08.17 16:03
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, Vladek, Вы писали:


AVK>>>Почему главные объекты предметной области обязательно агрегаты?

V>>Потому что, как правило, они моделируют некую относительно сложную сущность, состоящую из отдельных малых частей. Следовательно, агрегат.

AVK>А как быть с SRP?


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

AVK>>>Зачем что то сперва доставать для внесения изменений?

V>>Я использую фабрики или оператор new, чтобы создать объект, которого раньше не существовало, и репозитории, чтобы достать объект, который уже где-то есть.
AVK>Вопрос был в том зачем это делать, если нужно внести изменения.

Чтобы модель предметной области проявила своё поведение. Другими словами, чтобы отработала бизнес-логика. Если вся суть работы приложения заключается в изменение таблиц БД, то это просто накопление данных и тогда действительно модель предметной области не нужна. если бизнес-логика есть, я оформляю её в виде модели предметной области.

V>> Это просто, это логично, это работает.


AVK>Считывать данные из БД чтобы их поменять? Нет, это совсем не логично и не просто.


Пробуждаем модель предметной области (загружаем её состояние в оперативную память из бд), отрабатываем нужное поведение (записываем изменённое состояние из оперативной памяти в бд).

V>>>> Агрегаты сами себя умеют записывать в бд или куда им это надо.

AVK>>>Поштучно?
V>>Поштучно, с помощью репозитория пучком если именно так надо.

AVK>Подожди. Вот есть у тебя предикат, по которому, к примеру, надо изменить определенное поле. Т.е. нужны, в итоге, примерно такие запросы:

AVK>
AVK>UPDATE Log SET DeletedOn = GETDATE() WHERE CreatedOn < DATEADD(-30, D, GETDATE())
AVK>...
AVK>UPDATE Tasks SET CaptureCount = CaptureCount + 3 WHERE Type = 4
AVK>

AVK>Как это выразить в твоей модели?

Что мы здесь моделируем, какая бизнес-задача? Ты рассуждаешь об изменении бд — ну так и отобрази это в коде — выполни нужные запросы к серверу бд и дело с концом. Чем проще, тем лучше. Я повторюсь, если решение задачи выглядит как набор скриптов для бд — надо написать скрипты и больше с задачей не возиться.

AVK>>>А если вдруг транзакция и на чтение и на запись вместе?

V>>Радуюсь, что мне никогда такое не встречалось.

AVK>Ээээ, я вот даже не знаю как прокомментировать. Пожалуй, тогда вообще воздержусь.


V>> Нужен конкретный пример, где действия пользователя нельзя чётко разделить на запросы и команды.


AVK>Списываем баланс с одного счета, начисляем на другой. Последовательность действий: считать операции по исходному счету, просуммировать, получить баланс, вычислить корректирующую сумму, записать сумму с минусом на старый счет, с плюсом на новый. Все, разумеется, в одной транзакции. Вычисление баланса, разумеется, нужно более чем в одном месте.

AVK>Достаточно конкретный пример или еще что то уточнить нужно?

Уточнять можно бесконечно. Счета могут быть в разных банках, записи в разных хранилищах. Блокируются ли операции по счёту пока выполняется перевод или нет. И так далее. Задача модели предметной области всё это явно выразить в коде, только и всего. Универсального подхода нет, я вообще рассуждаю о обычном ООП.

public void Transfer(Account other, decimal amount)
{
  // вот у нас два объекта Account: this и other.
  // тут мы запускаем транзакцию
  // считываем историю операций
  // считаем баланс
  // добавляем новые операции
  // завершаем транзакцию
}


Чего тут такого сакрального, что перечёркивает мои потуги к решению задачи на нет?

AVK>>>Т.е. на каждую операцию дравствую полная тележка boilerplate кода?

AVK>>>Т.е. на каждый запрос заводим как минимум один метод?
V>>Стереотипный код писать я тоже не люблю.

AVK>Зачем тогда советуешь? Особенно это касается рассказов про CQRS, чтоб Фаулеру икалось.


Советуй другое.

V>> Мне важнее другое — вот папка, где лежит код работы с ORM. Я могу его прочитать весь сразу, я могу его поменять как угодно, и мне не надо особо трогать файлы и классы за пределами этой папки.


AVK>Зато появляется стадо контрактов, которое таки влияет на остальной проект. А, учитывая что все нормальные ORM умеют работать с POCO, получается куча развлечений по написанию кода без какого либо смыслового наполнения. Зато красивого и простого, да.


Я не использую POCO объекты для ORM в качестве модели предметной области. Раньше я так делал и это был говно-код, который очень быстро начинал вонять по мере развития проекта. Больше я такой говно-код не пишу и другим не советую.

Модель предметной области для реализации бизнес-логики и простые структуры данных для отображения пользователю — вот такой код мне удобнее всего (и получается короче).
Re: EntityFramework: (анти)паттерн Repository
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 24.08.17 18:18
Оценка: +4
Здравствуйте, Shmj, Вы писали:

S>Приглашаю высказать свое фи: https://habrahabr.ru/post/335856/


Подобные статьи появляются с периодичностью раз в полгода.
И эти идеи всегда натыкаются на одни и те же грабли.

Грабля номер раз: проекция. Если твой метод возвращает IEnumerable<T>, где T — сущность замапленная на таблицу, то твой код — тормозное говно. Мало того, что на каждое обращение тянутся целые объекты, так и еще и проблемы возникают когда надо вывести список заказов с именами и адресами клиентов.

Грабля номер два: композиция. Очень наивно думать, что все запросы будут по id или фильтром по одному полю. В приложении постоянно появляются дополнительные условия фильтрации. Даже для блогов надо показывать\скрывать неопубликованные посты и комментарии, а в реальных бизнес-приложениях еще и права пользователей учитывать надо. По факту в процессе развития приложения запросы постоянно усложняются (я не видел чтобы было по-другому) поэтому нужен удобный способ собирать запрос по кускам, чтобы в нужном месте можно было добавить предикаты.

Грабля номер три, она появится сразу после решения двух проблем выше: вы изобретаете свой IQueryable. Все что вы хотите уже есть в EF и других ORM. Изобретение того же, но своего нужно только с одной целью — понять что так делать не стоит.
Re[2]: EntityFramework: (анти)паттерн Repository
От: Shmj Ниоткуда  
Дата: 24.08.17 19:14
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Грабля номер раз: проекция. Если твой метод возвращает IEnumerable<T>, где T — сущность замапленная на таблицу, то твой код — тормозное говно.


А где там IEnumerable<T>?

Первый предлагаемый автором способ возвращает Expression<Func<T, bool>>, второй -- IQueryable<Comment>
Re[3]: EntityFramework: (анти)паттерн Repository
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 24.08.17 22:14
Оценка:
Здравствуйте, Shmj, Вы писали:

S>А где там IEnumerable<T>?

S>Первый предлагаемый автором способ возвращает Expression<Func<T, bool>>, второй -- IQueryable<Comment>

Это я про repository. Хотя в статье он упоминается как анти-паттрен.
Re[4]: EntityFramework: (анти)паттерн Repository
От: Shmj Ниоткуда  
Дата: 25.08.17 06:24
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Это я про repository. Хотя в статье он упоминается как анти-паттрен.


Вот именно. А по предложенным методикам статьи что можете сказать?
Re[7]: EntityFramework: (анти)паттерн Repository
От: Max Mustermann  
Дата: 25.08.17 10:58
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Профайлер, есессно, никто не подключает — к чему его подключать? Мы и так знаем, чем занимается система — поднимаем объекты в память, подправляем, записываем обратно. И так 20 миллионов раз.

S>Пользователи — не жалуются. "Чо ж вы хотели — 30 гигов, как-никак!" Сравнить им, бедняжкам, не с чем — переезд на другую систему будет стоить полгода и пару миллионов долларов. Не то, чем хочется заняться в выходные.
S>В итоге инженеры, поохав про то, что "ну никак невозможно! Мы там процентов 10 сможем отжать, и всё!" выкидывают нахрен ORM из апгрейд-процесса, аккуратно переписывают всё на SQL, и апгрейд укладывается в 1 час 40 минут.
S>Конечно, после такого приходится пить успокоительное. Ну, чтоб в табло не заехать тем, кто уверял про "никак невозможно".

Какая прохладная история. Я-то думал, что "пишу всё на хранимках с 91-го — хорошо себя чуствую" уже перевелись, а подиж-ты, жива старая гвардия!
Если вкратце — то всё это хорошо для тех, кто сложнее northwind баз не пользовал. А если выглянуть за пределы уютненького, то внезапно(!) окажется, что в процессе "подправляем" еще нужны данные из друго источника, поднимаются какие-то тонны правил в WF и попутно вызываются пара библиотек, которые в движок БД не завезли. Упс.
Поэтому разговор с вменяемыми базовиками на эту тему обычно напоминает старый анекдот "ты сильный, ты сможешь — не, я умный, я даже не возьмусь". С невменяемыми примерно то же самое, но они сначала берут месяц-два на "аккуратно переписывают всё на SQL", потом много "пить успокоительное" и так трогательно заглядывая в глаза "а у вас нет более другой ORM, вот такой же, но быстнее? Смотрите, уже быстрее, на целых 10%! Вот видите, есть же, а говорили, что не сможете!.. А, ну да.".

Собсна весь конфликт вращается вокруг этого самого: люди, у которых вся "логика" помещается в "update where" не понимают проблем тех, у которых перед update запускается ядерный реактор.
Вобщем это два разных Шапиро и вместе им не сойтись.


Но вообще в треде на тему делать ли обёртки поверх EF богатая идея "выкидывают нахрен ORM и аккуратно переписывают всё на SQL" — это успех однозначно.
Re[8]: EntityFramework: (анти)паттерн Repository
От: Sinclair Россия https://github.com/evilguest/
Дата: 25.08.17 17:56
Оценка: +1
Здравствуйте, Max Mustermann, Вы писали:
MM>Если вкратце — то всё это хорошо для тех, кто сложнее northwind баз не пользовал. А если выглянуть за пределы уютненького, то внезапно(!) окажется, что в процессе "подправляем" еще нужны данные из друго источника, поднимаются какие-то тонны правил в WF и попутно вызываются пара библиотек, которые в движок БД не завезли. Упс.
Конкретно при апгрейде ситуация "надо слазить в другой источник" бывает крайне редко. И повычислять что-нибудь экзотическое тоже надо очень редко.

MM>Поэтому разговор с вменяемыми базовиками на эту тему обычно напоминает старый анекдот "ты сильный, ты сможешь — не, я умный, я даже не возьмусь". С невменяемыми примерно то же самое, но они сначала берут месяц-два на "аккуратно переписывают всё на SQL", потом много "пить успокоительное" и так трогательно заглядывая в глаза "а у вас нет более другой ORM, вот такой же, но быстнее? Смотрите, уже быстрее, на целых 10%! Вот видите, есть же, а говорили, что не сможете!.. А, ну да.".

Отлично, коллега. Я вижу, вы уже созрели для освоения современных инструментов, которые всё ещё вдесятеро быстрее, чем lazy load, но при этом не страдают ограничениями SQL.

MM>Собсна весь конфликт вращается вокруг этого самого: люди, у которых вся "логика" помещается в "update where" не понимают проблем тех, у которых перед update запускается ядерный реактор.

MM>Вобщем это два разных Шапиро и вместе им не сойтись.
Я бы посоветовал вам ознакомиться с linq2db. На тему схождения несходимого.
MM>Но вообще в треде на тему делать ли обёртки поверх EF богатая идея "выкидывают нахрен ORM и аккуратно переписывают всё на SQL" — это успех однозначно.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.