Re[5]: Полезняшка для dictionary
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 29.04.16 19:38
Оценка: +1
Здравствуйте, -n1l-, Вы писали:

N>Сразу до кучи — ForEach для IEnumerable запилили?


Нет и не будет. Ибо зло в чистом виде
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[7]: Полезняшка для dictionary
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 30.04.16 13:33
Оценка: +1
Здравствуйте, -n1l-, Вы писали:

AVK>>Нет и не будет. Ибо зло в чистом виде

N>почему?

Потому что при чтении кода linq выражения человеком обычно воспринимаются как pure. И если на самом деле там внутри меняется внешнее состояние, это сильно снижает читаемость кода. Что есть зло.
А в зло в чистом виде, потому что никакого преимущества такой метод по сравнению с оператором foreach не дает, только лишний синтаксический шум и маскировка под чистые методы.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[8]: Полезняшка для dictionary
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 30.04.16 13:41
Оценка: +1
Здравствуйте, Jack128, Вы писали:

J>А вот чтоб переписать код ниже без метода Do — нужно заводить отдельный метод

J>
J>IEnumerable<MyObj> GetObjs()  {  .... } // получаем данные
J>void Process(IEnumerable<MyObj> objs) // обрабатываем их как то
J>{
J>   foreach(var obj in objs)
J>   {
J>      ...      
J>   }
J>}
J>AdditionalData GetAdditionalData(MyObj obj) { ... } 

J>Proccess(GetObjs().Do(obj => obj.AdditionalData = GetAdditionalData(obj)));
J>


AdditionalData GetAdditionalData(MyObj obj) { ... }

foreach (var obj in GetObjs())
{
    obj.AdditionalData = GetAdditionalData(obj)
    Process(obj);
}

Короче и понятнее. Или я чего то не понял?

Непременно надо цикл в метод запихнуть?
void Process(IEnumerable<MyObj> objs, Action<MyObj> preprocessor) // обрабатываем их как то
{
   foreach(var obj in objs)
   {
      preprocessor(obj);
      ...      
   }
}


Ну или если совсем уж намеренно упороться, то:
Proccess(GetObjs().Select(obj => {obj.AdditionalData = GetAdditionalData(obj); return obj;}));
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Полезняшка для dictionary
От: -n1l-  
Дата: 29.04.16 14:48
Оценка:
    public static TResult GetValue<TKey, TValue, TResult>(this IDictionary<TKey, TValue> source, 
                                                          TKey key, 
                                                          Func<TValue, TResult> callback,
                                                          Func<TKey, TResult> callbackIfEmpty)
    {
      if (!source.ContainsKey(key))
      {
        return callbackIfEmpty(key);
      }
      var result = source[key];

      return callback(result);
    }


Как вам такое?
Re: Полезняшка для dictionary
От: IT Россия linq2db.com
Дата: 29.04.16 15:00
Оценка:
Здравствуйте, -n1l-, Вы писали:

N>Как вам такое?


Почему не через TryGetValue?
Если нам не помогут, то мы тоже никого не пощадим.
Re: Полезняшка для dictionary
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 29.04.16 15:22
Оценка:
Здравствуйте, -n1l-, Вы писали:

N>Как вам такое?


Присутствует под названием GetValueOrDefault. Или я что то не так понял?
[Pure]
public static TResult GetValueOrDefault<TKey, TValue, TResult>(
    [NotNull] this IDictionary<TKey, TValue> dictionary,
    TKey key,
    [NotNull, InstantHandle] Func<TKey, TValue, TResult> resultSelector,
    [NotNull, InstantHandle] Func<TKey, TResult> defaultValueFactory)
{
    Code.NotNull(dictionary, nameof(dictionary));
    Code.NotNull(resultSelector, nameof(resultSelector));
    Code.NotNull(defaultValueFactory, nameof(defaultValueFactory));

    TValue result;
    return
        dictionary.TryGetValue(key, out result)
            ? resultSelector(key, result)
            : defaultValueFactory(key);
}
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Отредактировано 29.04.2016 15:23 AndrewVK . Предыдущая версия .
Re[2]: Полезняшка для dictionary
От: -n1l-  
Дата: 29.04.16 16:51
Оценка:
Здравствуйте, AndrewVK, Вы писали:

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


N>>Как вам такое?


AVK>Присутствует под названием GetValueOrDefault. Или я что то не так понял?

