Friday, April 18, 2014

Обзор встречи Kiev ALT.NET

Здравствуйте, уважаемые читатели моего блога. Эта статья посвящена мероприятию, которое мне посчастливилось посетить − Kiev ALT.NET. Конференция была организована компанией Ciklum, за что хотелось бы выразить огромною благодарность организаторам, поскольку все было сделано на высшем уровне. Встреча проходила на 20-ом этаже, в очень просторном помещении, в обстановке, которая чем-то напоминает домашнюю. Ниже приведена картинка офиса, в котором проходила конференция.
Только все пуфики были расположены полумесяцем вокруг проектора. С места, в котором была встреча, открывается бесподобный вид на Киев.  Я взял с блога фото панорамы, поскольку из-за дождя фотографии у меня получились невысокого качества.
Также позитивным моментом была возможность выпить сок или чай/кофе, угоститься печеньем, чипсами и конфетами. После того, как все расположились, нам рассказали несколько слов о докладах, которые будут представлены на встрече. В начале конференции также поступило предложение от организаторов продолжить обсуждения конференции за кружкой пива при желании и наличии дополнительных вопросов к докладчикам. По семейным обстоятельствам я не смог остаться на этом мероприятии, но думаю, что оно состоялось. Также была озвучена новость о том, что данную встречу планируют сделать регулярной. Это не может не радовать, так как доклады, которые были представлены на конференции, были профессионально подготовленные и интересные, что немаловажно. 
На встрече было представлено два доклада из запланированных трех. Не был представлен доклад "Canopy: F# DSL for Webdriver от Serhiy Kalinets", так как предыдущие доклады оказались настолько увлекательными, что заняли все время, выделенное на встречу.  Первым выступил Аким Бойко (Akim Boyko) со своим докладом "FsCheck: Property-based testing for F# and C#". Ниже привел фото автора доклада.
До этого мне приходилось слушать доклады этого автора, поэтому не было сомнений в том, что материал будет интересен. Один из докладов этого автора я впервые услышал, когда решил познакомиться с проектом Roslyn и нашел один из его докладов "Метапрограммирование в .Net: RoslynCTP". Все время на встрече я старался нотировать интересные вещи, почерпнутые с докладов, и пока они держатся в голове, хотел бы поделиться ими с вами. 
Началом доклада было банальное ознакомление с библиотекой FsCheck, которая предназначена для случайного и автоматического тестирования, основанного на свойствах. Также нам кратко рассказали о выборках тестирования с помощью функций forAll, throws, within, trivial и atLeastOne.  Записывал по памяти, так что могут быть опечатки. Также были кратко рассмотрены аналогичные механизмы тестирования для языка Scala – ScalaCheck и другие, которые, к сожалению, я не записал, понадеявшись на свою память. Забыл упомянуть тот факт, что, по сути, FsCheck работает с языком F#. Подружить его с языком C# можно, но очень проблематично. Одной из проблем, почему это составляет проблему, являются Generators – генераторы, которые генерируют входные данные для тестируемых методов.
Основное отличие от стандартных Unit тестов, к которым мы привыкли при использовании подхода с TDD или BDD, состоит в том, что FsCheck позволяет модифицировать входную последовательность по ходу выполнения.  Также мы можем указать, сколько генераций нам необходимо выполнить для тестируемого метода. По умолчанию в FsCheck задано 100 итераций, что бывает очень мало, если нужно протестировать, например, наличие вершины в графе. Частично такую возможность в юнит-тестах, которую позволяет покрыть FsCheck, можно сделать с помощью TestCase + Contracts. При написании тестов для FsCheck существует такое понятие, как Shrinkers – это минимальный набор входных данных, на которых получается получить ошибку. Также отличие FsCheck от стандартных юнит-тестов – в том, что позволяют проанализировать полностью выполнения тестирование метода, в то время как юнит-тест свалится при первой же ошибке. 
Основная проблема FsCheck для языка C# состоит в сложности написания генераторов. Написать генераторы для F# – процесс непростой, а для C# он намного сложнее. Во-первых, он слабо документирован, и синтаксис местами не понятен. Вторая проблема заключается в том, что все результаты тестирования выводятся в Output. Подружить с FsCheck с классическими юнит-тестами сложно. Хотя существует интеграция FsCheck с xUnit, если верить докладу, потому что отдельно я не разбирал эту тему. Поскольку единственный язык, который понимают юнит-тесты, об ошибке выполнения, есть бросание исключения, то с парсингом выходного результата, который нам дает FsCheck, есть множество проблем. 
Иногда процесс написания последовательности для теста может быть намного сложнее, чем сам тест. Одним из плюсов, о которых говорил автор доклада , является то, что подход с FsCheck заставляет разработчика думать о своих тестах и коде в пределах контрактов. К сожалению, я с этим не согласен, поскольку думать терминами контрактов можно уже сейчас, и подружить контракты с юнит-тестами можно без проблем. Контракты, которые уже есть в .NET 4.0, могут служить неплохим дополнением к тестам. По поводу того, как можно к своему коду подходить с точки зрения контрактов, рекомендую статьи известного в Украине MVP Сергея Теплякова "Контракты vs Юнит тесты" и "Контракты, состояние и юнит-тесты". Я к контрактам отношусь довольно предвзято, но отрицать их полезность в подходе к разработке не могу. Пожалуй, с докладом о FsCheck закончу, остановившись на втором докладе, ради которого, признаться честно, я и хотел пойти на встречу. Этот доклад  "C# Under the hood от Antya Dev " (Антон Молдован). Ниже привел фото автора.
Доклад был сделан профессионально и интересно. Автор доклада часто употреблял много жаргонных словечек из программистского лексикона, что придавало докладу особый колорит. Материал затрагивал несколько интересных вещей, по которым я и пройдусь. Доклад состоял из пяти условных частей:
  • switch;
  • lifted operators;
  •  lambda expressions;
  • async/await;
  • dynamic.
