Информация об изменениях

Сообщение Re[16]: Entity Framework за! и против! от 18.08.2014 21:40

Изменено 18.08.2014 21:53 Vladek

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

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


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


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


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


V>>>>>>Это зона ответственности репозитория, а снаружи ничего не известно и потому одну реализацию легко заменить на другую.

G>>>>>Это в теории.

G>>>>>А на практике разберем пример, что все посты хранятся в текстовом файле. Для простоты будем считать, что все оценки и комменты также хранятся вместе с постами (чтобы согласованность изменений была).

G>>>>>И вот нам надо получить самые популярные посты за день. Для этого надо "всего лишь" пробежать по всем постам и посчитать оценку за день. Когда постов станет пару тысяч это перестанет работать.
G>>>>>Чтобы оно работало надо будет написать фоновый процесс, который при добавлении оценки будет считать оценку за день и обновлять список лучших постов.

V>>>>Нет, надо выбросить код с текстовыми файлами и написать код, работающий с БД.


G>>>Не понял фразы. Кому надо? Куда выбросить? Вот я тебе привет пример кода, который с субд работает. Ты предположил что репозиторий поможет "одну реализацию легко заменить на другую" и сам привел пример с файлами. В результате поменять субд на файлы окажется совсем нелегко, несмотря на репозитарии.


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

G>Файл на субд — легко, наоборот — нет. Слишком много надо написать, чтобы с помощью файлов отвечать на запросы как СУБД. То есть если ты начинаешь проект в котором будет работа с субд, то репозитарий не дает ничего.

G>>>>>Замена репозитария будет настолько маленькой проблемой, что её в этом контексте можно не рассматривать.

V>>>>Что изменится в контракте репозитория? Правильно, ничего.
G>>>
G>>>Даже если переписать весь контракт репозитария изменится 4-5 строк в методах, которые взывают этот репзитарий, по сравнению с написанием джоба по вычислению топовых постов, эти изменения не будут видны в микроскоп.

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

G>И что? Интересует не репозитарий, а его влияние на программу в целом. Пока что положительного влияния не было замечено.

G>>>>>Получается для того, чтобы "одну реализацию легко заменить на другую" нужно чтобы все стореджи поддерживали как минимум SQL, а это значит что они будут поддерживать Linq.

G>>>>>Тогда зачем прятать Linq внутри репозитария, если можно IQueryable<T> отдать потребителю, а специфичные вещи спрятать в комбинаторы.

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

G>>>Ну ок, сделай все что надо непосредственно перед отдачей во внешний мир (в рендеринг страницы). Зачем тебе репозиторий?
V>>Этим и занимается репозиторий — выборкой данных — дальше не его забота куда данные отправляются.
G>Это не является ответом на вопрос зачем он нужен. Ты можешь миллион классов придумать, со своими функциями, но это не оправдывает их существования.
G>Тем более реальной выборкой данных нанимается ORM, а репозиторий только обертка, которая ничего положительного не приносит в код.

Скрыть механизм хранения данных от других слоёв приложения. Репозиторий оперирует коллекциями объектов, описывающих предметную область программы. Его контракт свободен от деталей того, какая технология используется внутри него. Это позволяет писать простой код как внутри репозитория, так и снаружи его. Простой код означает, что я быстрее закончу свою работу сейчас и быстрее внесу изменения потом. Простой код — это свободное время, которое я трачу в собственное удовольствие и не думаю о неработающем коде или хитроумном баге.

V>>>>ORM отдают IQueryable внешнему миру, а мы не пишем ORM, мы пишем репозиторий. Для нашего ORM весь внешний мир ограничивается репозиторием. А это значит, пользователь репозитория не имеет доступа к объектам ORM, которые маппятся из БД — нечего выдавать в качестве T для IQueryable<T>.

G>>>И какой в этом смысл? То что оно усложняет код я уже увидел, а где положительные эффекты?
V>>Код должен делать работу здесь и сейчас (для твоего работодателя и заказчика), код должен легко поддаваться изменениям и оставаться полезным (для тебя в будущем).
G>И как это онсоится к репозитарию?
G>"Здесь и сейчас" можно добиться, написав Linq прямо в контроллере. А "легко поддаваться изменениям и оставаться полезным" можно добиться сделав комбинаторы, примерно вот так: http://gandjustas.blogspot.ru/2010/05/iqueryable-generics.html?&amp;tpwf_mode=main
G>А какая польза от репозитория?

IEnumerable<EntityDetails> visibleEntities = repo.GetEntities(new EntityFetch { Visible = true });


И простая читабельная реализация метода GetEntites. Без велосипеда IVisible и костыля к нему FixupVisitor. Хотя бы название метода Fix — не заставило задаться вопросом о целесообразности решения?

V>>Положительные эффекты в разделении зон ответственности кода. Если тебе надо работать с кодом доступа к бд, ты делаешь это в одном месте и не тебе не приходится лазать по всему дереву исходников. В будущем, тебе не придётся долго искать этот код и потом читать половину проекта, чтобы внести изменения и быть уверенным, что ничего не забыто.

