Re[6]: EntityFramework: (анти)паттерн Repository
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 25.08.17 22:16
Оценка:
Здравствуйте, Vladek, Вы писали:

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

V>Думать о SRP когда какой-то код уже написан.

А пока не написан, то фиг ли думать, трясти надо?

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


Вопрос в другом — зачем писать заведомо кривое при любых раскладах решение? И, кстати, чем активнее ты кладешь болт на SRP, тем труднее потом это все будет переписывать.

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

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

Чего?

V> Другими словами, чтобы отработала бизнес-логика.


Зачем для отрабатывания бизнес-логики читать ненужные данные?

V> Если вся суть работы приложения заключается в изменение таблиц БД

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>>Как это выразить в твоей модели?
V>Что мы здесь моделируем, какая бизнес-задача?

Да вроде все тривиально. В первом случае пометить записи в логе старше 30 дней удаленными. Во втором — увеличить количество захватов задач на единицу для типа 4. Никакой специфики БД, все в терминах предметной области.
Так будет решение, или опять витание в абстракциях без ответа на конкретный вопрос?

V> Ты рассуждаешь об изменении бд — ну так и отобрази это в коде — выполни нужные запросы к серверу бд и дело с концом.


Я спрашиваю как предполагается это все делать у тебя.

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

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

Но ответа все равно не будет?

V>>>Стереотипный код писать я тоже не люблю.

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

Т.е. ответа опять нет.

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

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

Почму?

V>который очень быстро начинал вонять по мере развития проекта.


Конкретнее.

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


Приведи пример. Т.е. был такой говнокод на РОСО, потом ты его переписал и он стал вот таким вот прекрасным.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[8]: EntityFramework: (анти)паттерн Repository
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 25.08.17 22:21
Оценка: +2
Здравствуйте, Max Mustermann, Вы писали:

MM>Какая прохладная история. Я-то думал, что "пишу всё на хранимках с 91-го — хорошо себя чуствую" уже перевелись, а подиж-ты, жива старая гвардия!


А новая гвардия что делает? Пишет мегарешение, которое кушает 5 килобаксов в месяц за облако, выполняя при этом малую долю работы похожей системы, тратящей 1.5К в месяц? При том что и у второй системы не все идеально и с перфомансом, и с лишним бойлерплейтом.
Если что — это как раз реальный пример применения модных технологий и CQRS.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[7]: EntityFramework: (анти)паттерн Repository
От: Vladek Россия Github
Дата: 26.08.17 18:29
Оценка:
Здравствуйте, AndrewVK, Вы писали:

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


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

V>>Думать о SRP когда какой-то код уже написан.

AVK>А пока не написан, то фиг ли думать, трясти надо?


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


AVK>Вопрос в другом — зачем писать заведомо кривое при любых раскладах решение? И, кстати, чем активнее ты кладешь болт на SRP, тем труднее потом это все будет переписывать.


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

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

AVK>Чего?


V>> Другими словами, чтобы отработала бизнес-логика.


AVK>Зачем для отрабатывания бизнес-логики читать ненужные данные?


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

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

V>> Если вся суть работы приложения заключается в изменение таблиц БД

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

AVK>К чему эта абстракция? Вопрос был вполне конкретным — зачем что то читать, если задача стоит записать?


Максимально конкретно — пришёл запрос от пользователя что-то записать в бд. Надо проверить права пользователя, вдруг у него прав нет что-то менять. Права пользователя прописаны в той же бд. Будем слепо выполнять запрос пользователя или проверим его права сначала? Проверим, то есть загрузим профиль пользователя из бд, совершим операцию чтения, и уже решим выполнять запись или нет. Окей, у нас профиль пользователя в памяти висит, не надо ничего читать из бд. Выполняем проверку на права и решаем выполнять запись или нет.

Я всегда предполагаю, что в памяти у нас ничего нет, состояние программы перед выполнением операции надо полностью реконструировать. В самом первом посте этой бесполезной ветки я ответил на вопрос как я это делаю. Я отвечаю на вопрос откуда берётся профиль пользователя в памяти, как это оформляется в коде. Как часто программист будет читать профиль пользователя из бд — решает он сам, руководствуясь здравым смыслом.

Вот зачем что-то читать, перед тем как записать. Я ответил как создаются корневые объекты модели предметной области. Простые конструкторы, фабрики и репозитории. Ещё раз, создаются они обычно если их до этого в памяти не было. Как? Конструкторы, фабрики, репозитории. Когда — решает программист.

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