Теперь немного расскажу о том, что подразумевал под собой каждый из пунктов выше.  Что вы знаете об операторе switch? Если вы знаете, как работает оператор switch на уровне кода и как он оптимизирует свои запросы, то эта часть для вас может быть неинтересной. Но, как оказалось, я заблуждался насчет некоторых моментов работы switch.  Одним из таких нюансов есть использование данного оператора для сравнения строк. Я всегда думал, что для такого кода
string a = "f";
switch (a)
{
       case "a":
             Console.WriteLine("a"); break;
       case "b":
             Console.WriteLine("b"); break;
       case "c":
             Console.WriteLine("c"); break;
       case "d":
             Console.WriteLine("d"); break;
       case "e":
             Console.WriteLine("e"); break;
       case "f":
             Console.WriteLine("f"); break;
}
компилятором строится таблица переходов (хеш-таблица), и в данном контексте switch работает быстро. Оказывается я заблуждался, на уровне Il кода происходит самое обычное сравнение строк, если значений в операторе switch меньше 7 (актуально для строк); если больше или равно 7-ми case значениям, тогда уже строится хеш-таблица. Ниже приведен IL код, который подтверждает эти слова.  
// Methods
    .method private hidebysig static
        void Main (
            string[] args
        ) cil managed
    {
        // Method begins at RVA 0x23b0
        // Code size 171 (0xab)
        .maxstack 2
        .entrypoint
        .locals init (
            [0] string a,
            [1] string CS$0$0000
        )

        IL_0000: ldstr "f"
        IL_0005: stloc.0
        IL_0006: ldloc.0
        IL_0007: dup
        IL_0008: stloc.1
        IL_0009: brfalse IL_00a4

        IL_000e: ldloc.1
        IL_000f: ldstr "a"
        IL_0014: call bool [mscorlib]System.String::op_Equality(string, string)
        IL_0019: brtrue.s IL_005e

        IL_001b: ldloc.1
        IL_001c: ldstr "b"
        IL_0021: call bool [mscorlib]System.String::op_Equality(string, string)
        IL_0026: brtrue.s IL_006a

        IL_0028: ldloc.1
        IL_0029: ldstr "c"
        IL_002e: call bool [mscorlib]System.String::op_Equality(string, string)
        IL_0033: brtrue.s IL_0076

        IL_0035: ldloc.1
        IL_0036: ldstr "d"
        IL_003b: call bool [mscorlib]System.String::op_Equality(string, string)
        IL_0040: brtrue.s IL_0082

        IL_0042: ldloc.1
        IL_0043: ldstr "e"
        IL_0048: call bool [mscorlib]System.String::op_Equality(string, string)
        IL_004d: brtrue.s IL_008e

        IL_004f: ldloc.1
        IL_0050: ldstr "f"
        IL_0055: call bool [mscorlib]System.String::op_Equality(string, string)
        IL_005a: brtrue.s IL_009a

        IL_005c: br.s IL_00a4

        IL_005e: ldstr "a"
        IL_0063: call void [mscorlib]System.Console::WriteLine(string)
        IL_0068: br.s IL_00a4

        IL_006a: ldstr "b"
        IL_006f: call void [mscorlib]System.Console::WriteLine(string)
        IL_0074: br.s IL_00a4

        IL_0076: ldstr "c"
        IL_007b: call void [mscorlib]System.Console::WriteLine(string)
        IL_0080: br.s IL_00a4

        IL_0082: ldstr "d"
        IL_0087: call void [mscorlib]System.Console::WriteLine(string)
        IL_008c: br.s IL_00a4

        IL_008e: ldstr "e"
        IL_0093: call void [mscorlib]System.Console::WriteLine(string)
        IL_0098: br.s IL_00a4

        IL_009a: ldstr "f"
        IL_009f: call void [mscorlib]System.Console::WriteLine(string)

        IL_00a4: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
        IL_00a9: pop
        IL_00aa: ret
    } // end of method Program::Ma
