Б.7 Описание решения: спецификация интеграции, диаграммы, нефункциональные требования
Зачем это аналитику
Разница между middle и senior хорошо видна по документам: senior описывает не только «как должно работать», но и что будет при сбоях, какие нагрузки, как решение ложится в ландшафт и почему выбран именно этот вариант. Модуль готовит к блоку 6 и итоговому проекту: даёт шаблон описания решения и учит писать нефункциональные требования, которые можно проверить.
Готовность к модулю
Модуль опирается на темы ниже. Если какая-то из них незнакома или её вопросы для самопроверки даются с трудом, начните с неё.
Куда ведёт
Тема подробнее раскрывается в модулях:
Что понять
- Состав описания решения: контекст, участники, сценарии, модель данных, интеграции, нефункциональные требования, риски, открытые вопросы.
- Контекстная диаграмма: система и её окружение. Первое знакомство с моделью C4.
- Диаграмма последовательности для интеграции: основной сценарий, ошибки, повторы, таймауты.
- Маппинг полей между системами: источник, приёмник, преобразование, правила по умолчанию.
- Нефункциональные требования: производительность, доступность, объёмы, безопасность, аудит — с цифрами и способом проверки.
- Обработка ошибок как часть требований: какие ошибки возможны, кто их обрабатывает, что видит пользователь, что попадает в журнал.
- Фиксация решения и альтернатив: первое знакомство с ADR.
- Как проводить ревью своей постановки с разработкой и тестированием.
Урок
Постановка уровня middle отвечает на вопрос «что система делает, когда всё хорошо». Описание решения уровня senior отвечает ещё на три: что происходит, когда что-то пошло не так; при каких нагрузках и ограничениях это должно работать; почему выбран именно такой способ. Разработчик, тестировщик и эксплуатация читают документ именно ради этих ответов: основной сценарий они часто могут угадать сами, а поведение при сбоях — нет.
Урок построен на одном сквозном примере, и каждый раздел показывает соответствующую часть документа.
Сквозной пример
Банк для юрлиц подключает бухгалтерские системы клиентов напрямую, без ручной выгрузки файлов (интеграция host-to-host). Бухгалтерская система клиента должна уметь две вещи: отправить в банк подписанные платёжные поручения и получить выписку по счёту — список операций с остатками. На стороне банка интеграцию обслуживает отдельный сервис host-to-host, который стоит за API Gateway и работает с автоматизированной банковской системой (АБС) — учётным ядром банка, где живут счета и проводки.
Состав описания решения
Названия разделов в разных компаниях свои, но набор вопросов, на которые документ обязан ответить, устойчив.
| Раздел | На какой вопрос отвечает | Что в нём для примера |
|---|---|---|
| Контекст и цели | Зачем это делается и как поймём, что получилось | Сократить ручную загрузку файлов, цель — 80% поручений крупных клиентов через интеграцию |
| Участники | Кто и что взаимодействует с решением | Бухгалтер, бухгалтерская система, сервис host-to-host, АБС, сервис проверки подписи |
| Границы | Что входит в решение и что нет | Входят поручения и выписки; не входят валютные операции и зарплатные реестры |
| Сценарии | Как проходят основные и альтернативные потоки | Отправка поручения, повтор, отказ, получение выписки за период |
| Модель данных | Какие сущности и статусы появляются или меняются | Входящий документ, ключ идемпотентности, статусы поручения |
| Интеграции | Контракты, протоколы, маппинг полей | Описание API, таблица маппинга, способ аутентификации |
| Обработка ошибок | Что может сломаться и что тогда происходит | Таблица ошибок с реакцией и журналированием |
| Нефункциональные требования | Сколько, как быстро, насколько надёжно и безопасно | Нагрузка, время ответа, доступность, объёмы, аудит |
| Решения и альтернативы | Почему так, а не иначе | Запрос выписки клиентом, а не отправка банком |
| Риски | Что может помешать и что с этим делаем | Разные версии бухгалтерских систем у клиентов |
| Открытые вопросы | Что ещё не решено и кто решает | Срок хранения ключей идемпотентности — ждём ответа ИБ |
Раздел открытых вопросов часто считают признаком незрелости документа. Наоборот: документ без открытых вопросов на ранней стадии либо тривиален, либо скрывает допущения. Важно, чтобы у каждого вопроса был владелец и срок.
Контекстная диаграмма
Контекстная диаграмма показывает систему одним блоком и всё, что её окружает: людей и внешние системы, а на стрелках — что и как передаётся. Внутренности не показываются вовсе. Её задача — провести границу: что наше, что чужое, с кем мы договариваемся о контрактах.
Это первый уровень модели C4 (System Context). C4 предлагает смотреть на систему в нескольких масштабах, как на карте: контекст, затем контейнеры (отдельно разворачиваемые приложения и хранилища), затем компоненты внутри контейнера и, наконец, код. Для описания интеграции почти всегда хватает первого уровня, иногда второго.
flowchart TB
Acc["Бухгалтер клиента<br/>[Человек]<br/>Готовит и подписывает поручения"]
AccSys["Бухгалтерская система клиента<br/>[Внешняя система]<br/>Учёт, формирование документов"]
H2H["Сервис host-to-host<br/>[Проектируемая система]<br/>Приём поручений, выдача выписок"]
Sign["Сервис проверки подписи<br/>[Система банка]<br/>Проверка электронной подписи"]
ABS["АБС<br/>[Система банка]<br/>Счета, проводки, исполнение платежей"]
Portal["Интернет-банк<br/>[Система банка]<br/>Статусы для пользователя"]
Acc -->|"Работает в системе"| AccSys
AccSys -->|"Поручения и запросы выписок, HTTPS с сертификатом клиента"| H2H
H2H -->|"Проверка подписи, синхронно"| Sign
H2H -->|"Регистрация документов, запрос операций"| ABS
ABS -->|"События о смене статуса, асинхронно"| H2H
Portal -->|"Чтение документов, пришедших по интеграции"| H2H
Правила, которые делают диаграмму полезной:
- Одна система в фокусе. Всё остальное — окружение. Если на схеме две «проектируемые системы», это уже другой уровень.
- Подписи на стрелках. «Интеграция» — не подпись. Подпись говорит, что передаётся, и, если важно, как: синхронно или асинхронно, по какому протоколу.
- Легенда типов. Люди, внешние системы, системы своей компании — визуально или текстом различимы.
- Ни одной внутренней детали. Базы, очереди и сервисы внутри системы появятся на следующем уровне.
Диаграмма сразу порождает вопросы, и это её польза. Кто отвечает за сервис проверки подписи и какой у него лимит? Интернет-банк читает данные из нашего сервиса или из АБС? Откуда бухгалтерская система берёт сертификат? Каждый такой вопрос — строка в разделе открытых вопросов.
Диаграмма последовательности: не только основной сценарий
Диаграмма последовательности для интеграции ценна тем, что показывает поведение во времени, включая ожидание, таймауты и повторы. Основной сценарий нарисовать легко. Работа начинается, когда вы добавляете то, что происходит при сбое.
Ключевая ситуация для любой сетевой операции — потерянный ответ. Бухгалтерская система отправила поручение, банк его принял, но ответ не дошёл: оборвалось соединение или сработал таймаут клиента. Клиент не знает, принято поручение или нет. Если он просто отправит его снова, банк может принять его дважды и списать деньги дважды. Решение — ключ идемпотентности (idempotency key): клиент генерирует уникальный ключ на каждый документ и передаёт его при каждой попытке, а банк по этому ключу узнаёт повтор и возвращает прежний результат, не создавая новый документ.
sequenceDiagram
participant ACC as Бухгалтерская система
participant GW as API Gateway банка
participant H2H as Сервис host-to-host
participant ABS as АБС
ACC->>GW: POST payment-orders, ключ K-771
GW->>H2H: запрос после проверки сертификата
H2H->>H2H: проверить подпись и реквизиты, сохранить с ключом K-771
H2H->>ABS: зарегистрировать документ
ABS-->>H2H: зарегистрирован, id 5501
H2H--xACC: 201 Created потерян в сети
Note over ACC: таймаут 30 с, результат неизвестен
ACC->>GW: повтор через 10 с, тот же ключ K-771
GW->>H2H: запрос
H2H->>H2H: ключ K-771 найден, тело совпадает
H2H-->>ACC: 201 Created, документ 5501, без повторной регистрации
alt АБС недоступна при первой попытке
H2H-->>ACC: 503, повторить через 60 с, документ не создан
else ошибка в реквизитах
H2H-->>ACC: 422 с кодом ошибки, повтор бесполезен
else тот же ключ, другое тело
H2H-->>ACC: 422 (встречается и 409), ключ уже использован для другого документа
end
Что должно быть зафиксировано в требованиях рядом с диаграммой:
- Таймауты. Сколько ждёт клиент (здесь 30 секунд), сколько сервис ждёт АБС и сервис подписи. Внутренние таймауты должны быть меньше внешнего, иначе клиент уже сдался, а банк продолжает работу.
- Политика повторов. Какие ответы повторять (таймаут, обрыв,
503), какие нет (4xx, бизнес-отказы). Через какое время, сколько раз, с каким ростом интервала. - Идемпотентность. Как формируется ключ, сколько времени банк его помнит, что происходит при повторе с тем же ключом, но другим содержимым.
- Синхронная и асинхронная часть.
201означает «документ принят», а не «деньги ушли». Исполнение платежа — отдельный процесс в АБС, итоговый статус (исполнен, отклонён) клиент узнаёт позже: запросом статуса или из выписки. Это должно быть написано явно, иначе интегратор клиента будет считать201исполнением.
Обработка ошибок как часть требований
Ошибки — это не приложение к постановке, а такие же требования, как основной сценарий. Для каждой возможной ошибки нужно ответить на пять вопросов: что её вызывает, кто её обрабатывает, можно ли повторить, что видит пользователь, что попадает в журнал.
| Ситуация | Код | Кто обрабатывает | Повтор | Что видит бухгалтер | Журнал |
|---|---|---|---|---|---|
| Ошибка формата или реквизитов | 422 | Бухгалтерская система показывает ошибку | Нет, после исправления — новый документ | Текст ошибки с указанием поля | Код ошибки, ключ, клиент, без полного тела |
| Неверная подпись | 422 | Бухгалтер переподписывает | Нет | «Подпись недействительна» | Факт отказа, идентификатор сертификата |
| Сертификат клиента не принят | 401 или 403 | Администратор клиента, поддержка банка | Нет | «Нет доступа к банку» | Попытка доступа, отпечаток сертификата |
| АБС или сервис подписи недоступны | 503 | Бухгалтерская система автоматически | Да, с тем же ключом | «Отправка отложена» | Ошибка зависимости, время ответа |
| Таймаут или обрыв соединения | нет ответа | Бухгалтерская система автоматически | Да, с тем же ключом | Ничего, пока не исчерпаны повторы | На стороне клиента |
| Отказ при исполнении, например недостаточно средств | статус REJECTED позже | Бухгалтер | Нет, решение по ситуации | Статус и причина отказа | Смена статуса с причиной |
Из таблицы видно разделение ответственности: технические сбои обрабатывает система автоматически, ошибки данных — человек. Если это не записано, каждая сторона будет считать, что обработка на другой.
Отдельно стоит решить, что делать, когда повторы исчерпаны. Типичный ответ — документ остаётся в бухгалтерской системе в статусе «не отправлен», бухгалтер видит уведомление, а поддержка банка может найти все попытки по ключу в журнале. Если в требованиях нет этого пункта, документ может тихо «застрять», и об этом узнают только когда поставщик позвонит спросить, где деньги.
Маппинг полей
Когда две системы описывают одни и те же данные по-разному, нужен маппинг: таблица соответствия полей источника и приёмника. Хороший маппинг отвечает не только на вопрос «какое поле куда», но и на вопросы «как преобразовать», «обязательно ли» и «что делать, если поля нет».
Фрагмент маппинга для поручения — от API host-to-host к внутреннему формату АБС:
| Поле источника | Поле приёмника | Обязательность | Преобразование | Если нет или неверно |
|---|---|---|---|---|
number |
doc_num |
Да | Строка без изменений, проверка формата номера | Отказ 422 |
date |
doc_date |
Да | ISO-дата в формат АБС | Отказ 422, датой по умолчанию не подставлять |
amount |
amount_minor |
Да | Строка в рублях в целое число копеек: «1500.50» в 150050 | Отказ 422, если больше двух знаков после точки |
payer.account |
debit_account |
Да | Без изменений, проверка принадлежности клиенту | Отказ 403 |
payee.bic |
payee_bank_bic |
Да | Проверка по справочнику банков | Отказ 422 |
purpose |
payment_purpose |
Да | Обрезка пробелов по краям | Отказ 422, если длиннее 210 символов |
priority |
payment_priority |
Нет | Без изменений | По умолчанию 5 |
| — | channel |
— | Константа HOST_TO_HOST | Заполняется сервисом |
Несколько правил, которые стоит соблюдать:
- Значения по умолчанию — бизнес-решение. «Очерёдность 5, если не передана» должен подтвердить владелец процесса, а не придумать разработчик. Для даты поручения по умолчанию опасно подставлять «сегодня»: клиент мог готовить документ на завтра.
- Деньги — только в точном формате. Не число с плавающей точкой, а строка или целые копейки, с явным правилом округления или отказа.
- Поля, которых нет в источнике, тоже в таблице. Константы и вычисляемые поля, как
channel, иначе их забудут. - Обратное направление — отдельная таблица. Для выписки маппинг идёт от АБС к клиенту: признак дебета или кредита превращается в знак суммы или отдельное поле направления, внутренние коды операций — в коды, понятные бухгалтерской системе.
Нефункциональные требования с цифрами и способом проверки
Нефункциональное требование без числа — пожелание. «Система должна работать быстро» нельзя ни реализовать, ни проверить. Проверяемое требование содержит метрику, порог, условия, при которых он действует, и способ проверки.
| Атрибут | Требование | Как проверить |
|---|---|---|
| Производительность | Приём одного поручения: 95% ответов не дольше 2 с при нагрузке до 30 запросов в секунду | Нагрузочный тест на профиле с пиком конца месяца; в эксплуатации — метрика p95 на gateway |
| Объёмы | До 5 000 поручений в сутки от одного клиента; выписка за период до 50 000 операций отдаётся постранично, не больше 1 000 операций на страницу | Тест с синтетическим клиентом на граничных объёмах |
| Доступность | Приём поручений доступен 99,9% времени за календарный месяц, плановые работы — только ночью с уведомлением клиентов за 3 рабочих дня | Мониторинг внешней синтетической проверкой раз в минуту, ежемесячный отчёт |
| Надёжность и идемпотентность | Повтор с тем же ключом в течение 72 часов не создаёт второй документ; ни одно принятое с кодом 201 поручение не теряется | Автотест с повтором после искусственного обрыва; ежедневная сверка принятых поручений с АБС |
| Безопасность и аудит | Доступ только по взаимному TLS с сертификатом клиента; каждое поручение с проверенной подписью; каждый запрос журналируется с клиентом, ключом, результатом и временем; журнал хранится не меньше срока, установленного политикой банка, и не содержит полных реквизитов | Тест на отказ без сертификата и с чужим сертификатом; выборочная проверка журнала службой безопасности |
Откуда брать цифры. Заказчик редко называет их сразу, но их можно вывести. Объём — из текущей статистики: сколько поручений крупные клиенты загружают файлами сейчас, какой пик в последние дни месяца. Время ответа — из того, как долго бухгалтерская система готова ждать и как это скажется на пользователе. Доступность — из цены простоя: что будет, если поручения нельзя отправить час в последний день месяца. Цифры в таблице выше — пример для учебного случая, в реальном проекте их выясняют и согласуют.
Обратите внимание на формулировки: «95% ответов» вместо «среднее время», потому что среднее скрывает медленные запросы; «за календарный месяц», потому что 99,9% за день и за год — разные обещания; «при нагрузке до 30 запросов в секунду», потому что без условий порог бессмыслен. Способ проверки — не формальность: если его невозможно придумать, требование сформулировано плохо.
Фиксация решения и альтернатив
Почти в каждой интеграции есть решение, о котором через полгода спросят «почему так». Его стоит записать в виде короткой записи об архитектурном решении (Architecture Decision Record, ADR): контекст, рассмотренные варианты, решение, последствия.
В нашем примере спорный вопрос — как клиент получает выписку.
- Вариант 1. Клиент запрашивает выписку сам (pull): бухгалтерская система периодически вызывает API и забирает операции постранично. Простой контракт, клиент управляет темпом, банку не нужно знать адрес клиента. Минус — задержка появления операций и лишние запросы.
- Вариант 2. Банк отправляет операции клиенту (push): вызов API на стороне клиента при каждой операции. Операции приходят сразу. Минус — у многих клиентов бухгалтерская система не доступна извне, банк должен хранить адреса и сертификаты клиентов, повторять доставку при недоступности.
- Вариант 3. Файлы по расписанию через защищённый файловый обмен. Привычно, но задержка в часы и ручной разбор ошибок.
Решение: вариант 1, плюс лёгкое уведомление «есть новые операции» как возможное развитие. Последствия: нужна пагинация с курсором по времени изменения, чтобы клиент не пропускал операции; задержку до 15 минут бизнес принял; к варианту 2 возвращаемся, если больше трети клиентов попросят мгновенные уведомления.
Зачем записывать отвергнутые варианты. Во-первых, через полгода кто-то снова предложит push, и запись сэкономит день обсуждения: видно, почему отказались и при каком условии решение стоит пересмотреть. Во-вторых, условия меняются, и без записи непонятно, какие допущения устарели. В-третьих, на ревью это показывает, что решение выбрано, а не получилось само.
Ревью постановки с разработкой и тестированием
Документ, который прочитал только автор, почти наверняка содержит пробелы, невидимые автору: он знает контекст и мысленно дополняет пропущенное. Ревью с разработкой и тестированием — способ найти эти пробелы до того, как их найдёт код.
Как провести ревью, чтобы оно работало:
- Разослать заранее и попросить записывать вопросы, а не комментарии «в целом ок».
- Проходить по сценариям, а не по разделам. «Клиент отправил поручение, ответ потерялся, что дальше?» — разработчик вслух проходит путь по диаграмме и маппингу и находит места, где не знает, что делать.
- Тестировщик строит тесты из таблицы ошибок и нефункциональных требований. Если по строке таблицы нельзя написать тест, строка сформулирована плохо.
- Каждый вопрос — пробел в документе. Ответ дописывается в документ, а не остаётся в переписке. Если ответа нет — вопрос уходит в открытые с владельцем.
- Отдельный вопрос эксплуатации: как мы узнаем, что интеграция сломалась, и что будем смотреть в первую очередь.
Полезная метрика собственного роста: сколько вопросов возникает у разработки после ревью, уже в ходе реализации. Чем их меньше, тем лучше был документ.
Что дальше
Урок дал каркас и первое знакомство с инструментами. Нефункциональные требования в форме сценариев атрибутов качества и их приоритизация разбираются в модуле 6.1, форматы и жизненный цикл ADR — в модуле 6.2, уровни C4 и шаблон arc42 — в модуле 6.3. Итоговый проект потребует собрать по такому составу описание целой системы.
Типичные ошибки
- Описан только основной сценарий. Нет таймаутов, повторов, поведения при недоступности смежной системы — эти решения потом принимает разработчик, каждый по-своему.
- Код
201равен «платёж исполнен». Не разделены синхронный приём и асинхронное исполнение, клиент строит учёт на неверном допущении. - Нефункциональные требования словами: «быстро», «надёжно», «высокая доступность» — без числа, условий и способа проверки.
- Маппинг без преобразований и значений по умолчанию. Разработчик сам решает, подставить ли текущую дату и как округлять сумму.
- Контекстная диаграмма с внутренностями: базы и очереди на уровне контекста, стрелки без подписей.
- Решение без альтернатив. Через полгода никто не помнит, почему отказались от очевидного варианта, и обсуждение начинается заново.
- Ревью как формальность: документ рассылают «на согласование» и получают молчание вместо вопросов.
Как говорить об этом на собеседовании
Вопрос «как вы описываете интеграцию» проверяет, думаете ли вы о сбоях. Ответ уровня senior перечисляет состав документа и сразу переходит к тому, что отличает его от простой постановки: потерянный ответ и ключ идемпотентности, разделение синхронного приёма и асинхронного исполнения, таблица ошибок с ответственностью сторон, нефункциональные требования с цифрами и способом проверки, записанные альтернативы.
Хорошо работает конкретный пример из опыта: «В интеграции банка с бухгалтерскими системами мы отдельно описали, что 201 означает приём, а не исполнение, и ввели ключ идемпотентности на документ; до этого после обрывов связи появлялись дубли». На вопрос о нефункциональных требованиях приведите одно требование полностью — метрика, порог, условия, способ проверки — и объясните, откуда взялась цифра.
Коротко
- Описание решения отвечает не только на «что», но и на «что при сбое», «при какой нагрузке» и «почему так».
- Состав: контекст и цели, участники и границы, сценарии, модель данных, интеграции и маппинг, ошибки, нефункциональные требования, решения, риски, открытые вопросы с владельцами.
- Контекстная диаграмма — первый уровень C4: одна система в фокусе, окружение, подписанные стрелки, никаких внутренностей.
- Диаграмма последовательности для интеграции обязана показать таймаут, повтор и ошибки; потерянный ответ решается ключом идемпотентности.
- Для каждой ошибки: причина, кто обрабатывает, повторять ли, что видит пользователь, что пишется в журнал.
- Маппинг включает преобразования, обязательность и правила по умолчанию; значения по умолчанию утверждает бизнес.
- Нефункциональное требование — метрика, порог, условия и способ проверки.
- Решения фиксируются вместе с отвергнутыми вариантами, а ревью с разработкой и тестированием ищет пробелы через сценарии.
Читать дальше
- c4model.com — раздел «System context diagram».
- arc42.org — шаблон описания архитектуры.
- Карл Вигерс, «Разработка требований к программному обеспечению» — главы о нефункциональных требованиях.
На system-design.space:
Практика
- Взять интеграцию из своей практики (обезличенно) и описать её по составу из урока: контекст, диаграммы, маппинг, ошибки, нефункциональные требования.
- Для этой интеграции написать 5 нефункциональных требований с цифрами и способом проверки.
- Попросить коллегу-разработчика прочитать описание и записать его вопросы: каждый вопрос — пробел в документе.
Вопросы для самопроверки
- Из каких разделов состоит описание решения?
- Что показывает контекстная диаграмма?
- Как описать обработку ошибок в интеграции?
- Как сделать нефункциональное требование проверяемым? Приведите пример.
- Зачем фиксировать рассмотренные альтернативы?