Re[4]: Entity Framework за! и против!
От: Vladek Россия Github
Дата: 18.08.14 13:19
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Приведи пример такого кода.


G>Для начала простой кейс как в StackOverflow:

G>1) Показывать посты по дате добавления
G>2) Показывать посты по количеству оценок за день (самые популярные)
G>3) Показывать посты по комментов за день (самые обсуждаемые)
G>Еще обязательно пейджинг.

G>Я предполагаю что получится такой набор методов в репозитариях:


G>
G>IEnumerable<PostData> GetPostsByDate(int start, int pageSize);
G>IEnumerable<PostData> GetPostsByComments(int start, int pageSize);
G>IEnumerable<PostData> GetPostsByScore(int start, int pageSize);
G>


Я в репозиторий передаю наследников такого класса:

  DataFetch.cs
public class DataFetch
{
    public static readonly int[] AvailablePageSizes = new[] { 10, 20, 50, 100 };

    private int? pageSize;

    public DataFetch()
    {
        this.PageSize = NormalizePageSize(null);
    }

    public bool? Ascending { get; set; }

    public int Page { get; set; }

    public int? PageSize
    {
        get
        {
            return this.pageSize;
        }
        set
        {
            this.pageSize = NormalizePageSize(value);
        }
    }

    public bool? Reset { get; set; }

    public string SortBy { get; set; }

    private static int NormalizePageSize(int? pageSize)
    {
        if (pageSize == null)
            return AvailablePageSizes.Min();

        return AvailablePageSizes.Aggregate((x, y) => Math.Abs(x - pageSize.Value) < Math.Abs(y - pageSize.Value) ? x : y);
    }
}


G>Потом внезапно требуется сделать фильтр по тегам, придется править все три метода. В итоге у нас "нижние" слои приложения страдают от изменений деталей представления. Значит расслоение сделано неверно.

G>В сценарии интернет-магазина или CRM может быть куча фильтров и сортировок и таких методов в репозитарии будет очень много. Поэтому цена изменения станет огромной.

При изменении требований я добавляю поля в наследника (PostFetch) и изменяю реализацию метода GetPosts в репозитории (в единственном экземпляре).

IEnumerable<PostDetails> GetPosts(PostFetch fetch)
Re[4]: Entity Framework за! и против!
От: IT Россия linq2db.com
Дата: 18.08.14 13:21
Оценка: +1
Здравствуйте, A-Myth, Вы писали:

AM>А вот с change tracking была история. В одном приложении с развесистым UI внезапно понадобился глобальный undo/redo.


Для этой функциональности нужен не change tracking, а реализация IEditableObject. Это делается элементарно, добавлением в T4 модели данных слудующей строчки:

<#@ include file="..\..\Templates\EditableObject.ttinclude"  #>

А добавлением следующей строчки реализуется INotifyPropertyChanged для всех объектов модели:

<#@ include file="..\..\Templates\NotifyPropertyChanged.ttinclude"  #>
Если нам не помогут, то мы тоже никого не пощадим.
Re[5]: Entity Framework за! и против!
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 18.08.14 13:34
Оценка:
Здравствуйте, Vladek, Вы писали:

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


G>>Я предполагаю что получится такой набор методов в репозитариях:


G>>
G>>IEnumerable<PostData> GetPostsByDate(int start, int pageSize);
G>>IEnumerable<PostData> GetPostsByComments(int start, int pageSize);
G>>IEnumerable<PostData> GetPostsByScore(int start, int pageSize);
G>>


V>Я в репозиторий передаю наследников такого класса:


V>DataFetch.cs

V>
V>public class DataFetch
V>{
V>   //Skipped
V>}



Поздравляю, вы изобрели свой IQueryable<T>, только гораздо более слабый и неудобный в использовании.

Например текстовое поле SortBy как будет работать? Там же нужно считать агрегаты по связанным таблицам, поэтому просто передать Sort в ORDER BY не выйдет. В зависимости от значения Sort надо будет генерировать разные запросы, а это не решает исходную проблему. При добавлении сценария UI — надо править репозиторий, только вы скрыли проблему из интерфейса репозиториев и спрятали её в реализацию.

