Архитектура приложения — это его технологическая база, которая учитывает риски проекта, бюджет, требования и ограничения, потребности в масштабировании.
Помимо разработки архитектуры, на старте требуется приблизительно оценить объем и стоимость проекта. Для этого мы в своей практике используем одну из проверенных методологий создания архитектуры ПО — Attribute-Driven Design (ADD). При этом мы опираемся на атрибуты качества того или иного IT-продукта. На их основе мы на этапе оценки (пресейла) создаём архитектурную концепцию системы.
Рассмотрим этапы работы с архитектурной концепцией, возможные сложности и решения, исходя из опыта нашего Архитектурного комитета. Мы надеемся, что статья будет полезна архитекторам и разработчикам, желающим освоить методологию ADD, и может быть интересна смежным специалистам.
Именно IT-архитектор решает, как в конечном итоге будет выглядеть информационная система — в целом и в деталях. Ему требуется найти баланс между конкурирующими требованиями и ограничениями.
Если у вас есть детальное архитектурное решение, это позволит наиболее точно оценить сроки и стоимость реализации продукта. Кроме того, появляется возможность уже на старте определить характеристики системы, которая будет соответствовать бизнес-задачам. Среди критериев качества архитектуры – гибкость для масштабирования, снижение рисков, скорость работы и возможность независимого выбора подрядчиков.
О том, как выглядит день архитектора, и о наиболее требовательных к архитектуре проектах мы рассказывали ранее на Хабре и в нашем подкасте.
Требования и ограничения
Наша цель — спроектировать архитектуру систематическим, предсказуемым и экономически эффективным способом. Для этого нужно определить требования к продукту.
Как правило, техническое задание (ТЗ) на разработку продукта содержит требования, но не всегда они указаны в достаточном объеме. По этой причине в числе ключевых задач IT-архитектора – сбор и анализ требований, создание дизайна архитектуры и описание решения, его проверка, а также контроль и надзор во время разработки ПО.
Рассмотрим, что входит в список требований:
Цель проектирования
От цели зависит, что нам нужно на старте: детальная архитектура или приблизительное представление об устройстве системы, которое позволит оценить объем и стоимость работ.
Атрибуты качества, нефункциональные требования
Эти атрибуты определяют свойства системы, которые она должна демонстрировать — требования к производительности, доступности, безопасности, удобству использования.
Пример: система должна работать 24х7, допускается простой не более 30 минут в месяц.
Функциональные требования
Определяют действия, которые система способна выполнить.
Пример: возможность выгружать данные из файла и рассылать отчеты по email.
Системные требования
Возникают постепенно в процессе детализации и реализуются итеративно.
Пример: авторизация, ведение журнала действий, кэширование.
Ограничения
Не относятся напрямую к поведению системы и не поддаются нашему влиянию. Например, у клиента есть пожелания по разработке микросервисной, а не монолитной архитектуры. Также сюда относятся требования законодательства, например, в области хранения персональных данных.
Как правило, владелец продукта заранее не имеет полного списка требований к системе, поэтому архитектор непосредственно организует процесс их сбора и фиксации. Из всех требований к системе специалист обязан выделить архитектурно значимые, которые оказывают глубокое влияние на конечное решение.
Согласно методологии ADD, сбор требований – это первый этап работы. Его назначение:
- помочь оценить стоимость и график работ;
- выработать ключевые технологии;
- обеспечить достижение бизнес-целей в процессе разработки.
Далее рассмотрим остальные этапы проектирования.
Обзор методологии
1) Собираем требования
В качестве источника могут выступать результаты опросов стейк-холдеров, анализ бизнес-целей проекта и историй использования (user story). При этом важно конкретизировать, что имеет в виду клиент. Например, не просто «безотказная работа сайта», а «допустимый период простоя – 30 минут в месяц».
Далее мы оцениваем важность требований по двум критериям:
ценность для бизнеса;
степень влияния на архитектуру.
Уровни важности оцениваем по шкале HML (high, medium, low — высокий, средний, низкий). Таким образом, каждое требование будет иметь двухбуквенное сочетание. Архитектурно значимые пункты имеют обозначения HH, HM, HL, MH, MM. Стоит отметить, что большое число требований HH означает высокие риски на проекте.
2) Проектируем архитектуру
Мы проектируем архитектуру ПО, исходя из наиболее значимых атрибутов качества. Это рекурсивный процесс, в ходе которого система декомпозируется на более мелкие подсистемы.
ADD — первый метод, который концентрируется на атрибутах качества и способах их достижения. Важным вкладом ADD было признание того, что анализ и документация являются неотъемлемой частью процесса проектирования. Этот метод успешно применяется более 15 лет.
Сейчас актуальная версия ADD — 3.0, итеративная. Согласно ей, проектирование выполняется поэтапно в течение всего времени разработки системы, в каждом спринте. В ней по шагам описано руководство по тем задачам, которые необходимо выполнить в рамках каждой итерации.
Шаг 1. Проверка входных данных
Убеждаемся, что все необходимые данные и требования доступны, приоритизированы, корректны и выполнимы, а цель работы понятна.
Шаг 2. Определяем список требований к подсистеме
Ранжируем требования по важности для бизнеса и степени влияния на архитектуру, группируем в соответствии с оценкой HML, выбираем 5-6 приоритетных. Устанавливаем цель каждой итерации.
Шаг 3. Выбираем часть системы для проектирования
Исходим из риска и сложности реализации, ценности для бизнеса, критического пути и точности проработки требований. Строим работу на достижении требований, которые соответствуют целей итерации
Шаг 4. Определяем лучший вариант из возможных
Самый сложный пункт. Анализируем все варианты, находим преимущества и недостатки.
Шаг 5. Конкретизируем компоненты выбранной концепции, определяем обязанности и интерфейсы
Как правило, в начале работы концепция формулируется в общем виде. На данном этапе мы определяем все элементы подсистемы и ответственность каждого, выбираем интерфейс, через который компоненты взаимодействуют между собой.
Шаг 6. Делаем эскиз решения и краткое описание
Оформляем описание в наглядный документ, например, в виде UML-диаграммы или SFML. Нужно также зафиксировать все принятые решения, описать, на какие компромиссы мы пошли и какие альтернативы рассмотрели. Это поможет в дальнейшем оценить аргументы в пользу конкретной архитектуры и создать документацию.
Шаг 7. Проверка выполнения требований
На этом шаге методология рекомендует получить “второе мнение” других опытных коллег-архитекторов, для того чтобы подойти к процессу более объективно. Участие нескольких специалистов с их опытом и точкой зрения на архитектуру поможет оперативно выявить недочеты, если они есть.
Мы уточняем и конкретизируем требования, расставляем приоритеты и затем повторяем шаги со 2 по 7 в каждой итерации. Таким образом необходимо проработать все требования с высоким приоритетом, соблюдая все ограничения. Но не обязательно проводить итерации последовательно. Скорее всего, вы будете чередовать этапы проектирования и реализации системы.
3) Отслеживаем прогресс
Чтобы вовремя выполнить перечисленные выше шаги, архитектору нужно наблюдать за прогрессом работы команды и оперативно откликаться на изменения. Авторы методологии советуют отслеживать выполнение шагов с помощью архитектурного бэклога в виде канбан-доски. В ее столбцы мы помещаем архитектурно значимые требования, ограничения и системные задачи. Они могут иметь следующие статусы:
Not Yet Addressed (Еще не рассмотрено)
Partially Addressed (Рассмотрено частично)
Completely Addressed (Рассмотрено полностью)
Discarded (Отброшено)
Рассмотрим на примере
В заключение расскажем на примере о том, как закладывается архитектура по ADD.
Задача
К нам обратился зарубежный заказчик — владелец крупного хранилища данных, полученных из старинных газет (более 1 млрд отсканированных страниц). Заказчику потребовалось найти и собрать в единую базу знаний все брачные объявления, а также записи о свадьбах: кто, когда и на ком женился.
Чтобы обработать информацию и выделить нужные факты, мы использовали нейросеть. Инженеры заказчика ранее уже создали все необходимые модели TensorFlow, которые должны запускаться последовательно, образуя конвейер. На вход модели поступал результат работы предыдущей модели, преобразованный по определенному алгоритму. Модели работали с разной скоростью и имели разные требования к ресурсам (потребление оперативной памяти, нагрузка на процессор, потребность в GPU).
Чтобы выполнить проект в срок, мы определили, что в среднем нужно обрабатывать до 10 миллионов страниц в день. Запросы на обработку поступали неравномерно, в некоторые часы их количество было близко к нулю, в другие — составляло порядка одного-двух миллионов. Страница полностью обрабатывалась не позднее чем через час после поступления.
Заказчик планировал развернуть систему в облаке. Поэтому было важно оптимально использовать вычислительные ресурсы, чтобы минимизировать плату за их аренду.
Варианты использования
ID | Вариант использования | Описание |
UC-1 | Извлечение фактов из текста | На вход системы подается отсканированный текст. На выходе получаем JSON с извлеченными фактами на интересующую нас тему. |
Атрибуты качества
ID | Атрибут | Описание |
QA-1 | Быстродействие | До 10 миллионов страниц в день. Результат обработки страницы должен быть получен не позднее чем через 1 час. |
QA-2 | Масштабируемость | Система должна уметь справляться с ростом нагрузки. Она неравномерная: от 0 до 2 миллионов запросов в час. |
QA-3 | Экономичность | Необходимо оптимально использовать вычислительные ресурсы, чтобы минимизировать плату за их аренду. |
Ограничения
ID | Описание |
CON-1 | Система должна быть развернута в облаке AWS. |
CON-2 | Использовать для вычислений готовые модели TensorFlow. Модели работают с разной скоростью. Требования к ресурсам сильно отличаются: некоторые потребляют много оперативной памяти, другие сильно нагружают процессор, третьим для работы необходим GPU. |
Архитектурные задачи
ID | Описание |
CRN-1 | Спроектировать и описать высокоуровневую архитектуру системы |
Процесс проектирования
После фиксации требований мы подготовились к тому, чтобы начать первую итерацию ADD.
Шаг 1. Проверка и анализ исходных данных
Категория | Детали | Категория | Детали |
Цель проектирования | Спроектировать систему с нуля. Работа должна быть выполнена в виде последовательных коротких итераций, чтобы оперативно получать обратную связь. | Цель проектирования | Спроектировать систему с нуля. Работа должна быть выполнена в виде последовательных коротких итераций, чтобы оперативно получать обратную связь. |
Основные функциональные требования | UC-1 | Основные функциональные требования | UC-1 |
Атрибуты качества | ID | Важность для клиента | Сложность реализации |
QA-1 | Высокая | Высокая | |
QA-2 | Высокая | Средняя | |
QA-3 | Высокая | Средняя | |
Ограничения | CON-1 CON-2 | Ограничения | CON-1 CON-2 |
Архитектурные задачи | CRN-1 | Архитектурные задачи | CRN-1 |
Первая итерация – это референсная архитектура и общая структура системы.
Шаг 2. Цель итерации
По завершении итерации нам нужно определить общую структуру проектируемой системы (CRN-1).
Шаг 3. Выбор элемента системы для проработки
Прорабатываем структуру всей системы.
Шаг 4. Выбор архитектурных концепций
Решение | Описание |
Архитектурный стиль “Pipes and Filters” | Разобьем процесс обработки страницы на отдельные компоненты (фильтры). Каждый из них решает одну задачу с помощью одной модели TensorFlow. Компоненты конвейера будут выполняться на разных компьютерах. Это позволит масштабировать их независимо друг от друга. И мы можем выбрать наиболее оптимальное оборудование для работы соответствующей модели TensorFlow. |
Альтернативное решение | Причина отказа |
Монолит: выполнять всю обработку внутри одного неделимого модуля | Несмотря на то, что один модуль проще разрабатывать, сопровождать и развертывать, данный вариант не позволяет оптимально использовать вычислительные ресурсы из-за различий TensorFlow-моделей. |
Шаг 5. Конкретизация экземпляров архитектурных элементов, распределение обязанностей и определение интерфейсов
Решение | Обоснование |
Создаем отдельный кластер для каждого фильтра | - Возможность независимого масштабирования фильтров для выравнивания пропускной способности (QA-1, QA-2) - Возможность оптимального подбора оборудования: ресурсоемкие модели запускаем на высокопроизводительных серверах, менее ресурсоемкие — на экономичных серверах (QA-3, CON-2) - Решение реализуемо в AWS (CON-1) |
Используем очереди для передачи данных между фильтрами в формате JSON | - Размер одного сообщения небольшой - Очередь будет выступать в роли буфера для сглаживания всплесков нагрузки (QA-2) - Данные будут обрабатываться в виде потока: фильтр обрабатывает запрос, передает результат следующему фильтру и продолжает свою работу, что повышает пропускную способность (QA-1) - Решение реализуемо в AWS (CON-1) |
Используем файловое хранилище для хранения отсканированных страниц. В запросе передаем ссылку на файл | - Размер скана страницы может достигать нескольких Мб, поэтому нежелательно добавлять его в очередь - Решение реализуемо в AWS (CON-1) |
Используем возможность автомасштабирования кластера на основании значений метрик входной очереди | -Зная текущий размер очереди и возраст самого старого сообщения в очереди, мы можем автоматически подобрать необходимый размер кластера для обеспечения требуемой производительности (QA-1) - Решение реализуемо в AWS (CON-1) |
Шаг 6. Эскиз решения
Шаг 7. Анализ созданной архитектуры и прогресса
Цель итерации достигнута. Общая структура системы спроектирована. В качестве основы мы выбрали проверенный временем архитектурный стиль, подходящий под условия нашей задачи. В следующих итерациях следует подобрать технологии и детально описать, как будет обеспечиваться выполнение архитектурных требований.
Выводы
Если вы хотите оценить сроки и стоимость реализации проекта, бывает полезно уже на старте проработать детали его архитектурной концепции. Подход Attribute-Driven Design помогает при выборе архитектурного решения, инструментов и шаблонов, что в свою очередь позволяет снизить затраты на разработку.
Благодарим за внимание и надеемся, что наш пример был вам полезен.