V>>Пробуждаем модель предметной области

AVK>Ты перешел к описанию решения. А я спрашивал про задачу.


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>>>Как это выразить в твоей модели?
V>>Что мы здесь моделируем, какая бизнес-задача?

AVK>Да вроде все тривиально. В первом случае пометить записи в логе старше 30 дней удаленными. Во втором — увеличить количество захватов задач на единицу для типа 4. Никакой специфики БД, все в терминах предметной области.

AVK>Так будет решение, или опять витание в абстракциях без ответа на конкретный вопрос?

V>> Ты рассуждаешь об изменении бд — ну так и отобрази это в коде — выполни нужные запросы к серверу бд и дело с концом.


AVK>Я спрашиваю как предполагается это все делать у тебя.


Создаём объект лога через фабрику или репозиторий. Вызываем у него метод Purge, который выполнит этот запрос UPDATE. Лог обновляет сам себя.

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

Чёрный ящик выполнил запрос UPDATE Log... Что должно быть в чёрном ящике?

С Tasks то же самое.

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

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

AVK>Но ответа все равно не будет?


Я надеюсь кто-нибудь другой найдёт в моей писанине рациональное зерно.

V>>>>Стереотипный код писать я тоже не люблю.

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

AVK>Т.е. ответа опять нет.


Тебе не нужны мои ответы. Ты прочитал мой первый пост в ветке, решил что это туфта — и написал свой пост. Но начал мутить воду наводящими вопросами. Лучше сразу писать что это всё туфта и по пунктам. Вдруг действительно туфта. Или показываешь какой-нибудь проект, свой или чужой, где репозитории и прочее приготовлены правильно. Это будет полезно хотя бы.
Re[8]: EntityFramework: (анти)паттерн Repository
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 27.08.17 09:05
Оценка:
Здравствуйте, Vladek, Вы писали:

AVK>>Зачем для отрабатывания бизнес-логики читать ненужные данные?

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

Спорно. Особенно весело с состоянием становится в кластерах. Прошли те времена, когда серверный софт работал на standalone серверах. Сейчас минимум пара машин просто для обеспечения минимальной надежности.

AVK>>К чему эта абстракция? Вопрос был вполне конкретным — зачем что то читать, если задача стоит записать?

V>Максимально конкретно — пришёл запрос от пользователя что-то записать в бд. Надо проверить права пользователя, вдруг у него прав нет что-то менять. Права пользователя прописаны в той же бд. Будем слепо выполнять запрос пользователя или проверим его права сначала? Проверим, то есть загрузим профиль пользователя из бд, совершим операцию чтения, и уже решим выполнять запись или нет. Окей, у нас профиль пользователя в памяти висит, не надо ничего читать из бд. Выполняем проверку на права и решаем выполнять запись или нет.

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

V>>> Ты рассуждаешь об изменении бд — ну так и отобрази это в коде — выполни нужные запросы к серверу бд и дело с концом.

AVK>>Я спрашиваю как предполагается это все делать у тебя.
V>Создаём объект лога через фабрику или репозиторий.

Непонятно. Что за объект лога? Уже появились какие то объекты, привязанные не к записи, а к таблице целиком?

V>С Tasks то же самое.


Покажи псевдокод. Словами непонятно.

V>Я надеюсь кто-нибудь другой найдёт в моей писанине рациональное зерно.


Кто ж его найдет, если ты сам не можешь ответить на простые и прямо поставленные вопросы?

AVK>>Т.е. ответа опять нет.

V>Тебе не нужны мои ответы.

Решил перейти на личности? Кончились аргументы? Не во мне причина того, что ты не можешь на вопросы ответить.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[9]: EntityFramework: (анти)паттерн Repository
От: Слава  
Дата: 27.08.17 09:36
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Спорно. Особенно весело с состоянием становится в кластерах.


Я давно хочу посмотреть на БД в кластере. И как это вообще делается?
Re[10]: EntityFramework: (анти)паттерн Repository
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 27.08.17 10:31
Оценка:
Здравствуйте, Слава, Вы писали:

AVK>>Спорно. Особенно весело с состоянием становится в кластерах.

С>Я давно хочу посмотреть на БД в кластере.