Также со временем ваш DataFetch распухнет, что его надежно использовать станет сложно.

Предположим в том же кейсе понадобилось добавить фильтр по тегам для трех описанных выше выборок, а также добавился ее один экран, где надо показывать посты текущего пользователя (без фильтра по тегам).
Вы сделаете два разных DataFetch или будете кидать эксепшн на некорректном сочетании параметров?
Отредактировано 18.08.2014 13:39 gandjustas . Предыдущая версия .
Re[4]: Entity Framework за! и против!
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 18.08.14 13:48
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

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


V>>Сам так делал пока не вырос. В результате, их код очень цепко связан с конкретной ORM.


НС>Сейчас, в принципе, ни одна ORM не доросла до уровня, который позволит абстрагироваться от ее специфики. Так что попытка такую абстракцию ввести — классический случай leaky abstraction со всеми вытекающими.


Дело не в конкретных ORM, а в том как они используются.
SQL очень выразительный язык, гораздо выразительнее любого мейнстримного языка, Linq создавался как раз чтобы не сильно отставать по выразительности от SQL.

Попытка абстрагироваться от ORM с Linq это обычно создание классов с RPC-style интрфейсом, иногда со своим набором классов-спецификаций, которые на два порядка менее выразительны, чем Linq. Естественно такое абстрагирование приводит к распуханию кода, падению производительности и уменьшению мощности системы. А для потребителя эта абстракция не дает ничего хорошего.

Вот Синклер рассказывал к чему приводит "абстрагирование" http://rsdn.ru/forum/design/5682243
Автор: Sinclair
Дата: 10.07.14
Re[6]: Entity Framework за! и против!
От: Vladek Россия Github
Дата: 18.08.14 14:02
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Поздравляю, вы изобрели свой IQueryable<T>, только гораздо более слабый и неудобный в использовании.


Я его инкапсулировал.

G>Например текстовое поле SortBy как будет работать? Там же нужно считать агрегаты по связанным таблицам, поэтому просто передать Sort в ORDER BY не выйдет. В зависимости от значения Sort надо будет генерировать разные запросы, а это не решает исходную проблему. При добавлении сценария UI — надо править репозиторий, только вы скрыли проблему из интерфейса репозиториев и спрятали её в реализацию.


У меня сортировка по одному полю, поэтому этого SortBy мне достаточно. Если сортировка будет более сложной, то вместо текстовой строки я буду передавать что-то другое — зависит от условий задачи. А уж что там генерируется или делается за кулисами по этим полям, будет скрыто от внешнего мира.

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


Любой код распухнет при бесконечном изменении и расширении требований, в реальности новые требования перестают рано или поздно поступать или наступает дедлайн.

G>Предположим в том же кейсе понадобилось добавить фильтр по тегам для трех описанных выше выборок, а также добавился ее один экран, где надо показывать посты текущего пользователя (без фильтра по тегам).

G>Вы сделаете два разных DataFetch или будете кидать эксепшн на некорректном сочетании параметров?

В данном случае, теги и авторство вполне сочетаются. А если параметры точно не будут сочетаться, то тогда сделаю два разных класса.
Re[7]: Entity Framework за! и против!
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 18.08.14 14:14
Оценка:
Здравствуйте, Vladek, Вы писали:

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


G>>Поздравляю, вы изобрели свой IQueryable<T>, только гораздо более слабый и неудобный в использовании.


V>Я его инкапсулировал.


Нет, DataFetch делает ровно тоже, что и методы OrderBy, Top, Skip, при этом не дает никаких гарантий что Top и Skip применяются при наличии OrderBy.
Инкапсуляция, которая не дает дополнительных гарантий потребителю не нужна от слова вообще.



G>>Например текстовое поле SortBy как будет работать? Там же нужно считать агрегаты по связанным таблицам, поэтому просто передать Sort в ORDER BY не выйдет. В зависимости от значения Sort надо будет генерировать разные запросы, а это не решает исходную проблему. При добавлении сценария UI — надо править репозиторий, только вы скрыли проблему из интерфейса репозиториев и спрятали её в реализацию.


