6.1 Атрибуты качества и нефункциональные требования
Зачем это аналитику
Архитектуру определяют не функции, а атрибуты качества: производительность, доступность, модифицируемость, безопасность. Требование «система должна быть быстрой» непроверяемо и потому бесполезно. Умение превратить его в измеримый сценарий — ключевой навык архитектора и сильного аналитика.
Готовность к модулю
Модуль опирается на темы ниже. Если какая-то из них незнакома или её вопросы для самопроверки даются с трудом, начните с неё.
Что понять
- Функциональные требования, атрибуты качества и ограничения — почему архитектура в первую очередь отвечает на второе и третье.
- Модель качества ISO/IEC 25010: характеристики и подхарактеристики как чек-лист, чтобы ничего не забыть.
- Сценарий атрибута качества: источник, стимул, артефакт, среда, реакция, мера реакции.
- Приоритизация: дерево полезности (utility tree), важность для бизнеса против сложности реализации.
- Конфликты атрибутов: производительность против безопасности, доступность против согласованности, модифицируемость против производительности.
- Тактики: типовые архитектурные приёмы для каждого атрибута (например, для доступности — резервирование, обнаружение отказов, деградация).
- Как проверять: нагрузочные тесты, учения по отказам, архитектурные fitness functions.
Урок
Две системы с одинаковым набором функций могут иметь совершенно разную архитектуру. Интернет-магазин на сто заказов в день и на сто заказов в секунду умеет одно и то же: показать каталог, принять заказ, списать остаток. Различаются они требованиями к производительности, доступности и масштабируемости. Именно эти требования заставляют делить систему на части, выбирать хранилища, вводить очереди и кеши. Отсюда главная мысль урока: архитектура — ответ прежде всего на атрибуты качества и ограничения, а функции лишь размещаются внутри неё.
Три вида требований
Функциональные требования описывают, что система делает: «принять платёжное поручение», «сформировать заказ поставщику по прогнозу». Их можно реализовать почти в любой архитектуре, включая один монолит с одной базой.
Атрибуты качества (quality attributes) описывают, насколько хорошо система это делает и в каких условиях: за какое время, при какой нагрузке, с какой вероятностью отказа, сколько стоит изменение. В русской практике их чаще называют нефункциональными требованиями, но термин «атрибут качества» точнее: он подчёркивает, что речь о свойстве системы, которое можно измерить.
Ограничения (constraints) — решения, принятые до архитектора и не подлежащие обсуждению: стандарт компании на PostgreSQL, размещение данных в определённой юрисдикции, срок запуска, бюджет, навыки команды, обязательная интеграция с существующей учётной системой. Ограничение отличается от атрибута тем, что его не оптимизируют, а соблюдают.
Почему архитектура отвечает на второе и третье: функциональность локализуется в модулях и меняется по ходу проекта относительно дёшево. Атрибуты качества сквозные: доступность 99,95% нельзя добавить в один модуль, она требует резервирования, обнаружения отказов и процедур восстановления по всей цепочке. Перестроить систему под новый атрибут качества почти всегда дороже, чем добавить функцию.
Практическое следствие для аналитика: когда в постановке есть только функции, архитектор будет угадывать атрибуты качества. Угадывает он обычно по худшему сценарию, и система получается дороже, чем нужно, или по лучшему — и тогда она падает на первой распродаже.
ISO/IEC 25010 как чек-лист
Стандарт ISO/IEC 25010 описывает модель качества программного продукта: набор характеристик, каждая из которых раскладывается на подхарактеристики. Проекту не нужно выполнять стандарт целиком. Его ценность — в полноте: пройдясь по списку, легко заметить, что про совместимость, восстанавливаемость или переносимость в требованиях не сказано ничего.
Ниже — характеристики в редакции 2011 года, которая наиболее широко известна и цитируется.
| Характеристика | Подхарактеристики | Вопрос для постановки |
|---|---|---|
| Функциональная пригодность | Полнота, корректность, целесообразность | Все ли нужные функции есть и дают ли верный результат |
| Производительность | Временные характеристики, использование ресурсов, ёмкость | Сколько времени, при какой нагрузке, на каком объёме данных |
| Совместимость | Сосуществование, интероперабельность | С какими системами обменивается данными и делит ресурсы |
| Удобство использования | Узнаваемость, обучаемость, управляемость, защита от ошибок пользователя, эстетика, доступность | Кто пользователь и какие ошибки он не должен иметь возможности совершить |
| Надёжность | Зрелость, доступность, отказоустойчивость, восстанавливаемость | Сколько может быть недоступна, как быстро восстанавливается, что теряется |
| Защищённость | Конфиденциальность, целостность, неотказуемость, подотчётность, подлинность | Кто что видит, как доказывается авторство операции, что журналируется |
| Сопровождаемость | Модульность, повторное использование, анализируемость, модифицируемость, тестируемость | Какие изменения ожидаются и сколько они должны стоить |
| Переносимость | Адаптируемость, устанавливаемость, заменяемость | На какие окружения переезжает, что может быть заменено |
В редакции 2023 года модель пересмотрена: добавлена характеристика, связанная с безопасностью для людей и окружения (safety), часть характеристик переименована и расширена. Для роли чек-листа это непринципиально: важно пройти все направления и явно решить, какие из них для системы значимы.
Ответ на вопрос «зачем стандарт, если требования пишутся под проект»: стандарт даёт не требования, а общий словарь и защиту от пропусков. Требования под проект формулируются сценариями, а стандарт помогает проверить, что сценарии покрывают все значимые направления.
Сценарий атрибута качества
Размытое «система должна быть надёжной» превращается в проверяемое требование через сценарий из шести частей. Этот формат предложен в книге Басса, Клементса и Кацмана Software Architecture in Practice.
- Источник стимула — кто или что вызывает событие: пользователь, внешняя система, оператор, аппаратный сбой, злоумышленник.
- Стимул — само событие: запрос, отказ узла, попытка несанкционированного доступа, запрос на изменение.
- Артефакт — на что воздействует стимул: вся система, конкретный сервис, база данных, код модуля.
- Среда — в каком состоянии система: штатный режим, пиковая нагрузка, деградированный режим, время обслуживания, этап разработки.
- Реакция — что система делает в ответ.
- Мера реакции — как проверить, что реакция достаточна: время, доля, объём потерь, трудозатраты.
Пример для доступности в банке для юрлиц:
| Часть | Значение |
|---|---|
| Источник | Отказ оборудования в основном дата-центре |
| Стимул | Узел базы данных сервиса приёма платёжных поручений перестаёт отвечать |
| Артефакт | Сервис приёма платёжных поручений и его хранилище |
| Среда | Рабочий день, штатная нагрузка |
| Реакция | Отказ обнаружен, трафик переключён на реплику, клиенты получают ошибку с предложением повторить только на время переключения |
| Мера | Переключение не дольше 60 секунд, ни одно принятое поручение не потеряно, повторная отправка не создаёт дубля |
Мера реакции — самая ценная часть. Именно она превращает пожелание в требование, которое можно проверить тестом или учениями, и именно её заказчик чаще всего не может назвать сразу. Задача аналитика — выяснить её через последствия: сколько стоит минута простоя, какие потери данных допустимы, во что обходится час ожидания для пользователя.
Для производительности сценарий выглядит так: «Во время ночного пересчёта (среда) сервис автозаказа (артефакт) получает от планировщика (источник) команду рассчитать заказы для всех магазинов сети (стимул); расчёт завершается (реакция) до 5:00 при объёме до 3 000 магазинов и 40 000 товаров (мера)». Сразу видно, что требование касается пропускной способности пакета, а не отклика API, и проектировать нужно параллельную обработку, а не кеш.
Для модифицируемости стимулом становится запрос на изменение, а средой — время разработки: «Разработчик добавляет новый тип поставщика с собственным форматом заказа; изменение затрагивает только адаптер поставщика и занимает не больше трёх дней вместе с тестами».
Приоритизация: дерево полезности
Все атрибуты качества «важны», пока не выясняется, что за каждый нужно платить. Дерево полезности (utility tree) из метода ATAM структурирует этот разговор. Корень — общая полезность системы. Второй уровень — атрибуты качества. Третий — уточнения атрибута. Листья — конкретные сценарии, каждый с двумя оценками: важность для бизнеса и сложность реализации (обычно H, M, L).
flowchart LR
U["Полезность<br/>сервиса автозаказа"] --> P["Производительность"]
U --> A["Доступность"]
U --> M["Модифицируемость"]
U --> S["Защищённость"]
P --> P1["Ночной расчёт до 5:00<br/>на 3000 магазинов (H,H)"]
P --> P2["Ручная корректировка заказа<br/>ответ до 1 с (M,L)"]
A --> A1["Отказ узла расчёта<br/>не срывает отправку заказов (H,M)"]
M --> M1["Новый формат поставщика<br/>за 3 дня (H,M)"]
M --> M2["Смена алгоритма прогноза<br/>без правки автозаказа (M,H)"]
S --> S1["Поставщик видит только<br/>свои заказы (H,L)"]
Как читать оценки:
- (H,H) — главные архитектурные драйверы. На них тратится основное внимание архитектора, по ним проводится анализ компромиссов и прототипирование.
- (H,M) и (H,L) — важные, но понятные. Нужно убедиться, что решение их покрывает, чаще всего типовыми тактиками.
- (M,H) и (L,H) — кандидаты на обсуждение с бизнесом: дорого, а ценность средняя. Часто разумно ослабить требование.
- (L,L) — фиксируются и не обсуждаются.
Дерево ценно не картинкой, а процессом: заказчик вынужден ранжировать, а архитектор получает список сценариев, на которых проверяется решение. Если все листья помечены H по важности, это сигнал, что ранжирование не проведено, — стоит спросить, от какого сценария бизнес откажется первым при сокращении бюджета вдвое.
Конфликты атрибутов
Атрибуты качества почти никогда не улучшаются одновременно. Три классические пары:
Производительность против защищённости. Шифрование, проверка токена на каждом вызове, детальный аудит, изоляция сетевых зон добавляют задержку и нагрузку. Компромиссы: проверять подпись токена локально вместо обращения к серверу авторизации на каждый запрос, писать аудит асинхронно с гарантией доставки, разделять поток данных по чувствительности и усиливать защиту только там, где она нужна.
Доступность против согласованности. При разрыве сети между узлами система выбирает: отказать в операции, чтобы не допустить расхождения, или принять её и согласовать данные позже. Это следствие теоремы CAP; расширение PACELC добавляет, что и без разрывов приходится выбирать между задержкой и согласованностью. Компромисс ищется по типам данных: остаток денег на счёте — строгая согласованность, остаток товара в каталоге интернет-магазина — допустимо показать с задержкой и перепроверить при оформлении.
Модифицируемость против производительности. Слои абстракции, обобщённые интерфейсы, обмен через шину упрощают изменения, но добавляют преобразования и сетевые переходы. Компромиссы: держать гибкость на границах, где изменения действительно ожидаются, и позволять прямые, оптимизированные пути на горячем участке; денормализовать для чтения, сохраняя нормализованный источник истины.
Способ найти компромисс один: вернуться к сценариям и их мерам. Спор «безопасность важнее скорости» не решается. Спор «проверка через сервер авторизации добавляет 30 мс к p95, бюджет 200 мс, запас есть» решается за минуту. Выбранный компромисс фиксируется в записи архитектурного решения вместе с причинами.
Тактики
Тактика — типовой архитектурный приём, который улучшает конкретный атрибут. Тактики удобны тем, что превращают сценарий в список кандидатов на решение.
| Атрибут | Группы тактик | Примеры |
|---|---|---|
| Доступность | Обнаружение отказов, восстановление, предотвращение | Heartbeat и health check, резервирование активное и пассивное, повтор с идемпотентностью, автоматическое переключение, деградация функциональности, вывод узла из обслуживания |
| Производительность | Управление спросом на ресурсы, управление ресурсами | Ограничение частоты запросов, приоритизация, пакетная обработка, кеширование, реплики для чтения, параллелизм, секционирование данных |
| Модифицируемость | Снижение связности, повышение связности внутри модуля, отложенное связывание | Интерфейсы и адаптеры, выделение модулей по причинам изменений, конфигурация вместо кода, плагины, события вместо прямых вызовов |
| Защищённость | Обнаружение атак, противодействие, реакция, восстановление | Аутентификация и авторизация, шифрование, минимальные привилегии, ограничение поверхности атаки, аудит, отзыв доступа |
Деградация заслуживает отдельного упоминания: это тактика доступности, которая требует решений от бизнеса. Если сервис рекомендаций недоступен, карточка товара показывается без рекомендаций; если недоступен сервис прогноза, автозаказ строится по средним продажам прошлой недели. Какие функции можно отключить и что показывается взамен, должно быть в требованиях, а не придумано дежурным в момент аварии.
Как проверять
Требование, которое не проверяется, со временем перестаёт выполняться.
Нагрузочное тестирование проверяет производительность до выхода в эксплуатацию. Виды: нагрузочный тест на ожидаемом профиле, стресс-тест до отказа (найти предел и посмотреть, как система деградирует), длительный тест (утечки ресурсов, рост очередей), тест всплеска. Условия осмысленного теста: профиль нагрузки взят из реальных данных или обоснованной оценки, объём данных в базе сопоставим с эксплуатационным (план запроса на тысяче строк и на ста миллионах разный), окружение сопоставимо по ресурсам, мера реакции из сценария задана заранее, и результаты сравниваются с ней по перцентилям, а не по среднему.
Учения по отказам. Доступность проверяется только отказом. Плановые учения (game day) — заранее подготовленное отключение узла, зоны или зависимости с наблюдением за реакцией и замером времени восстановления. Хаос-инжиниринг (chaos engineering) делает это регулярным и автоматическим. Для начала достаточно сценариев из дерева полезности: отключить узел расчёта и проверить, что заказы уходят поставщикам.
Архитектурные функции пригодности (fitness functions). Идея из книги Building Evolutionary Architectures (Форд, Парсонс, Куа): каждое важное архитектурное свойство выражается автоматической проверкой, которая регулярно выполняется. Примеры:
- Тест в сборке проверяет, что модуль автозаказа не импортирует внутренние классы модуля прогноза, только его публичный интерфейс.
- Нагрузочный тест в конвейере на каждый релиз: p95 ручной корректировки заказа не выше 1 секунды на эталонном объёме данных.
- Проверка отсутствия циклических зависимостей между модулями.
- В эксплуатации — отслеживание доли ошибок относительно целевого уровня обслуживания (SLO) с оповещением при быстром расходовании бюджета ошибок.
Функции пригодности переводят атрибуты качества из документа в код, и это лучший способ не потерять их после ухода автора требований.
Типичные ошибки
- Писать атрибуты качества прилагательными («быстро», «надёжно», «масштабируемо») без меры реакции и среды.
- Задавать производительность средним временем отклика вместо перцентилей и не указывать нагрузку и объём данных, при которых она измеряется.
- Путать ограничения с атрибутами качества и пытаться оптимизировать то, что нужно просто соблюсти, или наоборот.
- Помечать все сценарии как высокоприоритетные и не обсуждать с бизнесом, от чего можно отказаться.
- Требовать максимума по всем атрибутам сразу, не видя конфликтов, и узнавать о них на нагрузочном тесте.
- Считать нагрузочный тест на пустой базе или слабом стенде доказательством производительности.
- Описать деградацию в требованиях, но ни разу не проверить её учениями.
Как говорить об этом на собеседовании
На вопрос о нефункциональных требованиях senior отвечает не списком «производительность, надёжность, безопасность», а способом работы: «я перевожу пожелание в сценарий с измеримой мерой, приоритизирую сценарии с бизнесом по важности и сложности и проверяю их тестами». Хорошо привести один сценарий целиком, например для доступности сервиса приёма платежей: отказ узла, время переключения, ноль потерянных поручений, отсутствие дублей.
Покажите понимание компромиссов на своём примере: где выбрали согласованность ценой доступности или гибкость ценой задержки, и по какой мере это решили. Упоминание дерева полезности, тактик и функций пригодности показывает знакомство с инструментарием, но ценнее история о том, как сценарий с конкретной мерой изменил архитектурное решение.
Коротко
- Архитектуру определяют атрибуты качества и ограничения; функции размещаются в ней и меняются дешевле.
- ISO/IEC 25010 — чек-лист направлений качества, который защищает от пропусков, а не готовые требования.
- Сценарий из шести частей (источник, стимул, артефакт, среда, реакция, мера) делает требование проверяемым; ключевая часть — мера реакции.
- Дерево полезности ранжирует сценарии по важности и сложности; драйверы архитектуры — пары (H,H).
- Атрибуты конфликтуют: производительность и защищённость, доступность и согласованность, модифицируемость и производительность. Компромисс решается через меры сценариев и фиксируется в ADR.
- Тактики — типовые приёмы для каждого атрибута; деградация требует решений бизнеса заранее.
- Проверка — нагрузочные тесты на реалистичных данных, учения по отказам и автоматические функции пригодности.
Читать дальше
- Bass, Clements, Kazman, Software Architecture in Practice — главы об атрибутах качества и сценариях.
- Стандарт ISO/IEC 25010 (обзор на iso25000.com).
- Карл Вигерс, «Разработка требований к программному обеспечению» — главы о нефункциональных требованиях.
На system-design.space:
- Что такое архитектура ПО и зачем она нужна в системном дизайне
- Fundamentals of Software Architecture (краткий обзор)
- Software Requirements (краткий обзор)
- Задержка (latency): физика, перцентили и бюджеты
Практика
- Взять пять размытых требований из своей практики (обезличенно: «быстро», «надёжно», «безопасно», «легко менять», «масштабируемо») и переписать каждое как сценарий из шести частей.
- Построить дерево полезности для обезличенной системы: 3–4 атрибута, по 2–3 сценария, оценки важности и сложности.
- Найти в своей системе два конфликтующих атрибута и записать, какой компромисс был выбран и почему.
Вопросы для самопроверки
- Чем атрибут качества отличается от функционального требования?
- Из каких частей состоит сценарий атрибута качества? Приведите пример для доступности.
- Как приоритизировать атрибуты качества, если все «важны»?
- Приведите два примера конфликтующих атрибутов и способы найти компромисс.
- Как проверить, что система удовлетворяет требованию производительности, до выхода в эксплуатацию?
- Зачем нужен стандарт ISO 25010, если требования всё равно пишутся под проект?