Облачныые БД все кластерные, бери да смотри.

С> И как это вообще делается?


Что именно?
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[11]: EntityFramework: (анти)паттерн Repository
От: Слава  
Дата: 27.08.17 12:03
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Облачныые БД все кластерные, бери да смотри.

С>> И как это вообще делается?
AVK>Что именно?

Мне непонятно, как БД, спроектированную для работы на одном сервере БД, растягивают на несколько серверов?

Насколько мне известно, существует ограниченное количество способов распределения нагрузки по БД:

1) Шардинг, партиционирование в общем виде — из некоего ключа можно вывести номер узла с БД, к которому следует обратиться с запросом. Как только запрос выходит за рамки одной таблицы, задача резко усложняется. Этот пункт применим ко всем нижележащим.
2) В мастер читают и пишут, всё это летит на реплику, если мастер помер — запросы переключаются на реплику. Не увеличивает скорость, повышает надёжность.
3) В мастер пишут, читают из одной или нескольких реплик. Повышает и скорость — частично, и надёжность.
4) Oracle RAC, работает непонятно как, стоит как самолёт.
5) Облако. Внезапно, в облаке обычные базы (не Oracle RAC) приобретают волшебную способность распределять нагрузку по узлам. Как они это делают, непонятно. Возможно и не делают, я не видел. Магия какая-то. Почему это стоит дешевле Oracle RAC, и нет ли тут каких недоговорённостей (а.к.а. хайпово-маркетинговая магия), тоже непонятно.
Re[12]: EntityFramework: (анти)паттерн Repository
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 27.08.17 12:25
Оценка:
Здравствуйте, Слава, Вы писали:

С>1) Шардинг, партиционирование в общем виде — из некоего ключа можно вывести номер узла с БД, к которому следует обратиться с запросом. Как только запрос выходит за рамки одной таблицы, задача резко усложняется. Этот пункт применим ко всем нижележащим.

С>2) В мастер читают и пишут, всё это летит на реплику, если мастер помер — запросы переключаются на реплику. Не увеличивает скорость, повышает надёжность.
С>3) В мастер пишут, читают из одной или нескольких реплик. Повышает и скорость — частично, и надёжность.
С>4) Oracle RAC, работает непонятно как, стоит как самолёт.
С>5) Облако. Внезапно, в облаке обычные базы (не Oracle RAC) приобретают волшебную способность распределять нагрузку по узлам. Как они это делают, непонятно. Возможно и не делают, я не видел. Магия какая-то. Почему это стоит дешевле Oracle RAC, и нет ли тут каких недоговорённостей (а.к.а. хайпово-маркетинговая магия), тоже непонятно.

Ну вот ты сам на все и ответил. Пачка NoSQL БД, ажуровский сторадж и сиквер при явном задании используют шардинг. Сиквел, кроме того, может и геореплики делать автоматично, и вручную настроенную синхронизацию.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[9]: EntityFramework: (анти)паттерн Repository
От: Vladek Россия Github
Дата: 27.08.17 12:53
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Решил перейти на личности? Кончились аргументы? Не во мне причина того, что ты не можешь на вопросы ответить.


Мы спорили? О чём? Какие твои аргументы? Где ты что-то утверждал? Кроме однотипных вопросов ничего не заметил.
Re[7]: EntityFramework: (анти)паттерн Repository
От: MadHuman Россия  
Дата: 27.08.17 19:32
Оценка:
Здравствуйте, AndrewVK, Вы писали:


AVK>Зачем для отрабатывания бизнес-логики читать ненужные данные?

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

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

под "так делать" имею ввиду наиболее часто применяемый способ (на своей практике) — работать через Entity и уже в самом классе Entity и реализованы эти правила проверки перед сохранением изменений в БД, а также и может быть бизнес-логика при присвоении в поля.
Re[8]: EntityFramework: (анти)паттерн Repository
От: Слава  
Дата: 27.08.17 20:07
Оценка:
Здравствуйте, MadHuman, Вы писали:

MH>делается что в объект представляющий запись поднимаются все поля записи.

MH>если конечно, когда мы пишем эту логику по обновлению мы точно знаем что проверять дополнительно ничего не придётся

То есть, требуется что-то вроде row level security, а то и какого-то механизма правил, но эти правила не представлены в БД, а прикрутили их потом, в коде, и объем их только растёт. И кто-то это должен поддерживать, а то и развивать.