V>У меня сортировка по одному полю, поэтому этого SortBy мне достаточно. Если сортировка будет более сложной, то вместо текстовой строки я буду передавать что-то другое — зависит от условий задачи. А уж что там генерируется или делается за кулисами по этим полям, будет скрыто от внешнего мира.


Тогда возвращаемся к кейсу:
1) Показывать посты по дате добавления
2) Показывать посты по количеству оценок за день (самые популярные)
3) Показывать посты по комментов за день (самые обсуждаемые)

Во втором и третьем случае надо сделать join и посчитать реальное количество комментов\оценок за день. Обойтись SortBy по одному полю не выйдет.
Как в этом случае сделать репозитарии?
Кстати текстовый SortBy гораздо хуже лямбды в OrderBy.



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

V>Любой код распухнет при бесконечном изменении и расширении требований, в реальности новые требования перестают рано или поздно поступать или наступает дедлайн.
У вас распухнет в двух местах: появится много классов DataFetch или в него добавится неприлично много методов, а также распухнет обработчик этого монструозного класса(ов) DataFetch.
Если напрямую писать Linq и использовать комбинаторы, то распухать будет только в одном месте.

G>>Предположим в том же кейсе понадобилось добавить фильтр по тегам для трех описанных выше выборок, а также добавился ее один экран, где надо показывать посты текущего пользователя (без фильтра по тегам).

G>>Вы сделаете два разных DataFetch или будете кидать эксепшн на некорректном сочетании параметров?

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

В данном случае не сочетаются. По условиям задачи. Даже если эти условия вам не нарвятся легко придумать правдоподобные условия задачи, где будут две независимые выборки, и объединить их параметры в один DataFetch не выйдет.
Re[8]: Entity Framework за! и против!
От: Vladek Россия Github
Дата: 18.08.14 14:57
Оценка:
Здравствуйте, gandjustas, Вы писали:

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


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


G>>>Поздравляю, вы изобрели свой IQueryable<T>, только гораздо более слабый и неудобный в использовании.


V>>Я его инкапсулировал.


G>Нет, DataFetch делает ровно тоже, что и методы OrderBy, Top, Skip, при этом не дает никаких гарантий что Top и Skip применяются при наличии OrderBy.

G>Инкапсуляция, которая не дает дополнительных гарантий потребителю не нужна от слова вообще.

Это выворачивание деталей реализации наизнанку. Не нужна вам инкапсуляция, не пользуйтесь. Мне нужна гарантия, что репозиторий делает то, что нужно и ничего меньше или больше, поэтому наружу торчит куцый DataFetch.

G>>>Например текстовое поле SortBy как будет работать? Там же нужно считать агрегаты по связанным таблицам, поэтому просто передать Sort в ORDER BY не выйдет. В зависимости от значения Sort надо будет генерировать разные запросы, а это не решает исходную проблему. При добавлении сценария UI — надо править репозиторий, только вы скрыли проблему из интерфейса репозиториев и спрятали её в реализацию.


V>>У меня сортировка по одному полю, поэтому этого SortBy мне достаточно. Если сортировка будет более сложной, то вместо текстовой строки я буду передавать что-то другое — зависит от условий задачи. А уж что там генерируется или делается за кулисами по этим полям, будет скрыто от внешнего мира.


G>Тогда возвращаемся к кейсу:

G>1) Показывать посты по дате добавления
G>2) Показывать посты по количеству оценок за день (самые популярные)
G>3) Показывать посты по комментов за день (самые обсуждаемые)

G>Во втором и третьем случае надо сделать join и посчитать реальное количество комментов\оценок за день. Обойтись SortBy по одному полю не выйдет.

G>Как в этом случае сделать репозитарии?
G>Кстати текстовый SortBy гораздо хуже лямбды в OrderBy.

Что такое лямбды, джойны и OrderBy? Зачем вам, пользователю репозитория, об этом знать? Может там все посты в обычном текстовом файле хранятся.

Сделаю поле вот такого типа и уже потом буду размышлять как это реализовать — через лямбды или строки.

public enum PostSortingMethod
{
  Recent,
  HighlyRated,
  Flames
}



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

