Аналитики в своей работе сталкиваются с различными архитектурными шаблонами, даже этого не зная, точнее, не задумываясь о терминологических тонкостях.
Основные термины
Архитектурным шаблоном считается обобщённое, часто используемое решение распространённой задачи в архитектуре программного обеспечения в заданном контексте.
В англоязычной литературе часто оперируют терминами архитектурный стиль и паттерн.
Архитектурный стиль — это набор принципов, стратегия высокого уровня, обеспечивающая абстрактную инфраструктуру для семейства систем. Архитектурный стиль позволяет использовать дизайн повторно, часто решая повторяющиеся проблемы.
Архитектурные паттерны более предметны и специфичны для конкретной проблемы или модуля в системе. Они представляют структурированное решение архитектурных проблем с детальным описанием того, как компоненты и взаимодействия должны быть организованы для определённой функциональности. Иногда из называют шаблонами.
Шаблоны проектирования и архитектурные стили играют решающую роль в формировании структуры и поведения программных систем.
Рассмотрим наиболее известные стили и шаблоны.
Стили и шаблоны
1. Многослойный архитектурный стиль
Многослойный архитектурный стиль - структурирует приложение в несколько отдельных слоев, каждый из которых отвечает за определенные задачи или проблемы. Этот подход помогает разделить различные аспекты приложения на модульные, управляемые и повторно используемые компоненты. Часто используется для традиционных небольших, простых приложений и веб-сайтов.
Обычно выделяют 3 слоя:
- Уровень представления (UI): Здесь пользователь взаимодействует с приложением. Он обрабатывает пользовательский ввод и отображает информацию.
- Уровень приложения (бизнес-логика): содержит основную логику приложения, такую как обработка пользовательских запросов и управление бизнес-правилами.
- Уровень доступа к данным (база данных): данные извлекаются и сохраняются. Он взаимодействует с базой данных, обеспечивая разделение проблем с данными.
Одним из паттернов многослойного стиля является Onion architecture.
Паттерн «Onion Architecture»
Onion Architecture — это архитектурный подход, который разделяет систему на несколько слоёв, каждый из которых выполняет свою функцию. Эти слои представляют собой «шелуху» лука, где внутренний слой (ядро) содержит бизнес-логику и данные, а внешние слои отвечают за взаимодействие с пользователем, доступ к данным и другие функции.
Основные принципы Onion Architecture включают в себя:
1. Ядро (Core) — внутренний слой, содержащий бизнес-правила и логику приложения. Этот слой не должен зависеть от внешних факторов, таких как пользовательский интерфейс или базы данных.
2. Инфраструктура (Infrastructure) — слой, отвечающий за доступ к внешним ресурсам, таким как базы данных, очереди сообщений и т. д. Этот слой может быть реализован с использованием различных технологий, таких как ORM, микросервисы и т. п.
3. Адаптеры (Adapters) — слой, обеспечивающий взаимодействие между ядром и инфраструктурой. Адаптеры могут быть реализованы в виде библиотек, фреймворков или других компонентов.
4. Презентация (Presentation) — внешний слой, представляющий пользовательский интерфейс и взаимодействующий с адаптерами. Этот слой отвечает за отображение данных и обработку пользовательских запросов.
Наиболее значимые аналитические практики при использованием паттерна "Onion Architecture".
Определение границ ответственности
Важно четко разграничить, какие компоненты относятся к каждому слою, чтобы избежать смешивания обязанностей.
Анализ зависимостей
Необходимо удостовериться, что зависимости между слоями соблюдаются. Зависимости всегда направлены внутрь, то есть внешние слои зависят от внутренних, но не наоборот.
Анализ рисков
При использовании "Onion Architecture" могут возникнуть определенные риски:
- Риск чрезмерной сложности: если система слишком мала, использование такого паттерна может привести к избыточному усложнению;
- Неправильное разделение слоев: нарушение принципов организации зависимостей может сделать систему менее гибкой;
- Отсутствие четких интерфейсов: Если интерфейсы между слоями не описаны должным образом, это может затруднить дальнейшее развитие системы.
Аналитическая задача здесь - идентифицировать возможные риски на ранних этапах разработки и предложить способы их минимизации.
2. Сервисно-ориентированный архитектурный стиль
Этот стиль разрабатывает программное обеспечение в виде набора сервисов, взаимодействующих друг с другом. Одним из ключевых принципов, лежащих в основе SOA, является представление о том, что каждый сервис должен выполнять единственную бизнес-ориентированную функцию и что эти функции должны быть независимыми, допускающими многократное использование и легко обнаруживаемыми.
К стилю SOA относятся, например, микросервисы.
Паттерн «Микросервисы»
Этот паттерн проектирует приложение в виде набора небольших сервисов, каждый из которых работает в своём процессе и общается с помощью легковесных механизмов, часто через HTTP. Эти сервисы ориентированы на бизнес-возможности и могут быть независимо развёрнуты с помощью полностью автоматизированного механизма развёртывания. Этот паттерн позволяет быстро, часто и надёжно доставлять сложные приложения.
Аналитические практики при работе с микросервисами
Анализ зависимостей между сервисами
Микросервисы должны быть независимыми, но полная изоляция невозможна, так как они взаимодействуют друг с другом. Поэтому важно анализировать зависимости между сервисами.
Создайте граф или карту взаимодействий между сервисами. Это поможет:
- Выявить потенциальные бутылочные горлышки;
- Снизить количество жестких зависимостей;
- Оптимизировать маршруты взаимодействия.
Анализ производительности
Микросервисная архитектура увеличивает количество сетевых вызовов, что может повлиять на производительность всей системы.
Используйте инструменты для мониторинга производительности (например, OpenTelemetry, Prometheus, Grafana) для анализа:
- Времени выполнения запросов;
- Количества ошибок;
- Загрузки сети и серверов.
Анализ развертывания и масштабирования
Микросервисы позволяют разворачивать и масштабировать каждый сервис независимо от других, что требует правильного планирования.
Можно внедрить процессы Continuous Integration и Continuous Delivery (CI/CD), чтобы автоматизировать развертывание сервисов.
Анализ метрик и логов
Мониторинг и анализ метрик являются критическими для успешной работы микросервисной архитектуры и позволяют получать подробную информацию о работе системы, могут использоваться для диагностики проблем.
Рекомендуется использовать централизованные системы сбора метрик и логов (например, ELK Stack (ElasticSearch + Logstash + Kibana), Splunk, Grafana Loki).
Анализ стоимости
Хотя микросервисы обеспечивают гибкость, они могут увеличить общую стоимость разработки и поддержки.
Критически важно регулярно анализировать затраты на инфраструктуру, разработку и поддержку каждого сервиса.
3. Стиль предметно-ориентированной архитектуры
Этот стиль сосредотачивается на основной предметной области и логике предметной области, основываясь на бизнес-модели предметной области. Он подчеркивает сотрудничество между техническими и предметными экспертами для итеративного совершенствования модели, которая точно и эффективно решает бизнес-проблемы.
Паттерн Предметно-ориентированного проектирования (Domain-Driven Design — DDD)
Этот паттерн представляет собой подход к разработке программного обеспечения для сложных потребностей путем связи реализации с развивающейся моделью. Он включает тесную связь между реализацией и текущей моделью с постоянным циклом итераций над обоими. DDD идеально подходит для сложных систем с богатыми, сложными бизнес-правилами или систем, где предметная область постоянно меняется.
Аналитические практики, применимые при предметно-ориентированном программировании
Анализ предметной области
Цель: Определить ключевые понятия, процессы и взаимосвязи в предметной области.
Методы:
- Интервью с экспертами: получение информации от специалистов предметной области;
- Процессное моделирование: создание диаграмм процессов (например, BPMN) для описания бизнес-операций;
- Карта поддоменов: разбиение предметной области на логические поддомены (core, supporting, generic).
Выявление границ контекста
Цель: Определить границы различных частей системы и их взаимодействие.
Методы :
- Контекстное картографирование (Context Mapping): определение границ между различными подсистемами и их зависимостей;
- Bounded Context: выделение областей ответственности для каждого компонента системы.
Моделирование языка предметной области
Цель: Создать единый язык общения между разработчиками и бизнес-специалистами.
Методы :
- Ubiquitous Language: разработка общего словаря терминов, используемых всеми участниками проекта;
- Глоссарий: формализация терминологии предметной области.
Анализ данных
Цель: Понять структуру данных и их потоки в системе.
Методы :
- Entity-Relationship Diagrams (ERD): моделирование структуры данных;
- Data Flow Diagrams (DFD): описание потоков данных между компонентами системы;
- Event Storming: коллективный анализ событий и данных в предметной области.
Прототипирование и экспериментирование
Цель: Проверить гипотезы и принять решения на основе реальных данных.
Методы :
- MVP (Minimum Viable Product): разработка минимальной рабочей версии для тестирования концепций;
- Proof of Concept (PoC): проведение экспериментов для проверки технической реализуемости.
4. Событийно-ориентированный архитектурный стиль
Событийно-ориентированная архитектура (Event-driven architecture), представляет собой распространенный асинхронный шаблон, в котором основной для системных действий становится реакция на какое-либо событие. Это позволяет создавать распределенные системы, которые легко масштабируются и обладают высокой отказоустойчивостью. Часто используется в электронной коммерции, интернете вещей, для получения аналитических данных.
К этому стилю относится и паттерн Pub-Sub.
Паттерн «Издатель-подписчик» (Pub-Sub Pattern)
Это паттерн обмена сообщениями, где отправители сообщений, известные как издатели (publishers), не направляют сообщения непосредственно конкретным получателям, известным как подписчики (subscribers). Вместо этого опубликованные сообщения объединяются по темам без информации о том, есть ли подписчики на них. Точно так же подписчики выражают интерес к одной или нескольким темам и получают только сообщения, которые их интересуют, не зная, есть ли издатели, которые их отправили. Этот паттерн широко используется в асинхронных системах для разделения процессов, которые производят события и процессов, которые их обрабатывают, что позволяет добиться большей масштабируемости и управления.
Аналитические практики при использовании Pub-Sub
Мониторинг производительности
- Отслеживание латентности: измеряйте время между публикацией события и его обработкой подписчиком. Это поможет выявить задержки в системе;
- Контроль загрузки брокера: следите за числом сообщений, обрабатываемых брокером, чтобы предотвратить перегрузку;
- Анализ отказов: отслеживайте случаи, когда сообщение не было доставлено или обработано.
Разделение данных на темы
- Группировка событий: разделяйте события на различные темы (например, "пользовательские действия", "платежи", "логи"). Это упрощает фильтрацию и обработку;
- Создание иерархии тем: для сложных систем можно использовать иерархическую структуру тем.
Обработка ошибок
- Dead Letter Queue (DLQ): если подписчик не может обработать сообщение, оно помещается в DLQ для дальнейшего анализа;
- Автоматическая повторная попытка: реализуйте механизм автоматической повторной доставки сообщений при временных ошибках.
Анализ поведения подписчиков
- Задержки обработки: анализируйте, какие подписчики медленнее других обрабатывают сообщения;
- Нагрузка на подписчиков: оцените, как распределена нагрузка между подписчиками, и определите необходимость масштабирования.
Оптимизация пропускной способности
- Пакетная обработка: группируйте сообщения для снижения количества запросов к брокеру;
- Compression: сжимайте большие сообщения для уменьшения объёма передаваемых данных.
5. Архитектурный стиль разделения ответственности
Принцип разделения ответственности (Separation of concerns) — это принцип проектирования, позволяющий разделить компьютерную программу на отдельные разделы, каждый из которых обрабатывает отдельную задачу. Чаще всего применяется в разработке мобильных приложений.
Паттерн "MVVM" (Model-View-ViewModel)
Этот паттерн упрощает разделение разработки графического пользовательского интерфейса от бизнес-логики или логики на стороне сервера. View-контроллер отвечает за предоставление объектов данных из модели, чтобы эти объекты легко управлялись и представлялись. Этот паттерн широко используется в областях с интенсивным взаимодействием с пользователями, таких как настольные и мобильные приложения.
Паттерн "MVP" (Model-View-Presenter)
Это модификация архитектурного паттерна "Model-View-Controller" (MVC), применяемая в основном для построения пользовательских интерфейсов. В паттерне MVP представитель (presenter) берет на себя роль среднего звена. Модель (model) и представление (view) полностью разделены и общаются друг с другом только через представителя. MVP является отличной архитектурой для современных веб-приложений, так как она облегчает автоматизированное модульное тестирование и предоставляет четкую структуру для проекта.
Аналитические практики для применения разделения ответственности
Идентификация задач
Первый шаг — это выявление всех возможных задач, которые нужно решить в системе. Например:
- Взаимодействие с пользователем (UI/UX);
- Обработка данных;
- Хранение данных;
- Безопасность;
- Логирование событий.
Классификация задач
После того, как все задачи были выявлены, их необходимо классифицировать. Задачи можно разделить на несколько категорий:
- Пространственные задачи: касаются физической организации системы (например, расположение файлов, модулей);
- Временные задачи: связаны с порядком выполнения операций (например, последовательность выполнения задач);
- Доменные задачи: относятся к бизнес-логике приложения (например, расчёт стоимости заказа);
- Технические задачи: касаются инфраструктуры (например, безопасность, логирование).
Моделирование структуры
На основе выявленных задач строится модель структуры системы. Это может быть выполнено с помощью различных методологий:
- UML диаграммы: для визуализации взаимодействия между компонентами;
- Схемы данных: для представления структуры базы данных;
- Процессные диаграммы: для анализа потока данных и логики.
Разработка компонентов
После моделирования начинается разработка компонентов, каждый из которых отвечает за свою конкретную заботу. При этом важно следовать таким правилам:
- Компоненты должны быть независимыми друг от друга;
- Интерфейсы между компонентами должны быть ясными и понятными;
- Изменение одного компонента не должно приводить к необходимости изменения других.
Тестирование и проверка
Разделение ответственности значительно упрощает процесс тестирования, так как каждый компонент можно тестировать отдельно. Это также помогает быстрее находить и исправлять ошибки.
Вместо заключения
Существует множество других паттернов и шаблонов, также постоянно появляются новые.
Выбор подходящего архитектурного шаблона для конкретного продукта – это первый шаг к успеху.
А для принятия решения о том, какой шаблон является подходящим для конкретного решения, важно использовать специфические аналитические практики.
Уже на старте проекта важно учитывать особенности бизнес-задач и имеющиеся ограничения. Также необходимо выстроить такие отношения в команде, которые позволят слышать и понимать друг друга, воспринимать идеи и предыдущий опыт коллег для достижения лучших результатов.
Необходимо обратить внимание, что перечень описанных в статье архитектурных шаблонов, равно как и аналитических практик, не является исчерпывающим. Именно эти паттерны показались автору наиболее значимыми и репрезентативными, а практики - наиболее подходящими для выбранных паттернов.
Автор: Анна Пушина
Редактор: Татьяна Курсина
Фото найдены в Сети