Ну вот… я ожидал, что появился способ заставить сам рантайм проверять типы (видимо исполняя Тайпскрипт без компиляции?), а тут про декораторы )) Но за статью все равно спасибо – в ней много полезной информации. Хотя я бы ещё добавил что-нибудь про type guards – мне кажется, они были бы тут в тему.
В общем чуда не случилось. Выкинул из вашего кода всякую ересь типа Моков (автоматом ушел тот баг с Setup), Автофаков, Тасков. Вынес парсинг за переделы теста и получилось то, что и ожидалось — Рефлексия гораздо медленнее!
public static IStorage InstanceDb()
{
var mock = new Mock<HabraDbContext>();
mock.Setup(x => x.ContactMapSchemas).ReturnsDbSet(GetFakeData());
return mock.Object;
}
Setup надо выставлять перед каждым вызовом (или лучше вообще эти моки убрать), а у вас получается, что "FakeData" возвращается всего один раз, при первом вызове, а потом null, что отключает всю работу по созданию Contact .
Подписочная модель не так уж и плоха и, зачастую, может быть выгодна не только производителю, но и покупателю. Разработка ПО меняется очень быстро – появляются новые языки, фреймворки, старые меняются до неузнаваемости и все это требует поддержки со стороны сред разработки. В случае с разовой покупкой, она с большой вероятностью, устареет в течение двух-трех лет, и придется покупать новую версию. С подпиской же, у вас всегда будет самая актуальная версия. К тому же надо учитывать, что технологический стек может полностью поменяться и продукт перестанет быть актуальным.
Для бизнеса так и вообще сплошная выгода – капитальные затраты сразу превращаются в операционные.
Безусловно, все преимущества может убить неадекватная стоимость подписки, но такие ошибки рынок всегда исправляет (так или иначе).
Автора прекрасно понимаю, так как сам сделал похожий “велосипед” (только под Ангуляр). И статью про его принципы написал. И хотел даже сделать её перевод на Хабре, но пока не решился, поскольку опасаюсь описанной автором реакции.
Думаю, что причина подобного отношения — это не то, что кто-то создал “велосипед”, а то, что этот кто-то не обладает достаточным авторитетом в глазах остальных разработчиков. Если бы эту библиотеку сделал Гугл, Фейсбук или, на худой конец, Яндекс, то её возможно критиковали бы, но никто бы не назвал её “велосипедом”.
С другой стороны, принцип “авторитета” отнюдь не плох, так как попросту позволяет экономить время, не тратя его на подробный анализ тысяч схожих “поделок”. Возможно, среди этих “поделок” на самом деле есть “брильянты”, тщательно обработанные их авторами, но их мало и шанс найти что-то выдающееся невелик, поэтому и берут известное решение так как оно в 99% случаев не будет самым худшим, а в 99% случаев это и достаточно.
Кстати да, этого я не заметил. Подозреваю, что в исходной статье опечатка.
Вот там такой комментарий есть:
Nice article, thanks! One concern: are you sure using WaitAny() / WaitAll() is a good solution for the last-mentioned case? I would suggest using WhenAny() / WhenAll() instead
Используйте Task.WaitAll, чтобы дождаться завершения всех задач.
Если, есть несколько тасков и нужно из каждого из них получить результат, то я бы не рекомендовал использовать Task.WaitAll, так как во многих случаях применение этой функции избыточно и ведет к более громоздкому коду.
Вот такого подхода обычно бывает достаточно:
Task<string> nameRequest = GetNameAsync();
Task<int> ageRequest = GetAgeAsync();
//Таски работают параллельно
string name = await nameRequest ;
int age = await ageRequest;
Ну… пока у меня только есть две Монады, реализованные подобным образом, и в теории можно было бы объединить их в одну, но вот по поводу трансформеров не уверен.
Про исключения тут уже есть комментарии. Вкратце, не нужно их использовать для реализации программной логики.
Maybe помогает избавится от избыточной условной логики, там где она действительно избыточна. Безусловно, можно привести 100500 примеров (с обоснованием), где применять Maybe не стоит, поэтому не надо применять Maybe (как, в принципе, и любой другой паттерн, подход, фреймворк и т. д.) там, где ее применять не стоит.
MaybeParse() вернет Maybe, await MaybeParse() вернет либо int, либо завершит выполнение текущей асинхронной функции (в примере это "Sum") с результатом "Nothing" (если её тип Maybe). Если её тип не Maybe, а например Task то надо вызвать await MaybeParse().GetMaybeResult() что бы получить структуру в которой будет финальный результат или "Nothing".
Где-то обработать из IsNothing(), безусловно, придётся. Но это будет всего одна проверка вместо N+1
Паттерн "Монада Maybe" применяется там где отсутствие (правильного?) значения не является проблемой и допускается логикой программы. Но, кстати, ничто не мешает добавить описание причины остановки выполнения цепочки вызова в MaybeResult, например:
Maybe<int> Parse(string str)
=> int.TryParse(str, out var result)
? result
: Maybe<int>.Nothing($"Could not parse: {str}");
IsNothing() — можно обработать только в самом конце цепочки вызовов, иначе пришлось бы делать проверку на каждом этапе, например:
int? Sum(string arg1, string arg2, string arg3)
{
int result = 0;
int tmp;
if(!int.TryParse(arg1, out tmp))
{
return null;
}
result += tmp;
if(!int.TryParse(arg2, out tmp))
{
return null;
}
result += tmp;
if(!int.TryParse(arg3, out tmp))
{
return null;
}
result += tmp;
return result;
}
вместо:
Maybe<int> Sum(string arg1, string arg2, string arg3)
{
int result = 0;
result += await MaybeParse(arg1);
result += await MaybeParse(arg2);
result += await MaybeParse(arg3);
}
Ну вот… я ожидал, что появился способ заставить сам рантайм проверять типы (видимо исполняя Тайпскрипт без компиляции?), а тут про декораторы )) Но за статью все равно спасибо – в ней много полезной информации. Хотя я бы ещё добавил что-нибудь про type guards – мне кажется, они были бы тут в тему.
I think that in 2020 "JetBrains Rider" should be definitely presented in the list
В общем чуда не случилось. Выкинул из вашего кода всякую ересь типа Моков (автоматом ушел тот баг с Setup), Автофаков, Тасков. Вынес парсинг за переделы теста и получилось то, что и ожидалось — Рефлексия гораздо медленнее!
Вот исходники (извините, что я запихал все в один файл :) ): https://gist.github.com/0x1000000/668bb6286042bceba6ecb0f40c1d91d3
Нашел одну из проблем:
Setup надо выставлять перед каждым вызовом (или лучше вообще эти моки убрать), а у вас получается, что "FakeData" возвращается всего один раз, при первом вызове, а потом null, что отключает всю работу по созданию Contact .
SetMethod.Invoke, на самом деле, работает чуть быстрее (на 5-10%) так как SetValue собственно к нему и обращается:
Странные у вас результаты получились. Написал самый простой “копирователь свойств” и как не крути, но рефлексия в 60 раз медленнее. Вот тут исходники: https://gist.github.com/0x1000000/5ee4d6d2fdf426f64b60a2cbd3263a4a
Подписочная модель не так уж и плоха и, зачастую, может быть выгодна не только производителю, но и покупателю. Разработка ПО меняется очень быстро – появляются новые языки, фреймворки, старые меняются до неузнаваемости и все это требует поддержки со стороны сред разработки. В случае с разовой покупкой, она с большой вероятностью, устареет в течение двух-трех лет, и придется покупать новую версию. С подпиской же, у вас всегда будет самая актуальная версия. К тому же надо учитывать, что технологический стек может полностью поменяться и продукт перестанет быть актуальным.
Для бизнеса так и вообще сплошная выгода – капитальные затраты сразу превращаются в операционные.
Безусловно, все преимущества может убить неадекватная стоимость подписки, но такие ошибки рынок всегда исправляет (так или иначе).
Автора прекрасно понимаю, так как сам сделал похожий “велосипед” (только под Ангуляр). И статью про его принципы написал. И хотел даже сделать её перевод на Хабре, но пока не решился, поскольку опасаюсь описанной автором реакции.
Думаю, что причина подобного отношения — это не то, что кто-то создал “велосипед”, а то, что этот кто-то не обладает достаточным авторитетом в глазах остальных разработчиков. Если бы эту библиотеку сделал Гугл, Фейсбук или, на худой конец, Яндекс, то её возможно критиковали бы, но никто бы не назвал её “велосипедом”.
С другой стороны, принцип “авторитета” отнюдь не плох, так как попросту позволяет экономить время, не тратя его на подробный анализ тысяч схожих “поделок”. Возможно, среди этих “поделок” на самом деле есть “брильянты”, тщательно обработанные их авторами, но их мало и шанс найти что-то выдающееся невелик, поэтому и берут известное решение так как оно в 99% случаев не будет самым худшим, а в 99% случаев это и достаточно.
Спасибо за статью, но на мой взгляд, отсутствие примеров с кодом не делает это введение понятнее.
Промисы — это опционально. Основной режим это, конечно, синхронные изменения.
Пример, приведенный выше, выглядел бы вот так:
или
"статики" гарантируют, что не будет сайд эффектов
Помучился я с этими mobX и Rx и в итоге написал свою библиотечку. В в ней можно написать вот так:
Кстати да, этого я не заметил. Подозреваю, что в исходной статье опечатка.
Вот там такой комментарий есть:
А результат то где?
Если, есть несколько тасков и нужно из каждого из них получить результат, то я бы не рекомендовал использовать Task.WaitAll, так как во многих случаях применение этой функции избыточно и ведет к более громоздкому коду.
Вот такого подхода обычно бывает достаточно:
Ну… пока у меня только есть две Монады, реализованные подобным образом, и в теории можно было бы объединить их в одну, но вот по поводу трансформеров не уверен.
Спасибо! Исправил
Вот первая строчка из статьи на Википедии:
await MaybeParse(arg1)
возвращает intIsNothing() — можно обработать только в самом конце цепочки вызовов, иначе пришлось бы делать проверку на каждом этапе, например:
вместо: