Как нефункциональные требования влияют на архитектуру

Привет, Хабр, меня зовут Светлана Уварова, я — ведущий системный архитектор в МТС.  

В этой статье я расскажу о том, как может меняться архитектура системы в зависимости от нефункциональных требований к ней, и как важно знать все нефункциональные требования на начальном этапе проектирования системы.

c0486bb41d8a07fc0cd1f0e6b4ebf6b0.jpg

Откуда берутся нефункциональные требования

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

Поэтому появляются важные нефункциональные требования.
Например, к длительности простоев системы во время обновлений или после аварий и, как следствие, к скорости восстановления.

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

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

Немного терминологии: что такое сервис и его описание

Чтобы далее мы говорили на одном языке, объясню пару терминов.

Начнём с каталога сервисов.
Речь, понятное дело, не про витрину с иконками приложений. В телекоме всегда есть оборудование, которое делает возможным звонок с телефона или выход в интернет. Когда мы, как простые пользователи,   звоним, мы не думаем об этом.

Оборудование понимает только свой язык и предлагает только конкретные возможности, на том же языке и написанные. Список этих возможностей описан в нашем каталоге, но не в виде «Тариф Безлимитище на 100 минут», а в виде аббревиатур, понятных оборудованию — TS10, TS22.

Когда мы звоним из Москвы в Екатеринбург, почти никто не задумывается, что для этого в фоне автоматика включила сервисы T11, TS21. Машинное описание в сервисном каталоге преобразуется в человеческое, и вуаля — набор непонятных аббревиатур становится минутами и гигабайтами.

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

Рисунок 1. Схема описания сервиса

Рисунок 1. Схема описания сервиса

На схеме сервис описывают два оператора.

Оператор № 1 — инженер — описывает сервис и получает несколько спецификаций, потому что сервис может подходить для разного оборудования. 

Оператор №2 не знает технических нюансов и особенностей оборудования. Но ему и не нужно, ведь есть первый оператор и его описание. А задача второго оператора — составлять предложения потребителям. Возможно, это продуктолог или маркетолог, специалист по продажам. И в своём описании этот оператор № 2 ссылается на описание этого же сервиса от оператора № 1 (инженера).

Разберёмся на примере: клиент получает голосовую связь. Но сам сервис подключается на трёх видах оборудования: отдельно для 2G, 3G, 4G. Так клиент может звонить и не думать, что какая-то технология не поддерживается.

Оператор № 2 — продуктолог или маркетолог — описал сервис так, что клиент его увидел и захотел подключить. И в этом описании нет технических нюансов. Там больше рассказано про количество минут, например, или роуминг при выезде за границу. А оператор № 1 написал три отдельных технических описания, три скрипта, которые нужны как раз для настройки оборудования под все эти стандарты связи. Но клиент их, разумеется, не видит.

Собственно, говоря об описаниях, мы имеем в виду эти два уровня:

  • уровень абстракции № 1 — описание для оборудования, включая скрипты подключения сервиса на оборудовании;

  • уровень абстракции № 2 — описание, не требующее знаний специфики оборудования. 

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

Как меняется архитектура

На примере каталога телеком-сервисов объясню, как меняется архитектура системы. Реализовывать нефункциональные требования в этом примере буду по очереди — так будет ясно, что будет, если не учесть все требования сразу.

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

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

Функциональные требования

FR-1.
В системе должно быть описание сервиса, которого будет достаточно для включения или отключения сервиса на оборудовании.

Формальный вариант

Система должна предоставить возможность описания сервиса, так, чтобы это описание можно было применить для включения/отключения экземпляра сервиса на телекоммуникационном оборудовании;

FR-2.
В системе должно быть описание сервиса, которое можно использовать, чтобы составить клиентское предложение. Описание должно быть понятно сотрудникам без специфических знаний — оператору каталога, менеджеру по продажам, маркетологу.