G>Весь код работы с БД находится в ORM, а запросы "в одном месте" это фантастика, потому что в каждом контроллере нужны разные запросы. Где-то нужны сортировки, где-то проекции итп. Очень редко запросы дублируются.

Их конечное количество и мы не тратим время на написание универсальных велосипедов.

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

G>>>>>Какие например? Ну чтобы получить тот же уровень контроля компилятором, как в случае Linq.
V>>>>PostSortingMethod.
G>>>Что это? Пример кода приведи.

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

G>Я уже писал, что это даже хуже разных методов. А преимуществ не вижу.

V>>Да, ты можешь попробовать пилить японской пилой рельсу вместо сосны и пила обязательно сломается. Лучше всё же пилить сосну.

G>Доказательство по аналогии? Тут профессиональный форум, такая демагогия не катит.

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

G>>>>>Программист может и не заметить. И тестер может не заметить. Ты же понимаешь что это хуже, чем проверка компилятором, что все параметры переданы.

V>>>>Ещё программить может привести IQueryable к IEnumerable, отсортировать и в цикле выбрать нужные объекты. Компилятор с радостью это скомпилирует. И оно даже будет работать быстро некоторое время.

G>>>А кто мешает сделать программисту тоже самое с IEnumerable? Или ты думаешь, что если ты отдаешь IEnumerable. то никто к нему Linq применить не сможет, родив очень неэффективный код? Кстати именно поэтому имеет смысл отдавать Iqueryable, ибо тогда Linq превратится в запрос и улетит в базу, а привести к IEnumerable еще и не каждый догадается.

V>>Этот IEnumerable будет содержать с десяток объектов, уже готовых для отображения пользователю. Любые манипуляции с ним не будут отличаться большими накладными расходами.

G>А где гарантия что десятки?
G>Откуда репозиторий узнает что нужно для отображения пользователю?

DataFetch.PageSize


А про пользователя репозиторий ничего не знает.

G>С такими рассуждениями у тебя вся логика уедет в репозитории и методы репозиториев будут 1-в-1 повторять контроллеры. А проблемы никуда не денутся.


Логика выборки данных для набора конкретных случаев, которые нужны в приложении. И, главное, код будет простой как доска.
Re[16]: Entity Framework за! и против!
Здравствуйте, gandjustas, Вы писали:

G>Это не является ответом на вопрос зачем он нужен. Ты можешь миллион классов придумать, со своими функциями, но это не оправдывает их существования.

G>Тем более реальной выборкой данных нанимается ORM, а репозиторий только обертка, которая ничего положительного не приносит в код.

Скрыть механизм хранения данных от других слоёв приложения. Репозиторий оперирует коллекциями объектов, описывающих предметную область программы. Его контракт свободен от деталей того, какая технология используется внутри него. Это позволяет писать простой код как внутри репозитория, так и снаружи его. Простой код означает, что я быстрее закончу свою работу сейчас и быстрее внесу изменения потом. Простой код — это свободное время, которое я трачу в собственное удовольствие и не думаю о неработающем коде или хитроумном баге.

G>И как это онсоится к репозитарию?

G>"Здесь и сейчас" можно добиться, написав Linq прямо в контроллере. А "легко поддаваться изменениям и оставаться полезным" можно добиться сделав комбинаторы, примерно вот так: http://gandjustas.blogspot.ru/2010/05/iqueryable-generics.html?&amp;tpwf_mode=main
G>А какая польза от репозитория?

IEnumerable<EntityDetails> visibleEntities = repo.GetEntities(new EntityFetch { Visible = true });


И простая читабельная реализация метода GetEntites. Без велосипеда IVisible и костыля к нему FixupVisitor. Хотя бы название метода Fix — не заставило задаться вопросом о целесообразности решения?

V>>Положительные эффекты в разделении зон ответственности кода. Если тебе надо работать с кодом доступа к бд, ты делаешь это в одном месте и не тебе не приходится лазать по всему дереву исходников. В будущем, тебе не придётся долго искать этот код и потом читать половину проекта, чтобы внести изменения и быть уверенным, что ничего не забыто.

G>Весь код работы с БД находится в ORM, а запросы "в одном месте" это фантастика, потому что в каждом контроллере нужны разные запросы. Где-то нужны сортировки, где-то проекции итп. Очень редко запросы дублируются.

Их конечное количество и мы не тратим время на написание универсальных велосипедов.

V>>Этот IEnumerable будет содержать с десяток объектов, уже готовых для отображения пользователю. Любые манипуляции с ним не будут отличаться большими накладными расходами.

G>А где гарантия что десятки?
G>Откуда репозиторий узнает что нужно для отображения пользователю?

DataFetch.PageSize


А про пользователя репозиторий ничего не знает.

G>С такими рассуждениями у тебя вся логика уедет в репозитории и методы репозиториев будут 1-в-1 повторять контроллеры. А проблемы никуда не денутся.


Логика выборки данных для набора конкретных случаев, которые нужны в приложении. И, главное, код будет простой как доска.