Что такое паттерны проектирования

Что такое паттерны проектирования

Как разработчику упростить код с помощью шаблонов.

Можно ли писать код так, чтобы его понимал только автор — разработчик? Да, если он же — единственный заказчик, создатель и пользователь продукта. Иначе это дурной тон.

Вячеслав Щупак более 15 лет разрабатывает ПО и управляет проектами в IT. Последние 3 года он отвечает за бэкенд в компании Sportradar, которая занимается сбором и обработкой спортивной аналитики. А ранее консультировал разработчиков программы Дія, создавал программу для переводчиков Trados и мобильные приложения для Киевской горадминистрации и контактного центра «1551», а также работал с Big Data.

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

Что такое паттерн

Паттерн (шаблон) проектирования — это именованное описание проблемы и ее решения, которые можно использовать в разработке других систем. Такое определение дает в своей книге «Применение UML и шаблонов проектирования» (Applying UML and Patterns) Крэг Ларман — специалист по гибкой методологии и итеративной разработке.

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

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

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

Когда используют паттерны

Необязательно использовать паттерн в каждой строчке кода — можно только там, где это необходимо для простоты и «читабельности».

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

Чтобы писать чистый код, нужно использовать не только паттерны. Также программисты применяют:

class Order
{
    public void calculate(){ ... }
    public void addItem(Product product){ ... }
    public List<Product> getItems(){ ... }
    ...
    public void load(){ ... }
    public void save(){ ... }
    public void print(){ ... }
}
class Order
{
    public void calculate();
    public void addItem(Product product){ ... }
    public List<Product> getItems(){ ... }
} 
class OrderRepository
{
    public Order load(int orderId){ ... }
    public void save(Order order){ ... }
} 
class OrderPrinter
{
    public void print(Order order){ ... }
}
  • SOLID: ключевые принципы объектно-ориентированного программирования, которые помогают оптимизировать код и создавать гибкое ПО. SOLID — это аббревиатура от пяти основных принципов:
    • Single responsibility — Принцип единственной обязанности
    • Open-closed — Принцип открытости/закрытости
    • Liskov substitution — Принцип подстановки Барбары Лисков
    • Interface segregation — Принцип разделения интерфейса
    • Dependency inversion — Принцип инверсии зависимостей
  • Event Sourcing: архитектурный шаблон, позволяющий выполнять и сохранять изменения в приложении в одинаковой последовательности.
  • Алгоритмы и структуры данных: инструменты, которые помогают упорядочивать, хранить и работать с данными оптимальным способом.
  • Test Driven Development: техника разработки ПО, основанная на повторении коротких циклов.

Эти и другие инструменты мы со студентами изучаем на курсе «Чистый код и паттерны проектирования».

Зачем применять паттерны

1. Паттерны помогают оптимизировать и повысить эффективность работы программистов. Кодить без паттернов — это как забыть, что кто-то уже придумал колесо.

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

Паттерны — это универсальный язык разработчиков. Каждый паттерн предусматривает знание определенной схемы. Но программистам не нужно описывать их — достаточно сказать «Фабрика» или «Компоновщик». Как, например, мы говорим «Я позвоню [по телефону]» вместо «Я использую средство связи с помощью радиоволн, передачи данных, дискретизации, фазового кодирования и шифрования».

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

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

5. Знание паттернов помогает программистам — как новичкам, так и опытным — в поиске работы. На техническом собеседовании нанимающие менеджеры часто дают задание написать код — и обращают внимание на то, насколько эффективно программист его выполняет. В том числе — применяет ли паттерны там, где это целесообразно.

Какие паттерны используют чаще всего

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

Примеры графических аннотаций для некоторых популярных паттернов

Например, я работал в компании SDL — в команде разработчиков известной системы автоматизированного перевода Trados. Сложность задачи состояла в том, что в исходных файлах часто есть не только текст, но и таблицы, картинки, другие элементы. Плюс система поддерживает более 40 форматов — Word, Excel, PDF, html и десятки других. В своей работе мы чаще всего использовали два паттерна:

  • «Компоновщик» (Composite) — объединяет группы объектов в древовидную структуру, похожую на меню с пунктами, и позволяет работать как с отдельными объектами, так и с группами.
  • «Посетитель» (Visitor) — используется, когда есть много объектов разных классов и интерфейсов и нужно выполнять действия над каждым из них.

Почти все современные приложения используют подключение к серверам и базам данных. В этой операции применяется паттерн «Объектный пул» (Object Pool).

Паттерн «Прототип» (Prototype) позволяет создавать объекты на основе уже имеющихся (по сути, копировать их). Встроен в язык программирования JavaScript и его производные (такие как TypeScript).

Шаблонный метод (Template method) определяет основу алгоритма и помогает наследникам менять шаги без изменений общей структуры. Используется в языках программирования, где есть абстрактные классы (Java, C#, C++ и др.).

Паттерн «Итератор» (Iterator) улучшает навигацию по коллекции объектов.

Паттерн «Объект-Значение» (Value Object) используется для хранения простых величин (таких как деньги или даты).

Современные системы часто используют ленивую инициализацию (Lazy initialization) — подход в программировании, когда сложное действие выполняется «по требованию». Например, «Фабричный метод» (Factory Method) предполагает, что базовый класс поручает создание объектов классам-наследникам. Благодаря этому не нужно многократно описывать создание объекта и вносить изменения в разные подклассы (это делается один раз).

С новыми технологиями постоянно появляются новые паттерны. Например, популярность микросервисов привела к необходимости паттернов Database per Service, External Configuration, Service Discovery и Circuit Breaker. Потребность понимать состояние распределенных систем — к необходимости паттернов Log Aggregation, Distributed Tracing и Health Check. Упор современных систем на маркетинг в том числе способствовал популярности паттерна Blue-Green Deployment.

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

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

Ещё статьи
Що алгоритми дозволяють робити з кодом і чому розробнику потрібно бути креативним.
Віктор Шитюк, Lead Data Engineer з 12 річним досвідом у IT сфері, про робочу рутину інженера даних, must-have інструменти та перспективи професії