AVK>
AVK>[Pure]
AVK>public static TResult GetValueOrDefault<TKey, TValue, TResult>(
AVK>    [NotNull] this IDictionary<TKey, TValue> dictionary,
AVK>    TKey key,
AVK>    [NotNull, InstantHandle] Func<TKey, TValue, TResult> resultSelector,
AVK>    [NotNull, InstantHandle] Func<TKey, TResult> defaultValueFactory)
AVK>{
AVK>    Code.NotNull(dictionary, nameof(dictionary));
AVK>    Code.NotNull(resultSelector, nameof(resultSelector));
AVK>    Code.NotNull(defaultValueFactory, nameof(defaultValueFactory));

AVK>    TValue result;
AVK>    return
AVK>        dictionary.TryGetValue(key, out result)
AVK>            ? resultSelector(key, result)
AVK>            : defaultValueFactory(key);
AVK>}
AVK>


А я не смотрел код)
Только сегодня додумался о такой функции и решил предложить.
А почему у первого колбэка два параметра входных?
Зачем?
Re[2]: Полезняшка для dictionary
От: -n1l-  
Дата: 29.04.16 16:52
Оценка:
Только сегодня идея пришла в голову.
Re[3]: Полезняшка для dictionary
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 29.04.16 16:59
Оценка:
Здравствуйте, -n1l-, Вы писали:

N>А почему у первого колбэка два параметра входных?

N>Зачем?

Иногда бывает нужно.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[4]: Полезняшка для dictionary
От: -n1l-  
Дата: 29.04.16 17:06
Оценка:
Сразу до кучи — ForEach для IEnumerable запилили?
Re[5]: Полезняшка для dictionary
От: Jack128  
Дата: 29.04.16 17:56
Оценка:
Здравствуйте, -n1l-, Вы писали:

N>Сразу до кучи — ForEach для IEnumerable запилили?

Не нужен. А вот
IEnumerable<T> Do(this IEnumerable<T> source, Action<T> action)

был бы полезен
Re[6]: Полезняшка для dictionary
От: Sinix  
Дата: 29.04.16 18:11
Оценка:
Здравствуйте, Jack128, Вы писали:

J>Не нужен. А вот

IEnumerable<T> Do(this IEnumerable<T> source, Action<T> action)

J> был бы полезен
Оба не нужны.
Серьёзно, давайте всё-таки предлагать фичи по принципу "есть _реальный_ сценарий использования", а не "что б ещё такое переподвывернуть?"

Для последнего php с js есть, развлекайся — не хочу

Есть сценарий — не вопрос, можно обсудить. Нет — я бы выкидывал без сожалений. Мы ж не за количеством методов гонимся
Re[6]: Полезняшка для dictionary
От: -n1l-  
Дата: 30.04.16 09:38
Оценка:
Здравствуйте, AndrewVK, Вы писали:

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


N>>Сразу до кучи — ForEach для IEnumerable запилили?


AVK>Нет и не будет. Ибо зло в чистом виде


почему?
Re[6]: Полезняшка для dictionary
От: -n1l-  
Дата: 30.04.16 09:39
Оценка:
В чем разница?
Re[7]: Полезняшка для dictionary
От: -n1l-  
Дата: 30.04.16 09:41
Оценка:
Ну я запилил себе ForEach для IEnumerable, нарадоваться не могу.
Re[7]: Полезняшка для dictionary
От: Jack128  
Дата: 30.04.16 11:39
Оценка:
Здравствуйте, -n1l-, Вы писали:


N>В чем разница?


в возвращаемом значении.
простой ForEach ничем от цикла не отличается. Кроме производительности


А вот чтоб переписать код ниже без метода Do — нужно заводить отдельный метод

IEnumerable<MyObj> GetObjs()  {  .... } // получаем данные
void Process(IEnumerable<MyObj> objs) // обрабатываем их как то
{
   foreach(var obj in objs)
   {
      ...      
   }
}
AdditionalData GetAdditionalData(MyObj obj) { ... } 

Proccess(GetObjs().Do(obj => obj.AdditionalData = GetAdditionalData(obj)));
Отредактировано 30.04.2016 11:44 Jack128 . Предыдущая версия . Еще …
Отредактировано 30.04.2016 11:43 Jack128 . Предыдущая версия .
Re[8]: Полезняшка для dictionary
От: -n1l-  
Дата: 30.04.16 14:47
Оценка:
Здравствуйте, AndrewVK, Вы писали:

Как вы поступаете с большими выражениями?
Создаете временную переменную?
И что так лучше читается вместо добавления одного метода, который этот форыч инкапсулирует?
Re[8]: Полезняшка для dictionary
От: Sinix  
Дата: 30.04.16 15:27
Оценка:
Здравствуйте, Jack128, Вы писали:

J>А вот чтоб переписать код ниже без метода Do — нужно заводить отдельный метод

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

