Этим постом я начинаю перевод замечательной серии статей Джона Скита под названием «Edulinq: Reimplementing LINQ to Objects». С оригинальными записями можно ознакомиться в виде постов, либо в формате электронной книги. Просьба указывать на неточности перевода в комментариях.
Примерно полтора года назад я выступил на дне DDD в Рединге, стараясь реализовать столько LINQ to Objects, сколько это было возможно за час. Основываясь на поступивших отзывах, я быстро продвинулся вперед… и по-прежнему был далёк до финиша. Тем не менее, я до сих пор считаю, что это интересное упражнение, поэтому я решил, что повторю его в свободное время, попутно ведя блог. Всё будет помечено тэгом "Edulinq", поскольку это самый простой способ получить все части в правильном порядке без других моих постов.
Общий подходПлан – имплементировать весь LINQ to Objects, объясняя каждый метод (или группу методов) в посте блога. Я собираюсь делать код рабочего качества, но я не буду включать никакой XML документации: я и так пишу, как это работает, и не собираюсь делать это дважды. Я буду добавлять оптимизацию там, где это необходимо, надеюсь, делая лучше, чем собственно сам LINQ to Objects.
Подход будет очень прост: для каждого метода LINQ я буду писать модульные тесты (большинство из которых я не буду показывать в постах) и убеждаться, что они работают относительно обычной .NET имплементации. Далее я закомментирую директиву using для System.Linq, и вместо неё добавлю такую же для JonSkeet.Linq. Тесты провалятся, я имплементирую методы, и постепенно они опять заработают. Это не совсем классический подход TDD, но он достаточно хорошо работает.
Я буду создавать запись в блоге для каждого оператора LINQ, возможно включая весь код, но только «интересные» тесты. Я буду выделять важные паттерны по мере их появления – это часть нашей цели, естественно.
В конце каждого поста я буду добавлять ссылку на «код до настоящего момента». Ради тех, кто будет искать эти записи в будущем, я буду держать загрузки отдельно пронумерованными, вместо обновления единственной версии. Я надеюсь, что код будет просто расти, но осмеливаюсь сказать, что по пути также будут производиться и некоторые модификации.
Цель – не закончить с LINQBridge: я буду использовать .NET 3.5 (в основном для того, чтобы использовать методы расширения без создания своих собственных атрибутов) и я точно не собираюсь начинать беспокоиться об установщиках и т.п. Цель всего этого исключительно образовательная: если вы пройдете через все эти записи, вы получите углублённое понимание работы LINQ в общем и LINQ to Objects в частности. Например, такая тема, как отложенное выполнение часто оказывается понята неправильно: взгляд на реализацию может хорошо всё прояснить.
ТестированиеМодульные тесты будут написаны при помощи NUnit (только ради моего с ним ознакомления). Довольно очевидно, что одна из вещей, которую нам придется часто тестировать – это проверка, являются ли две последовательности равными. Мы будем делать это при помощи класса TestExtensions из MoreLINQ (который я только что добавил в проект). На нетбуке, который я, возможно, буду использовать для написания большей части кода, установлен только C# Express 2010, поэтому я собираюсь использовать внешний NUnit GUI. Я установил его стартовым приложением в файле проекта… чего вы не сможете сделать из C# Express напрямую, но редактировать файл проекта просто, следует лишь добавить следующее:
<startaction>Program</startaction>
<startprogram>C:\Program Files\NUnit-2.5.7.10213\bin\net-2.0\nunit-x86.exe</startprogram>
Это – довольно безобразный хак, но он работает. «Дополнительным параметром командной строки» будет JonSkeet.Linq.Tests.dll: текущим каталогом является каталог bin/debug, поэтому всё хорошо. Очевидно, что если вы хотите запускать тесты сами, и у вас установлен ReSharper или что-то подобное, вы сможете видеть результаты, интегрированные в Visual Studio.
Несмотря на то, что я надеюсь писать код рабочего уровня, я сомневаюсь, что в нём будет столько модульных тестов, сколько я бы действительно писал для рабочего кода. Я ожидаю, что даже в этом случае количество строк тестового кода уменьшит количество строк рабочего кода. Существует просто огромное количество исключительных случаев. Помните, что цель здесь – это исследовать интересные аспекты LINQ.
Структура кодаТак же, как и реальный LINQ to Objects, я буду создавать огромный статический класс Enumerable, но я буду делать это, используя разделяемые классы с одним название метода (но с несколькими перегрузками) на файл. Поэтому, к примеру, Where будет имплементирован в Where.cs и тестирован в WhereTest.cs.
Первая порция кодаДоступен первый zip файл: Linq-To-Objects-1.zip. Он пока не содержит рабочего кода – только 4 теста для Where, чтобы я мог проверить, что NUnit работает правильно. Следующая остановка… имплементация Where.
Комментариев нет:
Отправить комментарий