V>>Любой код распухнет при бесконечном изменении и расширении требований, в реальности новые требования перестают рано или поздно поступать или наступает дедлайн.
G>У вас распухнет в двух местах: появится много классов DataFetch или в него добавится неприлично много методов, а также распухнет обработчик этого монструозного класса(ов) DataFetch.
G>Если напрямую писать Linq и использовать комбинаторы, то распухать будет только в одном месте.

В том-то и дело, что у меня Linq написан только внутри репозиториев. Чистый и конкретный, без моих лишних велосипедов и абстракций. Наследники DataFetch предназначены для передачи параметров, методов у них нет. Много классов я не боюсь, причём через некоторое время начинаешь замечать их похожесть и объединяешь их.

G>>>Предположим в том же кейсе понадобилось добавить фильтр по тегам для трех описанных выше выборок, а также добавился ее один экран, где надо показывать посты текущего пользователя (без фильтра по тегам).

G>>>Вы сделаете два разных DataFetch или будете кидать эксепшн на некорректном сочетании параметров?

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

G>В данном случае не сочетаются. По условиям задачи. Даже если эти условия вам не нарвятся легко придумать правдоподобные условия задачи, где будут две независимые выборки, и объединить их параметры в один DataFetch не выйдет.

Ну значит будут отдельные классы входящих параметров для особых случаев, ничего страшного.
Re[9]: Entity Framework за! и против!
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 18.08.14 15:12
Оценка: +1
Здравствуйте, Vladek, Вы писали:

G>>>>Например текстовое поле SortBy как будет работать? Там же нужно считать агрегаты по связанным таблицам, поэтому просто передать Sort в ORDER BY не выйдет. В зависимости от значения Sort надо будет генерировать разные запросы, а это не решает исходную проблему. При добавлении сценария UI — надо править репозиторий, только вы скрыли проблему из интерфейса репозиториев и спрятали её в реализацию.


V>>>У меня сортировка по одному полю, поэтому этого SortBy мне достаточно. Если сортировка будет более сложной, то вместо текстовой строки я буду передавать что-то другое — зависит от условий задачи. А уж что там генерируется или делается за кулисами по этим полям, будет скрыто от внешнего мира.


G>>Тогда возвращаемся к кейсу:

G>>1) Показывать посты по дате добавления
G>>2) Показывать посты по количеству оценок за день (самые популярные)
G>>3) Показывать посты по комментов за день (самые обсуждаемые)

G>>Во втором и третьем случае надо сделать join и посчитать реальное количество комментов\оценок за день. Обойтись SortBy по одному полю не выйдет.

G>>Как в этом случае сделать репозитарии?
G>>Кстати текстовый SortBy гораздо хуже лямбды в OrderBy.

V>Что такое лямбды, джойны и OrderBy? Зачем вам, пользователю репозитория, об этом знать? Может там все посты в обычном текстовом файле хранятся.

Почему репозиторий определяет что я должен знать?
Я хочу задавать сортировку так, чтобы при переименовании поля код ругался. Лямбды для этого хорошо подходят, а linq идеально. Строки тут в жопе.


V>Сделаю поле вот такого типа и уже потом буду размышлять как это реализовать — через лямбды или строки.


V>
V>public enum PostSortingMethod
V>{
V>  Recent,
V>  HighlyRated,
V>  Flames
V>}
V>



То есть будет количество членов в enum по количеству разных выборок, а внутри будет большой swith. Это полностью аналогично разным методам. Более того разные методы даже удобнее, ибо списки параметров есть. А DataFetch позволяет легко не указать то, что надо.
Re[10]: Entity Framework за! и против!
От: Vladek Россия Github
Дата: 18.08.14 15:29
Оценка:
Здравствуйте, gandjustas, Вы писали:

V>>Что такое лямбды, джойны и OrderBy? Зачем вам, пользователю репозитория, об этом знать? Может там все посты в обычном текстовом файле хранятся.

G>Почему репозиторий определяет что я должен знать?
G>Я хочу задавать сортировку так, чтобы при переименовании поля код ругался. Лямбды для этого хорошо подходят, а linq идеально. Строки тут в жопе.

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

V>>Сделаю поле вот такого типа и уже потом буду размышлять как это реализовать — через лямбды или строки.


V>>
V>>public enum PostSortingMethod
V>>{
V>>  Recent,
V>>  HighlyRated,
V>>  Flames
V>>}
V>>