Формальный вариант

Система должна предоставить возможность описания сервиса таким образом, чтобы для описания предложений клиентам, оператору, формирующему описание в каталоге, не потребовались специфические знания, настраиваемые по требованию в FR-1. 

Собственно, так мы и получаем те два уровня описаний, о которых я говорила в предыдущем разделе.

Нефункциональные требования

 NFR-1
Операторы системы (инженеры, продуктологи, маркетологи) должны иметь возможность в своё рабочее время создавать описания сервисов.

Формальный вариант

Возможность описания и настройки сервисов должна быть доступна в рабочее время операторов, выполняющих настройку и описание;

NFR-2

Подключение или отключение сервисов на оборудовании должно быть доступно круглосуточно (кроме времени технических работ). Система может быть недоступна не более 12 часов за год.

Формальный вариант

Возможность чтения описания сервисов для процессов подключения/отключения сервисов должна быть доступна 24/7, за исключением времени технических работ. Суммарно недоступность системы не должна превышать 12 часов в год;

NFR-3

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

Формальный вариант

Описание сервисов, доступное для процессов подключения клиентам, должно гарантировать его подключение/отключение. Т. е. описания должно быть достаточно, чтобы выполнить подключение/отключение сервиса на оборудовании;

NFR-4

Система должна быть достаточно изолирована, чтобы сбой в одной её части не вызывал проблем в других частях.

Формальный вариант

Недоступность одной возможности (функции) системы не должна вызывать недоступность других функций;

NFR-5

У 95 из 100 пользователей страницы с информацией о сервисе и его настройке должны открываться меньше, чем за 2 секунды при нагрузке 200 запросов в секунду (RPS).

Формальный вариант

Время отклика методов чтения описания сервиса для процессов настройки при нагрузке 200 запросов в секунду (RPS) не должно превышать 2 секунд для 95% запросов;

NFR-6

У 98 из 100 пользователей подключение или отключение сервиса должно происходить за 50 мс при нагрузке 1200 RPS.

Формальный вариант

Время отклика методов чтения описания сервиса для процессов подключения/отключения сервисов при нагрузке 1200 RPS не должно превышать 50 мс для 98% запросов.

Реализация FR-1, FR-2 и NFR-1

Если реализовывать требования FR-1, FR-2 и NFR-1, то архитектура системы вполне может выглядеть как на рисунке 2.

Кроме уже знакомых нам операторов (которые условно будут инженером и продуктологом) появляется центр обработки данных (ЦОД) № 1:

  • общая витрина (front/сайт). Нужна, чтобы вносить оба вида описания;

  • модуль внутренней логики системы (back);

  • база данных.

Здесь мы получаем самую простую архитектуру: front-back-database.
Она позволит операторам описывать сервис в их рабочее время и сохранять это описание в базе данных.

Рисунок 2. Архитектура системы, реализующей требования FR-1, FR-2, NFR-1

Рисунок 2. Архитектура системы, реализующей требования FR-1, FR-2, NFR-1

Реализация NFR-2

Для выполнения требования NFR-2 база данных и backend-система должны быть доступны для подключения и отключения сервиса круглосуточно. При этом, у нас нет требования о доступности системы 24/7 для операторов. Значит, мы можем использовать второй центр обработки данных (ЦОД), где развернём резервные копии системы и базы данных без frontend-модуля.

Рисунок 3. Архитектура системы, реализующей требования FR-1, FR-2, NFR-1, NFR-2

Рисунок 3. Архитектура системы, реализующей требования FR-1, FR-2, NFR-1, NFR-2

С помощью второго ЦОД мы повысили надёжность системы. Если вдруг сломается первый ЦОД, то второй будет доступен. А значит, время недоступности системы из-за поломки будет минимальным. И можно будет спокойно чинить первый ЦОД, пока второй работает. Иначе система запросто может простаивать 3 часа, пока её не починят. А с такой архитектурой этого не случится.

Реализация NFR-4

В системе должна быть возможность настроить сервис на уровне оборудования даже если нельзя настроить её на уровне клиента. Это требование NFR-4. Чтобы его выполнить, мы выделим компоненты на разных уровнях, имеющие отдельные базы данных (рис. 4).

Рисунок 4. Архитектура системы, реализующей требования FR-1, FR-2, NFR-1, NFR-2, NFR-4

Рисунок 4. Архитектура системы, реализующей требования FR-1, FR-2, NFR-1, NFR-2, NFR-4

На прошлых схемах мы описывали одну базу и один сервис с логикой. Но сейчас, выполняя требование об изолированности системы, мы делим базы на два уровня.
Одна база — для описаний «с железом» — с ней работают технические специалисты.
Над второй базой — для описаний «без железа» — работают сотрудники без глубоких технических знаний.
Соответственно, операторы каждого уровня работают со своей базой и своим сервисом.
Если упадёт сервис или база для описания «с железом», сотрудники, работающие с базой без него просто спокойно продолжат работать. И наоборот.
Оба уровня имеют по 2 ЦОД — резервный и основной. Мы ведь помним, что нам нужно как можно меньшее время простоя.

Реализация NFR-3, NFR-5, NFR-6

Теперь выполняем требование NFR-3: описание сервиса, полученное при подключении и отключении, должно гарантировать отсутствие ошибок на этих этапах.
Для этого нужно организовать тестирование каждого описания.
И только после успешного тестирования описания сервиса можно переходить к боевому подключению или отключению.

Объясню на примере.

В системе есть 2 вида описания. Для фактического подключения нужны оба. Например, с витрины (сайт «Мой МТС») приходит команда «Подключить возможность звонить». Это описание без технических подробностей, без оборудования. А система, которая будет выполнять эту команду, должна понять, что именно ей на оборудовании делать. То есть, она связывает описание без «железа» с описанием «с железом» и запускает нужные скрипты.
И набор вот этой связанной между собой информации изображен на схеме ниже (рис. 5). Мы называем его либо графом, либо деревом спецификаций (описания).
Для быстрого чтения данных и подключения сервиса нужны все описания со всеми связями. Если запрашивать всё по отдельности, будет очень долго.

А когда мы учтём требования NFR-5 и NFR-6, то нагрузка на чтение графа станет ещё выше.

Рисунок 5. Граф, состоящий из описаний сервиса на разных уровнях абстракции (частично протестированный и полностью протестированный)

Рисунок 5. Граф, состоящий из описаний сервиса на разных уровнях абстракции (частично протестированный и полностью протестированный)

Чтобы выполнить оставшиеся требования можно ввести ещё один компонент. Он будет хранить набор протестированных описаний в такой же сущности-графе с собственным кешем запросов и ответов. Компонент можно будет горизонтально масштабировать.
Вопрос «Как сам граф попадет в новый компонент?», оставим за кадром. А тем временем, архитектура системы будет выглядеть уже по-другому.

Рисунок 6. Архитектура системы, реализующей требования FR-1, FR-2, NFR-1, NFR-2, NFR-3, NFR-4, NFR-5, NFR-6

Рисунок 6. Архитектура системы, реализующей требования FR-1, FR-2, NFR-1, NFR-2, NFR-3, NFR-4, NFR-5, NFR-6

Как мы понимаем, кроме ЦОД-ов, разных уровней описаний у нас появляется ещё один сервис — хранение графов.

Он контролирует корректную работу графа — иначе будут ошибки при подключении сервиса из-за неправильно работающего описания. Проверенный граф уходит на исполнение.

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

Что будет, если не учитывать нефункциональные требования

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

Заключение

Вот так, казалось бы, из трёх кубиков изначальных складывается большая и сложная архитектура. А всё из-за нефункциональных требований к ней.

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

© Habrahabr.ru