Если коротко и цензурно, то код пишут не чтоб потешить ЧСВ, а чтоб через годика 4 его смог за полминуты поправить только что принятый джуниор. И чтоб при этом код не превратился в какашку.

Серьёзно, это прям таки классический пример, почему код нельзя писать в solution-driven стиле.
Допустим, Process чуть позже станет фильтровать objs или получать только последний из них. Соответственно, большая часть AdditionalData будет заполнена зря.
Зашибись как сэкономили, да?

Вы точно уверены, что хотите поддерживать код с такими потенциальными багами?

Ну и как всегда правильный варинт:
1. признать, что текущий дизайн — отстой, т.к. вынуждает лепить костыли в самых тривиальных случаях.
2. Сделать рефакторинг под реальный сценарий использования. Например, вытащить тело цикла в отдельный метод.
3. В будущем на code review показывать разработчику, что в 99% случаев необходимость в костылях к стандартным конструкциям языка означает криво спроектированное API. Правильный способ — не прикрыть текущую ситуацию штукатуркой, а чинить исходную проблему.
Re[9]: Полезняшка для dictionary
От: -n1l-  
Дата: 30.04.16 16:09
Оценка:
Здравствуйте, Sinix, Вы писали:
S>3. В будущем на code review показывать разработчику, что в 99% случаев необходимость в костылях к стандартным конструкциям языка означает криво спроектированное API. Правильный способ — не прикрыть текущую ситуацию штукатуркой, а чинить исходную проблему.

Это в мирках где бизнес-логика настолько простая, что все что нужно делать — использовать стандартные методы фреймворка?
Re[10]: Полезняшка для dictionary
От: Sinix  
Дата: 30.04.16 17:17
Оценка:
Здравствуйте, -n1l-, Вы писали:

S>>3. В будущем на code review показывать разработчику, что в 99% случаев необходимость в костылях к стандартным конструкциям языка означает криво спроектированное API. Правильный способ — не прикрыть текущую ситуацию штукатуркой, а чинить исходную проблему.


N>Это в мирках где бизнес-логика настолько простая, что все что нужно делать — использовать стандартные методы фреймворка?

Э-э-э, пост внимательней читай
речь была про

необходимость в костылях к стандартным конструкциям языка

,
не про хелперы для фреймворка.

Предложенный Do() означает, что девелоперу влом написать foreach. Или что дизайн API вынуждает вырезать гланды с другой стороны, как в примере с GetAdditionalData().


И таки да, костяк БЛ практически никогда не вылезает за if/else/foreach + хелперы для "on A,B,C changed — do Y", всё страшное прячется на уровень ниже, в методы, которые разруливают конкретные случаи. Точнее, оно так может быть записано. А на практике я видел всё — от кодогенерации конечных автоматов в рантайма и до логики в 5-6 килострок на linq. Но это не значит, что код надо писать так

Это если мы конечно о типовой бухгалтерско-банковской опердени говорим, не о экзотике типа реалтайма/каналах связи и о прочей инфраструктурщине.
Re[9]: Полезняшка для dictionary
От: Jack128  
Дата: 30.04.16 17:58
Оценка:
Здравствуйте, Sinix, Вы писали:

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


J>>А вот чтоб переписать код ниже без метода Do — нужно заводить отдельный метод

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

S>Если коротко и цензурно, то код пишут не чтоб потешить ЧСВ, а чтоб через годика 4 его смог за полминуты поправить только что принятый джуниор. И чтоб при этом код не превратился в какашку.


S>Серьёзно, это прям таки классический пример, почему код нельзя писать в solution-driven стиле.

S>Допустим, Process чуть позже станет фильтровать objs или получать только последний из них. Соответственно, большая часть AdditionalData будет заполнена зря.
S>Зашибись как сэкономили, да?
хм, а то что большая часть объектов MyObj тоже будет создана зря тя не волнует? Если не волнует, то как бы двойные стандарты уместны в политике, но не в программировании. Если же волнует, то по твоей логике вообще все методы, фильтрующие IEnumerable — аЦЦтой ибо все отфильтрованные объекты созданы зря.

S>Вы точно уверены, что хотите поддерживать код с такими потенциальными багами?

Где потенциальный баг? Пока ты привел аргумент по производительности.

S>Ну и как всегда правильный варинт:

S>1. признать, что текущий дизайн — отстой, т.к. вынуждает лепить костыли в самых тривиальных случаях.
Не, тут я всегда за, сам люблю оцтоить дизайн, особенно чужой :-D
S>2. Сделать рефакторинг под реальный сценарий использования. Например, вытащить тело цикла в отдельный метод.
Он вроде и так в отдельном методе, метод Proccess только из цикла и состоит.
S>3. В будущем на code review показывать разработчику, что в 99% случаев необходимость в костылях к стандартным конструкциям языка означает криво спроектированное API. Правильный способ — не прикрыть текущую ситуацию штукатуркой, а чинить исходную проблему.
Смотрю во все глаза
Re[10]: Полезняшка для dictionary
От: Sinix  
Дата: 30.04.16 18:29
Оценка:
Здравствуйте, Jack128, Вы писали:

S>>Допустим, Process чуть позже станет фильтровать objs или получать только последний из них. Соответственно, большая часть AdditionalData будет заполнена зря.

J>хм, а то что большая часть объектов MyObj тоже будет создана зря тя не волнует?
Не волнует, т.к. из публичного контракта и сценария использования следует, что GetAdditionalData() — "тяжёлый" метод и должен вызываться лениво, только при необходимости. Если это не так — двойной косяк в дизайне: мы пишем костыли чтоб сэкономить на том, на чём вообще нет смысла экономить.



J> Если не волнует, то как бы двойные стандарты уместны в политике, но не в программировании. Если же волнует, то по твоей логике вообще все методы, фильтрующие IEnumerable — аЦЦтой ибо все отфильтрованные объекты созданы зря.

J>Где потенциальный баг? Пока ты привел аргумент по производительности.

Не, смотри про что речь: сам по себе перебор enumerable — ок.

перебор, который закладывается на то, что при вызове MoveNext() происходят какие-то побочные эффекты — прямой путь к тому, что ожидания не сработают
твой код аналогичен:
var x = GetX();
DoSomething(x);
var y = x.Y; - закладываемся на то, что Y заполнен в DoSomething().


Надеюсь, не надо спрашивать "что тут может пойти не так?"
Ну фигня же, а не хороший код, не согласен?


S>>Ну и как всегда правильный варинт:

S>>1. признать, что текущий дизайн — отстой, т.к. вынуждает лепить костыли в самых тривиальных случаях.
J>Не, тут я всегда за, сам люблю оцтоить дизайн, особенно чужой :-D
Не-не-не, ты не понял про что речь. Дизайн отстой не потому что автор его плохо написал, или потому что автор чего-то не знает (тут это очевидно не так). Дизайн отстой, потому что он очевидно используется не по делу.

Вот пока с этим не согласились — все дальнейшие движения не имеют смысла, т.к. получается спор из разряда "а слон кита заборет?".
Даже если заборет — получится фигня. Очень часто выходит так, что хорошего решения не находится и все варианты кроме исходного сам предлагающий постепенно сносит в мусорку.
Вот как раз пример
Автор: Sinix
Дата: 18.04.16
, недавно было.

Короче, "дизайн отстой" ни разу не значит "автор отстой", если было воспринято так — я сам отстой и мои извинения

S>>2. Сделать рефакторинг под реальный сценарий использования. Например, вытащить тело цикла в отдельный метод.

J>Он вроде и так в отдельном методе, метод Proccess только из цикла и состоит.
Было:
void Process(IEnumerable<MyObj> objs) // обрабатываем их как то
{
   foreach(var obj in objs)
   {
      ...      
   }
}


тело цикла (троеточие) вынести в отдельны метод, или передать делегат параметром. Собсно AndrewVK выше предложил.
Re[9]: Полезняшка для dictionary
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 30.04.16 19:52
Оценка:
Здравствуйте, -n1l-, Вы писали:

N>Как вы поступаете с большими выражениями?


Какими большими выражениями? Выражения это pure код, там никаких foreach быть не может. А в foreach да, завожу столько переменных, сколько нужно.

N>И что так лучше читается вместо добавления одного метода, который этот форыч инкапсулирует?


Оператор foreach вместо метода совершенно точно делает код прозрачнее.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[10]: Полезняшка для dictionary
От: -n1l-  
Дата: 01.05.16 07:41
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Какими большими выражениями? Выражения это pure код, там никаких foreach быть не может. А в foreach да, завожу столько переменных, сколько нужно.


ну типа — collection.Select(...).Where(...).GroupBy(...).SelectMany(...)

Вы это все в форыч засовываете?
Или отдельную переменную делаете, query например.

AVK>Оператор foreach вместо метода совершенно точно делает код прозрачнее.

Почему?
Re[11]: Полезняшка для dictionary
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 01.05.16 18:38
Оценка:
Здравствуйте, -n1l-, Вы писали:

N>ну типа — collection.Select(...).Where(...).GroupBy(...).SelectMany(...)

N>Вы это все в форыч засовываете?
N>Или отдельную переменную делаете, query например.

Обычно отдельную. А что?

AVK>>Оператор foreach вместо метода совершенно точно делает код прозрачнее.

N>Почему?

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