G>То есть будет количество членов в enum по количеству разных выборок, а внутри будет большой swith. Это полностью аналогично разным методам. Более того разные методы даже удобнее, ибо списки параметров есть. А DataFetch позволяет легко не указать то, что надо.


Тогда сортировка просто не будет работать как надо, программист быстро укажет то, что нужно, и всё заработает.
Re[11]: Entity Framework за! и против!
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 18.08.14 15:55
Оценка:
Здравствуйте, Vladek, Вы писали:

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


V>>>Что такое лямбды, джойны и OrderBy? Зачем вам, пользователю репозитория, об этом знать? Может там все посты в обычном текстовом файле хранятся.

G>>Почему репозиторий определяет что я должен знать?
G>>Я хочу задавать сортировку так, чтобы при переименовании поля код ругался. Лямбды для этого хорошо подходят, а linq идеально. Строки тут в жопе.

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

Это в теории.

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

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

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

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

Какие например? Ну чтобы получить тот же уровень контроля компилятором, как в случае Linq.


G>>То есть будет количество членов в enum по количеству разных выборок, а внутри будет большой swith. Это полностью аналогично разным методам. Более того разные методы даже удобнее, ибо списки параметров есть. А DataFetch позволяет легко не указать то, что надо.


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

Программист может и не заметить. И тестер может не заметить. Ты же понимаешь что это хуже, чем проверка компилятором, что все параметры переданы.
Re[9]: Entity Framework за! и против!
От: Dair Россия https://dair.spb.ru
Дата: 18.08.14 16:17
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>Да примерно так же и будет:

НС>
НС>from loc in db.Locations
НС>from evt in loc.Events
НС>where evt.CrDate > DateTime.Now - TimeSpan.FromHours(period)
НС>order by loc.Id
НС>group loc by new {loc.Id, loc.Name} into g
НС>select new {g.Key.Id, g.Key.Name, g.Count()};
НС>


Ого. Это C# умеет такое парсить? Круто.

Спасибо, поизучаю на досуге.
Re[5]: Entity Framework за! и против!
От: Dair Россия https://dair.spb.ru
Дата: 18.08.14 16:22
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

О, мне тут ответов понаписали, а я и не видел

НС>SQL, надеюсь, понимаешь?

Да, довольно неплохо.

НС>
НС>SELECT TOP 1
НС>  f.ForumShortName, m.CreatedOn, m.Subject, a.Origin, mt.Text
НС>FROM Messages m
НС>  JOIN Forums f ON f.ID = m.ForumID
НС>  OUTER JOIN Accounts a ON a.ID = m.AccountID
НС>  JOIN MessageTexts mt ON mt.ID = m.ID
НС>WHERE m.ID = @id AND f.ReadLevel <= @accessLevel
НС>


Запрос понятен, да.

НС>Приведенный код открывает коннект к БД, выполняет этот sql с передачей значений двух параметров, читает результат. Если записей нет — возвращает null, если есть — создает и заполняет данными экземпляр класса MessageModel (при этом вызывается функция FormatMessageBody с частью полей результата) и возвращает этот экземпляр. При этом все типы в запросе, его параметрах и результате контролируются комспилятором.

НС>Теперь понятно?

Спасибо.
Да, всё понятно, кроме одного момента — что именно и как контролирует компилятор?
Re[3]: Entity Framework за! и против!
От: Dair Россия https://dair.spb.ru
Дата: 18.08.14 16:22
Оценка:
К>Почему начинаете издалека? Лучше сразу к делу — зачем нужно ООП.

ООП я использую практически постоянно, вопросов "зачем" не возникает
Re[6]: Entity Framework за! и против!
От: Ночной Смотрящий Россия  
Дата: 18.08.14 17:09
Оценка:
Здравствуйте, Dair, Вы писали:

D>Да, всё понятно, кроме одного момента — что именно и как контролирует компилятор?


Типы он контролирует.
Re[5]: Entity Framework за! и против!
От: Ночной Смотрящий Россия  
Дата: 18.08.14 17:09
Оценка: +1
Здравствуйте, gandjustas, Вы писали:

НС>>Сейчас, в принципе, ни одна ORM не доросла до уровня, который позволит абстрагироваться от ее специфики. Так что попытка такую абстракцию ввести — классический случай leaky abstraction со всеми вытекающими.


G>Дело не в конкретных ORM


Конечно не в конкретных. Потому что ровно 100% ORM не способны полностью спрятать детали реализации. Причем с тяжелыми ORM вообще сразу все понятно. Из легковесных linq2db продвинулась дальше всего, но и там такое море специфики, что о полной абстракции не приходится даже мечтать. Итого, нетекущая абстракция сейчас возможна только на уровне самых простых запросов с явными джойнами.

G>SQL очень выразительный язык, гораздо выразительнее любого мейнстримного языка,


Чего? Я тебе как садовод могу сказать, что даже та выразительность, что дает expression tree в шарпе на голову выше, чем выразительность SQL. Потому что постоянно приходится сталкиваться с ситуацией, когда тривиальное выражение на linq невозможно или очень сложно оттранслировать в SQL. Банальный group by порой таких жестких приседаний на sql требует, что в пору застрелиться.

G> Linq создавался как раз чтобы не сильно отставать по выразительности от SQL.


Это ты сам придумал?

G>Вот Синклер рассказывал к чему приводит "абстрагирование" http://rsdn.ru/forum/design/5682243
Автор: Sinclair
Дата: 10.07.14


Он то расказал правильно, а вот ты понял его как то странно, судя по всему.
Re[5]: Entity Framework за! и против!
От: Ночной Смотрящий Россия  
Дата: 18.08.14 17:09
Оценка:
Здравствуйте, Vladek, Вы писали:

V>Я в репозиторий передаю наследников такого класса:


Куда интереснее что ты делаешь, когда в одном месте нужны посты с рейтингом, а в другом без, или в одном месте достаточно имени автора, а в другом потребно пяток полей из его профиля?
Re[9]: Entity Framework за! и против!
От: Ночной Смотрящий Россия  
Дата: 18.08.14 17:09
Оценка:
Здравствуйте, Vladek, Вы писали:

V>Что такое лямбды, джойны и OrderBy? Зачем вам, пользователю репозитория, об этом знать? Может там все посты в обычном текстовом файле хранятся.


Ну и как, хоть раз приходилось доставать данные, которые раньше доставались из БД, из текстового файла?

V>
V>public enum PostSortingMethod
V>{
V>  Recent,
V>  HighlyRated,
V>  Flames
V>}
V>


Т.е., получаем, на каждый запрос я создаю отдельный метод выборки, который будет использоваться ровно в одном месте? Ну и ради чего? Чтобы когда нибудь БД заменить на текстовый файл?
Re[12]: Entity Framework за! и против!
От: Vladek Россия Github
Дата: 18.08.14 17:45
Оценка:
Здравствуйте, gandjustas, Вы писали:

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

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

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

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

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

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


Что изменится в контракте репозитория? Правильно, ничего.

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

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

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

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

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

PostSortingMethod.

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

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

Ещё программить может привести IQueryable к IEnumerable, отсортировать и в цикле выбрать нужные объекты. Компилятор с радостью это скомпилирует. И оно даже будет работать быстро некоторое время.
Re[6]: Entity Framework за! и против!
От: Vladek Россия Github
Дата: 18.08.14 17:50
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

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


V>>Я в репозиторий передаю наследников такого класса:


НС>Куда интереснее что ты делаешь, когда в одном месте нужны посты с рейтингом, а в другом без, или в одном месте достаточно имени автора, а в другом потребно пяток полей из его профиля?


Просто делаю параметры выборки в виде Nullable. Тогда их можно комбинировать как угодно. На моей практике таких полей редко больше четырёх. Пользователи не очень любят заполнять формы со 100500 полями.
Re[10]: Entity Framework за! и против!
От: Vladek Россия Github
Дата: 18.08.14 17:52
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>Т.е., получаем, на каждый запрос я создаю отдельный метод выборки, который будет использоваться ровно в одном месте? Ну и ради чего? Чтобы когда нибудь БД заменить на текстовый файл?


Чтобы код был простым и его было легко расширять и менять.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.