Автор: Sergey Teplyakov

След. запись: Паттерн Стратегия

Посты серии:

  • Паттерн Стратегия
  • Паттерн Шаблонный Метод
  • RAII в C#. Локальный Метод Шаблона vs. IDisposable
  • Паттерн Посредник

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

Так, когда в начале 90-х на арене программного мира появились паттерны проектирования, многие начали мечтать о том, что благодаря им даже бизнес-пользователи и 1С программисты смогут собирать приложение из готовых кирпичиков. Довольно быстро стало ясно, что этого не случится и начали искать другие подходы, включая программирование через конфигурацию, пламенно воспетую Хантом и Томасом в их Программисте-прагматике. Затем появились IoC (или DI) контейнеры и начался новый этап создания слабосвязанных приложений, разбираться с которыми стало еще сложнее, чем прежде благодаря замене физической (прямой) связи между компонентами на логическую (косвенную).

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

Отношение к паттернам проектирования

Большинство разработчиков ПО сходятся в мысли, что паттерны проектирования небезынтересная вещь, но, тем не менее, многие относятся к этому инструменту по-разному. Почему так вышло? Когда молодой разработчик сталкивается с новым инструментом, то он изо всех сил старается воспользоваться им по максимуму. В результате, он проходит определенные стадии развития, которые в случае паттернов проектирования могут выглядеть так:

1-я стадия: Ух-ты-Ух-ты-Ух-ты! Я узнал, что такое паттерны! Класс! Когда и где я смогу ими воспользоваться?
2-я стадия: Ух-ты! Я отрефакторил старый код и вместо десяти строк кода заиспользовал 7 паттернов! Я мегакрут!
3-я стадия: ух-ты. Ну, паттерны - это классная штука, но через пару месяцев мой прошлый рефакторинг уже не кажется таким уж классным. Что-то я и сам начал путаться за всеми этими абстрактными фасадированными декораторами, завернутыми в синглтон.
4-я стадия: нет, паттерны это хорошо, но нужно отталкиваться не от паттернов, а от решаемой задачи и уже исходя из проблемы выбирать подходящие решения. Паттерны хорошо, но своя голова на порядок лучше!

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

Какое будет у вас отношение к паттернам при виде классов вроде AbstractSingletonProxyFactoryBean и приложений Hello, World следующего вида? public class HelloWorld
{
public static void Main(String[] args)
{
MessageBody mb = new MessageBody(),
mb
.Configure('Hello World!'),
AbstractStrategyFactory asf = DefaultFactory.Instance,
MessageStrategy strategy = asf.CreateStrategy(mb),
mb
.Send(strategy),
}
}

ПРИМЕЧАНИЕ
Пример кода взят из обсуждения паттернов проектирования на shashdot.

Подливает масла в огонь наше через чур наивное отношение к паттернам проектирования, которое отлично описал Джошуа Кериевски в своей книге Рефакторинг с использованием шаблонов. К сожалению, когда программисты смотрят на единственную диаграмму, сопровождающую каждый шаблон в книге Design Patterns, они часто приходят к выводу, что приведенная диаграмма и есть способ реализации шаблона. Они бы гораздо лучше разобрались в ситуации, если бы внимательно прочитали самое интересное - примечание к реализации. Многие программисты берут в руки книгу Design Patterns, всматриваются в структурную диаграмму шаблона и начинают кодировать. Полученный код в точности отражает диаграмму, а не реализацию шаблона, наиболее полно соответствующую решаемой задаче.

Большинство экспертов в ООП сходятся на мысли, что основным инструментом ООП является не наследование, а инкапсуляция сокрытие информации. Этой же точки зрения придерживались и авторы Design Patterns, советуя предпочитать агрегацию наследованию.

Но несмотря на этот совет, оригинальные диаграммы классов большинства паттернов проектирования поддерживают специализацию путем наследования. Есть паттерны, в которых наследование является неотъемлемой частью самого решения, но ведь есть и такие, в которых наследование является второстепенной характеристикой, предназначенной для получения более гибкого решения. К первой категории относятся Декоратор, Композит, Стратегия, Команда, Шаблонный Метод и другие. Но ведь для таких паттернов, как Строитель, Посредник, Прокси, Фабричный Метод наследование не является обязательным.

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

Фреймворки паттернов

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

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

Для чего нужна еще одна серия постов о паттернах?

В этой серии статей я хочу вернуться к стандартным паттернам проектирования и посмотреть на то, что с ними случилось за последние двадцать лет и показать, в каком виде они применяются или могут применяться в современных приложениях.

Паттерны не привязаны к платформе, но их типовая реализация зачастую несколько отличается от языка к языку, иногда из-за технических различий, иногда из-за культурных. Это не очередная серия постов типа, а давайте перескажем GoF паттерны, вместе с оригинальными определениями и диаграммами классов. Цель у меня несколько иная.

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

В этой серии я практически не буду приводить классические диаграммы паттернов, поскольку в реальных проектах паттерны далеко не всегда используются в каноническом виде. Вместо этого я буду приводить примеры использования паттернов проектирования непосредственно в .NET Framework и в современных .NET приложениях, а также постараюсь максимально глубоко разобрать влияние конкретных паттернов на дизайн систем.

Дополнительные источники
  • Фриман и Фриман Паттерны проектирования.
  • Гамма и др. Приемы объектно-ориентированного проектирования. Паттерны проектирования
  • Шаллоуей и Тротт Шаблоны проектирования. Новый подход к объектно-ориентированному анализу и проектированию
  • Programming Stuff: цикл статей об управлении зависимостями.
  • Programming Stuff: Шаблоны проектирования. История успеха.



Помогла статья? Оцените её!
0 из 5. Общее количество голосов - 0
 

You have no rights to post comments

Дмитрий Крикунов

Публикую статьи, обучающие курсы и новости по программированию: алгоритмам, языкам (С++, Java), параллельному программированию, паттернам и библиотекам (Qt, boost).