Лучше, конечно, вообще не работать с подобными проектами и в подобных конторах. Пусть оно умрёт.
Re[9]: EntityFramework: (анти)паттерн Repository
От: MadHuman Россия  
Дата: 28.08.17 16:59
Оценка:
Здравствуйте, Слава, Вы писали:

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


MH>>делается что в объект представляющий запись поднимаются все поля записи.

MH>>если конечно, когда мы пишем эту логику по обновлению мы точно знаем что проверять дополнительно ничего не придётся

С>То есть, требуется что-то вроде row level security, а то и какого-то механизма правил, но эти правила не представлены в БД, а прикрутили их потом, в коде, и объем их только растёт. И кто-то это должен поддерживать, а то и развивать.


да.
код проверок — на языке программирования, со всеми вытекающими плюсами.
минус только в сценариях массового обновления, когда реально надо много данных заапдейтить. но к счастью обычно (на моей практике) кол-во таких сценариев относительно немного. но когда прижмет, что делать ведь ясно.

а вы предлагаете всё в базе на триггерах реализовать?
Re[10]: EntityFramework: (анти)паттерн Repository
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 28.08.17 18:43
Оценка:
Здравствуйте, MadHuman, Вы писали:

MH>код проверок — на языке программирования, со всеми вытекающими плюсами.


А если проверка затрагивает большой объем данных? Все равно все вычитываем? Или можно уже что то в БД оставить, и вытаскивать запросом только результат?
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[8]: EntityFramework: (анти)паттерн Repository
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 28.08.17 19:00
Оценка:
Здравствуйте, MadHuman, Вы писали:

AVK>>Зачем для отрабатывания бизнес-логики читать ненужные данные?

MH>это могут быть примерно такие случаи: мы пишем логику по обновлению чего-то.
MH>но перед сохранением изменений, должны отработать разные правила проверок. эти правила проверок и могут использовать другие данные (поля)
MH>из обновляемой записи и даже из других записей. причём когда мы пишем нашу логику по обновлению, нам конечно не хочется думать ещё и
MH>обо всей логике этих проверок и тем более о их реализации. и в общем случае (тк мы не знаем какие там правила и какие им данные из записи понадобятся)
MH>делается что в объект представляющий запись поднимаются все поля записи.

Давай без абстракций. Вот свежий пример из одного из реальных продуктов (ненужные подробности убраны):
var packageTemplate =
    await db
        .PackageTemplates
        .Where(pt =>
            pt.Type == PackageType.Subsription
            && pt.DeletedDate == null
            && pt.Tag == activationInfo.Edition)
        .Select(pt => new { pt.Id, pt.PagesCount })
        .SingleOrDefaultAsync();

HttpServiceCode.AssertState(
    packageTemplate != null,
    "PackageTemplateNotFound",
    false,
    $"Internal error: package template for {activationInfo.Edition} subscription not found.");

var actQuery =
    db
        .Subscriptions
        .Where(s => s.SerialNumber == activationInfo.SerialNumber);

if (activationInfo.Limit > 1)
    HttpServiceCode.AssertArgument(
        !await actQuery.AnyAsync(s => s.UserId == userId),
        nameof(activationInfo.SerialNumber),
        "SerialNumberAlreadyUsedForUser",
        true);

HttpServiceCode.AssertArgument(
    await actQuery.CountAsync() < activationInfo.Limit,
    nameof(activationInfo.SerialNumber),
    activationInfo.Limit == 1
        ? "SerialNumberAlreadyUsed"
        : "SerialNumberActivationsExceeded",
    true);

db
    .BalanceLogs
    .Insert(() =>
        new BalanceLog
        {
            Id = Guid.NewGuid(),
            UserId = userId,
            ClientId = clientId,
            ObjectType = ObjectType.PackageTemplate,
            ObjectId = packageTemplate.Id,
            OperationType = OperationType.SubscriptionActivate,
            PagesCount = packageTemplate.PagesCount.GetValueOrDefault(),
            EndDate = activationInfo.ExpirationDate,
            CreatedDate = DateTime.UtcNow
        });

var subsId = Guid.NewGuid();
db
    .Subscriptions
    .Insert(() =>
        new FRSubscription
        {
            Id = subsId,
            CreatedOn = DateTime.UtcNow,
            SerialNumber = activationInfo.SerialNumber,
            UserId = userId
        });

