List<Product> GetProductsBy..()
{
return dbContext.Models.SelectMany(....)
.Join(....)
.GroupBy(a => new Product()
{
a.Id,
Sales = a.FactSales.Select(b => new Sale())
});
}
если они работают то не напрягают и даже думаешь какая сложная и круто выглядит. Но когда начинаешь ошибку дебажить то часто нужно видеть что получается после каждой функции типа SelectMany
и приходится разбивать это на промежуточные конструкции.
Ваше мнение: лучше каждая функция в отдельную переменную или же есть вариант удобного дебага таких длинных конструкций?
Здравствуйте, merge, Вы писали:
M>если они работают то не напрягают и даже думаешь какая сложная и круто выглядит. Но когда начинаешь ошибку дебажить то часто нужно видеть что получается после каждой функции типа SelectMany
А разве по коду нельзя понять что он делает и какой результат будет?
Здравствуйте, Kernan, Вы писали:
M>>если они работают то не напрягают и даже думаешь какая сложная и круто выглядит. Но когда начинаешь ошибку дебажить то часто нужно видеть что получается после каждой функции типа SelectMany K>А разве по коду нельзя понять что он делает и какой результат будет?
Понять-то наверное можно, а вот проверит, точно ли промежуточные результаты соответствуют ожидаемым — уже сложнее
Здравствуйте, merge, Вы писали:
M>Часто попадаю в коде на такие длинные конструкции
Из данного примера не понятно, что это: linq to objects или что-то типа EF/linq2db. Если второе, то отлаживать нужно не отдельные методы выражения, а смотреть какой генерируется SQL и отлаживать уже его. Если же это linq to object и вот прямо совсем совсем без отладки ну никак, то нормальный ремесленник/мастеровой всегда может смастерить себе какую-нибудь приспособу на коленке. Возьмём к примеру метод GroupBy, нам понадобится его сигнатура, далее пишем по ней следующий конвертик:
static class DebuggableEnumerable
{
#if !DEBUG
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static IEnumerable<IGrouping<TKey,TSource>> DebugGroupBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector)
{
#if DEBUG
var before = source.ToList();
var after = source.GroupBy(keySelector).ToList();
return after;
#else
return source.GroupBy(keySelector);
#endif
}
}
Далее в своём выражении меняем GroupBy на DebugGroupBy и дебажим вволю.
Но это если совсем припекло. В Enumerable методов очень много и сразу покрыть всё вряд ли появится желание.
Если нам не помогут, то мы тоже никого не пощадим.
#if DEBUG
static class DebuggableEnumerable
{
public static IEnumerable<IGrouping<TKey,TSource>> DebugGroupBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector)
{
var before = source.ToList();
var after = source.GroupBy(keySelector).ToList();
return after;
}
}
#endif
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Marty, Вы писали:
M>точно ли промежуточные результаты соответствуют ожидаемым — уже сложнее
Мне прямо интересно, а как можно получить неожиданный результат если ты понимаешь что за код пишешь?
Здравствуйте, Kernan, Вы писали:
M>>точно ли промежуточные результаты соответствуют ожидаемым — уже сложнее K>Мне прямо интересно, а как можно получить неожиданный результат если ты понимаешь что за код пишешь?
Если где-то ошибся и написал не то, что хотел, не?
Здравствуйте, merge, Вы писали:
M>Ваше мнение: лучше каждая функция в отдельную переменную или же есть вариант удобного дебага таких длинных конструкций?
Функциональные конструкции очень тяжело отлаживать. Поэтому если по конструции нельзя быстро понять, что она делает, то её нужно упрощать.
Но основная идея и профит функциональных конструкций — что по ним, как правило, очевидно, что они делают, и отлаживать там нечего.