Пожалуй, перейдем ко второй теме и поговорим о lifted operators. Это операторы, которые позволяют работать безопасно с nullable типами данных. Например, валидной является запись
public static int? Result(int? a, int? b)
{
       return a + b;
}
И другие нюансы, связанные с nullable типами.
Следующая тема Lambda Expression затронула удивительный мир монад. Автор доклада почему-то затронул только ту часть лямбда-выражений, которая строится вокруг точечной нотации. К сожалению, в этой теме для себя я не узнал ничего нового, правда, причина этого была в том, что я уже знаком с монадами со статей Ерика Липперта в его блоге Fabulous Adventures In Coding. Правда, автор рассказывал о монадах довольно интересно. Эта тема была очень беглой и, по сути, автор доклада ознакомил слушателей только с монадой MayBe и показал пример ее использования. Это тоже очень неплохо из-за ограниченности по времени доклада.
Следующей интересной темой лично для меня было объяснение того, как работает async/await в C#. Также был создал искусственный пример, который эмулировал работу с async/await, как это делает компилятор. Понравился тот момент, что автор указал на популярную ошибку при использовании async/await: использование явно метода WaitAll или Result, что, по сути, вешало основной поток. После того как был продемонстрирован пример, я понял, почему это происходило.
Последняя тема, которая вызвала дискуссию в зале, была тема, связанная с dynamic. Автор доклада рассказал невзначай о своем фреймворке, над которым он работает (KingAOP). Сама тема не касалась этого фреймфорка и он был затронут вскользь, но я специально самостоятельно позже посмотрел, на чем основывается данный фреймворк (в основе лежит dynamic и IDynamicMetaObjectProvider и фреймфорк PostSharp) и не смог придумать ему применения, наверное, больше из-за своей нелюбви к PostSharp. Сам же доклад о dynamic очень понравился, поскольку рассказал о том, как работает данный тип изнутри IL. Но он вызвал также множество вопросов и дискуссий по поводу DLR, которая была затронута в рамках этого доклада. Лично я выразился о том, что DLR на данный момент не доделана до конца, и что dynamic (ExpandoObject/Dynamic) – лишь верхушка айсберга, а другие языки, как IronPython и IronRuby, не прижились и, по сути, являются недоделанными частями DLR. Также очень тормозит взаимодействие между C# кодом и IronPython через ScriptEngine. Также на взаимодействие накладывается куча ограничений. В целом, тема была позитивной и приоткрыла некоторые занавесы мира C#.

Надеюсь, этот краткий обзор позволит вам оценить пользу тем, которые были озвучены на встрече, и на следующую встречу будет еще больше желающих разработчиков. 

No comments:

Post a Comment