Вот здесь имеют место быть три проверки, потом две записи. Но нигде ничего не вычитывается из БД сверх скалярных данных в минимально требуемом объеме. Как это будет выглядеть в пропагандируемом тут подходе? Можно псевдокод.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[9]: EntityFramework: (анти)паттерн Repository
От: MadHuman Россия  
Дата: 28.08.17 20:44
Оценка:
Здравствуйте, AndrewVK, Вы писали:


AVK>Давай без абстракций. Вот свежий пример из одного из реальных продуктов (ненужные подробности убраны):

AVK> ..... skip .....
AVK>Вот здесь имеют место быть три проверки, потом две записи. Но нигде ничего не вычитывается из БД сверх скалярных данных в минимально требуемом объеме. Как это будет выглядеть в пропагандируемом тут подходе? Можно псевдокод.

ну во первых, я не пропагандирую какой-то конкретный подход как единственный тру, я за справедливость)

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

//процедура импорта
//пропущены всякие подготовительные действия
var updatedFields = ... //массив имен обновляемых полей
foreach(var r in importedRows){
  var record=db.Get(r["id"]);
  foreach(var fname in updatedFields){
    record[fname] = r[fname];
  }
}

db.SaveChanges(); //тут и сработают предусмотренные для изменённых записей проверки
//конец процедуры



//проверки в классе Order, вызываются перед сохранением изменений (в недрах SaveChanges).
//Order может меняться: при сохранении изменений из ЮИ, при сохранении изменений от апи, при импорте изменений из файла, вариантов ЮИ-форм может быть много.
//и во всех этих случаях перед тем как сохранить надо проверить валидность нового состояния сущности.
public override void Validate(){
   //если заказ подтверждён - то должны быть заполнены поля номер, дата и приатачены все необходимые документы
  if (Status == OrderStatus.Accepted){
    if (Number == null)
      //для упрощения кода в примере - генерится исключение. в реальности возвращается ValidationResult с подробностями что не так. 
      throw new UserError("Не заполнен номер");
    if (Date == null)
      throw new UserError("Не заполнена дата");
    //и тд
  }
  
  //и тут ещё что-нибудь дохрена и не такого простого как выше, код логики может быть довольно сложный.
}
Re[11]: EntityFramework: (анти)паттерн Repository
От: MadHuman Россия  
Дата: 28.08.17 20:47
Оценка:
Здравствуйте, AndrewVK, Вы писали:

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


MH>>код проверок — на языке программирования, со всеми вытекающими плюсами.


AVK>А если проверка затрагивает большой объем данных? Все равно все вычитываем? Или можно уже что то в БД оставить, и вытаскивать запросом только результат?


вопрос риторический? конечно в таком случае лучше запросом.
Re[9]: EntityFramework: (анти)паттерн Repository
От: Au Австралия  
Дата: 29.08.17 02:13
Оценка: +1 -1
AVK>Давай без абстракций. Вот свежий пример из одного из реальных продуктов (ненужные подробности убраны):
AVK>...

Этот код покрыт юнит тестами? Можно их посмотреть (без ненужных подробностей разумеется)?
Отредактировано 29.08.2017 11:45 Au . Предыдущая версия .
Re: EntityFramework: (анти)паттерн Repository
От: IB Австрия http://rsdn.ru
Дата: 29.08.17 12:28
Оценка: +1 :)
Здравствуйте, Shmj, Вы писали:

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

Приставка "анти" не перед тем словом стоит, должна быть перед EF =)
Мы уже победили, просто это еще не так заметно...
Re[10]: EntityFramework: (анти)паттерн Repository
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 29.08.17 21:19
Оценка:
Здравствуйте, MadHuman, Вы писали:

MH>в твоем примере я невижу необходимости что-то менять.


Но если следовать советам топикстартера, то придется. Да даже без его советов, одного перехода от linq2db к EF уже хватит чтобы кучу вопросов вызвать.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[10]: EntityFramework: (анти)паттерн Repository
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 29.08.17 21:19
Оценка:
Здравствуйте, Au, Вы писали:

Au>Этот код покрыт юнит тестами?


Да.

Au> Можно их посмотреть (без ненужных подробностей разумеется)?


Нет. А зачем? Там ничего удивительного нет, прогоняются юзкейсы основные. И без подробностей все равно пользы от них не будет.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.