Книга: Погружение в Паттерны Проектирования
Назад: Зачем знать паттерны?
Дальше: Базовые принципы проектирования

ПРИНЦИПЫ ПРОЕКТИРОВАНИЯ

Качества хорошей архитектуры

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

Повторное использование кода

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

Повторное использование программной архитектуры и кода — это один из самых распространённых способов снижения стоимости разработки. Логика проста: вместо того, чтобы разрабатывать что-то по втором уразу, почему бы не использовать прошлые наработки в новом проекте?

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

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

Приведу цитату Эрика Гаммы, одного из первооткрывателей паттернов, о повторном использовании кода и роли паттернов в нём.

Существует три уровня повторного использования кода. На самом нижнем уровне находятся классы: полезные библиотеки классов, контейнеры, а также «команды» классов вроде контейнеров/итераторов.

Фреймворки стоят на самом верхнем уровне. В них важна только архитектура. Они определяют ключевые абстракции для решения некоторых бизнес-задач, представленных в виде классов и отношений между ними. Возьмите JUnit, это маленький фреймворк, даже базовый, я бы сказал. В нём есть всего несколько классов — Test, TestCase и TestSuite, а также связи между ними. Обычно, фреймворк имеет гораздо больший охват, чем один класс. Вы должны вклиниться в фреймворк, расширив какой-то из его классов. Всё работает по так называемому голливудскому принципу "не звоните нам, мы сами вам перезвоним". Фреймворк позволяет вам задать какое-то своё поведение, а затем сам вызывает его, когда приходит черёд что-то делать. То же происходит и в JUnit. Он обращается к вашему классу, когда нужно выполнить тест, но всё остальное происходит внутри фреймворка.

Есть ещё средний уровень. Это то, где я вижу паттерны. Паттерны проектирования и меньше, и более абстрактные, чем фреймворки. Они, на самом деле, просто описание того, как парочка классов относится и взаимодействует друг с другом. Уровень повторного использования повышается, когда вы двигаетесь в направлении от конкретных классов к паттернам, а затем к фреймворкам.

Что ещё замечательно в этом среднем уровне так это то, что паттерны — это менее рискованный способ повторного использования, чем фреймворки. Разработка фреймворка — это крайне рисковая и дорогая инвестиция. В то же время, паттерны позволяют вам повторно использовать идеи и концепции в отрыве от конкретного кода.

Расширяемость

Изменения часто называют главным врагом программиста.

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

У каждого программиста есть дюжина таких историй. Есть несколько причин, почему так происходит.

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

Во-вторых, изменения могут прийти извне. У вас есть идеальный клиент, который с первого раза сформулировал то, что ему надо, а вы в точности это сделали. Прекрасно! Но вот, выходит новая версия операционной системы, в которой ваша программа перестаёт работать. Чертыхаясь, вы лезете в код, чтобы внести кое-какие изменения.

Можно посмотреть на это с оптимистичной стороны: если кто-то просит вас что-то изменить в программе, значит она всё ещё кому-то нужна.

Вот почему даже мало-мальски опытный программист проектирует архитектуру и пишет код с учётом будущих изменений.

Назад: Зачем знать паттерны?
Дальше: Базовые принципы проектирования

asd
asdda