вторник, 28 августа 2012 г.

Параметризованные юнит тесты

DISCLAIMER: все примеры в этой статье написаны с использованием NUnit, однако все их можно применять и с другими тестовыми фреймворками, как xUnit и MbUnit.

Юнит тесты – это отличная штука; они помогают навести порядок в дизайне приложения, являются незаменимым средством при рефакторинге, позволяют делать процесс разработки более управляемым и т.п. Но как и любой другой инструмент юнит тесты тоже можно использовать неправильно. Если с плохо поддерживаемым кодом все мы хоть как-то привыкли бороться, поскольку сталкиваемся с ним постоянно, но когда на каждую строку г#%@&-кода приходится еще пара строк таких же по качеству тестов, то положение становится каким-то совсем уж невеселым.

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

понедельник, 20 августа 2012 г.

Об идиоме RAII и классе ReaderWriterLockSlim

Идиома RAII (Resource Acquisition Is Initialization) берет свое начало в языке С++ и заключается в том, что некоторый ресурс захватывается в конструкторе объекта, и освобождается в его деструкторе. А поскольку деструктор локальных объектов вызывается автоматически при выходе из метода (или просто из области видимости) не зависимо от причины (нормальное завершение метода или при генерации исключения), то использование этой идиомы является самым простым и эффективным способом написания сопровождаемого C++ кода, безопасного с точки зрения исключений.

При переходе к «управляемым» платформам, таким как .NET или Java, эта идиома в некотором роде теряет свою актуальность, поскольку освобождением памяти занимается сборщик мусора, а именно память была самым популярным ресурсом, о котором приходилось заботиться в языке С++. Однако поскольку сборщик мусора занимается лишь памятью и никак не способствует детерминированному освобождению ресурсов (таких как дискрипторы операционной системы), то идиома RAII все еще применяется и в .NET, и в Java, пусть мало кто из разработчиков знает об этом замысловатом названии.

вторник, 14 августа 2012 г.

Интересное из MSDN Magazine 2009-2012

Я не знаю, как другие, но лично я в последнее время не так часто читаю какие-то статьи из MSDN Magazine (не путать с MSDN). Может у этих статей релевантность не очень высокая, что я на них из поисковиков попадаю не часто, может быть юзабилити у веб-морды не очень для ручного поиска и категоризации материала, а может быть и то и другое.

Но, несмотря на это, в MSDN Magazine писали и продолжают писать очень интересные авторы и многие статьи заслуживают внимания. Поэтому я решил просмотреть выпуски за последние 4 года и выписать заинтересовавшие меня статьи по разным тематикам. Поскольку облака, веб, WP7 и SQL Server мне лично не слишком интересны, то в этой подборке ссылок информации по этим темам не будет (так что если это интересно вам, то придется проделать подобную же процедуру самостоятельно). В мой же список вошли следующие темы: многопоточное и параллельное программирование, .NET in general, паттерны и практики, распределенные системы, функциональное программирование и некоторые другие темы.

Так что если мой список интересов пересекается с вашим, то вы здесь наверняка найдете немало полезной информации. Все статьи разбиты по рубрикам и внутри каждой рубрики располагаются от самых свежих к самым старым; многие статьи на русском языке, хотя некоторые есть только в оригинале (хотя вы всегда можете на страничке выбрать нужный вам язык).

вторник, 7 августа 2012 г.

Перегрузка и наследование

Существует определенный набор возможностей в любом языке программирования для понимания которых нужно просто знать, как они реализованы. Вот, например, замыкания; это не сверх сложная концепция, но знание того, как этот зверь устроен позволяет делать определенные выводы относительно поведения замыканий с переменными цикла. Тоже самое касается вызова виртуальных методов в конструкторе базового класса: здесь нет одного правильного решения и нужно просто знать, что именно решили разработчики языка и будет ли вызываться метод наследника (как в Java или C#), или же «полиморфное» поведение в конструкторе не работает и будет вызываться метод базового класса (как в С++).

Еще одним типом проблемы у которой нет идеального решения, является совмещение перегрузки методов (overloading) и переопределения (overriding) метода. Давайте рассмотрим следующий пример. Предположим, у нас есть пара классов, Base и Derived, с виртуальным методом Foo(int) и невиртуальным методом Foo(object) в классе Derived:

среда, 1 августа 2012 г.

Duck typing или “так ли прост старина foreach?”

Я думаю, что многие разработчики знают, что цикл foreach в языке C# не так прост, каким он кажется на первый взгляд. Для начала давайте ответим на вопрос: «А что нужно, чтобы конструкция foreach успешно компилировалась?». Интуитивным ответом на этот вопрос кажется что-то типа: «Реализация классом интерфейса IEnumerable или IEnumerable<T>.». Однако, это не так, ну, или не совсем так.

Полный ответ на этот вопрос такой: «Для того чтобы конструкция foreach успешно компилировалась необходимо, чтобы у объекта был метод GetEnumerator(), который вернет объект с методом MoveNext() и свойством Current, а если такого метода нет, то тогда будем искать интерфейсы IEnumerable и IEnumerable<T>».

Причин у такого «утиного» поведения две.