вторник, 6 января 2015 г.

Ретроспектива 2014

Прошел Новый Год, на носу Рождество, а значит пришло время подводить итоги прошедшего года.

Этот год был практически полностью посвящен паттернам и принципам проектирования. В основном из-за того, что я таки решился на написание книги, а публикация черновых материалов в блоге дает очень полезную обратную связь и повышает мотивацию.

Специфичных постов о языке C# практически не осталось, хотя хорошо это или плохо, сказать сложноJ. В этом году я планирую добить книгу по паттернам, а значит, часть постов будет посвящено именно этой теме. С переходом в Майкрософт времени стало немного меньше, но желание писать пока не убавилось.

Ниже представлен перечень наиболее интересных и значимых постов, сгруппированных по тематике. Гляньте, а вдруг чего-то интересное пропустили!

SOLID принципы
Паттерны проектирования
Философия программирования
Другое
C#/.NET
Книги

З.Ы. Я беру перерыв в блоггинге где-то на месяц. Надеюсь, что этого времени хватит, чтобы добить книгу по паттернам и отправить ее для редактирования.

понедельник, 29 декабря 2014 г.

О менторах и менторстве

В некотором роде этот «капитанский» пост можно считать продолжением популярного прошлогоднего поста Увлеченный программист, в котором тема менторства уже поднималась.

Многие из нас хотели бы в жизни встретить настоящего Учителя, который бы раскрыл все секреты бытия и научил бы читать регулярные выражения, написанные другим человеком. Десятку человек в мире повезло и они встретили своего мудрого наставника, когда он им был нужен и они были готовы воспринимать его мудрость. Остальным миллионам бедных программистов повезло не так сильно.

Перед переходом в Майкрософт один из моих коллег восторгался тем, что у меня будет возможность работать с лучшими специалистами индустрии и впитывать мудрость их каждого коммита. И хотя возможность пообщаться напрямую со Стивеном Таубом, Мэдсом Торгесеном или Гербом Саттером очень радует, но вероятность стать их настоящим подмастерьем ничтожно мала.

понедельник, 22 декабря 2014 г.

Фильтры исключений в C# 6.0

Одной из новых возможностей языка C# 6.0 являются фильтры исключений.

Общая идея довольно простая: рядом с блоком catch появляется возможность задать некоторый предикат, который будет определять, будет ли вызван блок catch или нет.

clip_image002

Данный вариант синтаксиса доступен в публичной версии VS2015, но он будет изменен в финальной версии языка C#. Вместо if будет использоваться ключевое слово when.

четверг, 11 декабря 2014 г.

Интерфейсы vs. Абстрактные классы

DISCLAIMER: ниже речь идет об интерфейсах и абстрактных классах на платформе .NET. Большая часть рассуждений применима и к другим языкам, с разделением понятий интерфейсов и классов.

Между интерфейсами и абстрактными классами нет особой разницы с точки зрения моделирования. И то, и другое определяет «абстрактный интерфейс» семейства объектов и разница есть лишь в том, существует ли поведение по умолчанию или нет.

Когда мы моделируем предметную область нет разницы между интерфейсом IPrecondition и абстрактным классом Precondition. Оба эти понятия моделируют семейство предусловий, но первый лишь декларирует открытый интерфейс этого семейства, а второй позволяет ограничить и использовать повторно часть реализации.

Разница появляется с точки зрения языка программирования, разработчики которого решили не морочить голову с полноценным множественным наследованием: «ромбовидным наследованием», конфликтами имен из разных базовых классов и т.п. вещами.

В языках с множественным наследованием, таких как С++ или Eiffel, понятие интерфейса отсутствует, в нем просто отпадает необходимость. Отсутствие полноценного множественного наследования влияет на то, как мы проектируем иерархию классов.

понедельник, 8 декабря 2014 г.

Для чего нужны интерфейсы?

В чем сила интерфейсов? Сила интерфейсов в правде слабости системы типов!

Принято считать, что интерфейсы предназначены для моделирования абстракций и обеспечения слабой связанности (loose coupling). Звучит умно, но что это значит?

Что дают интерфейсы?

Наследование моделирует семейство объектов с общим поведением. Интерфейс и абстрактный класс определяет «протокол» этого семейства, а наследники определяют конкретную реализацию. Разные виды предусловий можно спрятать за интерфейсом IPrecondition, разные виды стратегий сортировки – за ISorter, разные виды импортеров/экспортеров – за Importer/Exporter.

Наличие интерфейсов/абстрактных классов позволяет думать о задаче более абстрактно, не вдаваясь в подробности, какая конкретная разновидность используется. Абстрактность интерфейсов позволяет сосредоточиться на главном, игнорируя второстепенные детали. Отсюда вытекает распространенное убеждение, что интерфейс моделируют абстракцию.

четверг, 27 ноября 2014 г.

DI vs. DIP vs. IoC

Существует три схожих понятия, связанных передачей и управлением зависимостями, в каждом из которых есть слово “инверсия” (inversion) или “зависимость” (dependency):

  • IoC – Inversion of Control (Инверсия управления)
  • DI – Dependency Injection (Внедрение зависимостей)
  • DIP – Dependency Inversion Principle (Принцип инверсии зависимостей)

Подливает масло в огонь рассогласованность использования этих терминов. Так, например, контейнеры иногда называют DI-контейнерами, а иногда IoC-контейнерами. Большинство разработчиков не различает DI и DIP, хотя за каждой из этих аббревиатур скрываются разные понятия.

среда, 12 ноября 2014 г.

Когда предусловия не являются предусловиями

UPDATE: библиотека Code Contract знает о тонкостях реализации таких возможностей как async/await и блоков итераторов. Поэтому описанные ранее проблемы касаются лишь старых (legacy) предусловий, основанных на if-throw. Если вы зашли сюда первый раз, то просто не обращайте внимания на этот абзац!

Что такое предусловие? Это некоторое утверждение, которое должно быть истинным во время вызова метода, причем за его истинность отвечает вызывающая сторона. Предусловия включают в себя проверку аргументов или внутреннего состояния объекта, а его нарушение проявляется в генерации вызываемым кодом исключений ArgumentException для невалидных аргументов, и InvalidOperationException для вызова метода в невалидном состоянии объекта.

Другими словами, предусловия гарантируют, что вызывающий код находится в нужном состоянии и ему передали все нужные данные для выполнения своей работы:

// class CustomStream
public Task<string> ReadString(int
position)
{
   
if (position < 0
)
       
throw new ArgumentOutOfRangeException("position"
);
   
if
(CanRead)
       
throw new InvalidOperationException("Stream is not readable"
);

   
return Task.FromResult("42");
}