Модуль 13.2. Портфолио системного аналитика
Как собрать «проектную папку»: SRS, BPMN, ER, OpenAPI, RTM, NFR. Пошаговая инструкция, готовые шаблоны, примеры, риски, Q&A.
Зачем портфолио SA и что должно быть на выходе
Цель — показать, что вы умеете превращать «хаотичное требование» в согласованный пакет артефактов, пригодный для релиза: Vision → SRS → BPMN/DMN → ER/словарь → OpenAPI/Events → NFR/Observability → RTM → AC/BDD → UAT → C4.
Результат модуля — репозиторий вида Docs-as-Code с «проектной папкой», ссылкой, которую можно приложить к отклику и открывать на собеседовании за 3–5 минут.
Принципы «Docs-as-Code» (как сотруднику — к исполнению)
- Одна истина в Git. Документы, диаграммы, схемы — всё рядом с кодом/спецификациями, с версиями и PR-ревью.
- Явная версия + CHANGELOG. Семантическое версионирование (1.3.0), в каждом файле version:/шапка с датой и владельцем.
- Ссылки между артефактами. Любой артефакт знает, где его контекст в SRS и где его проверяют тесты (RTM).
- Артефакт ≠ стена текста. Графы (C4), диаграммы (BPMN/UML), контракты (OpenAPI), таблицы (RTM/NFR).
- Проверяемость. Для каждого NFR — «как проверю». Для каждого REQ — «чем докажу».
- НДА-безопасность. Анонимизация домена/данных, синтетика, универсальные названия.
Структура репозитория (скелет)
portfolio/ README.md # 1-страничная витрина: домен, что внутри, как навигироваться vision/vision.md srs/srs.md # + srs/changelog.md processes/bpmn_main.bpmn # BPMN XML или .puml rules/dmn_tables.dmn # (если есть правила) data/er.puml # ER PlantUML/снимок + data/dictionary.md contracts/openapi.yaml # или contracts/*.yaml (по сервисам) contracts/events/ # JSON Schema/Avro событий quality/nfr_catalog.md quality/observability.md # логи/метрики/трейсы/алерты rtm/rtm.csv # трассируемость REQ→AC→Tests→API/Events→Metrics tests/ac_bdd/*.feature # BDD-сценарии uat/uat_plan.md c4/context_l1.puml # C4 L1 c4/containers_l2.puml # C4 L2 adr/ADR-0001-decision.md # ключевые решения (по необходимости)
Бранчи/теги: main — опубликованная версия; feature-ветки — правки; теги vX.Y.Z.
«Проектная папка»: что в каждом артефакте (шаблоны + нюансы)
SRS (Software Requirements Specification)
Шапка: название, версия, владелец, дата, ссылки на OpenAPI/BPMN/ER/RTM.
Секции (минимум):
- Введение: цели/глоссарий/ссылки.
- Контекст и границы (C4 L1/L2, акторы).
- Внешние интерфейсы (API/Events/UI ссылки).
- Функциональные требования (REQ-идентификаторы REQ-ORD-001 и т. п.).
- Нефункциональные: производительность/надёжность/безопасность/наблюдаемость/локализация/доступность.
- Данные: ER, словарь, DQ-правила.
- Сценарии и состояния: Use Case, BPMN/UML State/Sequence.
- Ограничения/допущения.
- Трассируемость (ссылка на RTM).
- Критерии приёмки (AC/BDD ссылки).
Рыба требования (измеримая):
REQ-PAY-003 Сервис ДОЛЖЕН возвращать 202 Accepted для платежей с асинхронным PSP и публиковать событие payment.pending.v1 в течение ≤ 2 сек p95. Метод проверки: e2e + измерение SLI.
BPMN (Collaboration)
Минимум: пулы (клиент/ваш продукт/провайдеры), Event-based gateway на «ожидании внешнего события vs таймера», Boundary (timer/error/compensation), End на всех ветвях.
Ссылки: в аннотациях — OpenAPI#/paths/..., events/payment.captured.v1.json, DMN/SLA.
Чек-лист качества: message-flows между пулами, default-ветви у XOR, нет «висящих» токенов.
ER + словарь данных
ER (PlantUML фрагмент):
@startuml
entity "Order" as Order {
* order_id : UUID <<PK>>
--
customer_id : UUID
status : ENUM
total_amount : DECIMAL(18,2)
currency : CHAR(3)
created_at : TIMESTAMP
}
entity "OrderItem" as Item {
* order_item_id : UUID <<PK>>
--
order_id : UUID <<FK>>
sku : STRING
qty : INT
unit_price : DECIMAL(18,2)
}
Order ||--o{ Item
@enduml
Словарь (фрагмент):
|
Атрибут |
Тип |
Обяз. |
Домены/справ. |
DQ-правило |
Комментарий |
|---|---|---|---|---|---|
|
currency |
CHAR(3) |
да |
ISO 4217 |
IN (RUB,USD,EUR) ≥ 99.9% |
хранить в мин. ед. |
|
total_amount |
DECIMAL(18,2) |
да |
≥0 |
NOT NULL=100% |
округление в БД |
OpenAPI (фрагмент)
openapi: 3.0.3
info: { title: Orders API, version: 1.2.0 }
paths:
/v1/orders:
post:
summary: Place order
parameters:
- in: header
name: Idempotency-Key
required: true
schema: { type: string, maxLength: 128 }
- in: header
name: X-Correlation-Id
required: true
schema: { type: string }
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PlaceOrderRequest'
responses:
"201": { description: Created }
"202": { description: Accepted (async payment) }
"409": { description: Duplicate idempotency key → previous result }
"422": { description: Validation error }
components:
schemas:
PlaceOrderRequest:
type: object
required: [items, customerId]
properties:
customerId: { type: string, format: uuid }
items:
type: array
items: { $ref: '#/components/schemas/OrderItem' }
OrderItem:
type: object
required: [sku, qty]
properties:
sku: { type: string }
qty: { type: integer, minimum: 1 }
security:
- oauth2: [orders:write]
События (JSON Schema фрагмент):
{
"title":"payment.captured.v1",
"type":"object",
"required":["eventId","occurredAt","paymentId","orderId","amount","currency"],
"properties":{
"eventId":{"type":"string","format":"uuid"},
"occurredAt":{"type":"string","format":"date-time"},
"paymentId":{"type":"string","format":"uuid"},
"orderId":{"type":"string","format":"uuid"},
"amount":{"type":"string","pattern":"^[0-9]+(\\.[0-9]{2})$"},
"currency":{"type":"string","enum":["RUB","USD","EUR"]},
"correlationId":{"type":"string"}
}
}
RTM (requirements traceability matrix)
rtm/rtm.csv (пример строк):
REQ_ID,Description,AC_ID,Test_ID,API/Schema Ref,Metric/Alert,Status REQ-ORD-001,Create order with Idempotency,AC-ORD-01,TC-ORD-01,openapi#/paths/~1v1~1orders/post,N/A,Approved REQ-PAY-003,Return 202 on PSP timeout,AC-PAY-03,TC-PAY-07,openapi#/paths/~1v1~1payments/post,SLO-PAY-202,Approved REQ-TRK-005,Consume tracking webhooks,AC-TRK-01,TC-TRK-02,events/tracking.updated.v1.json,ALERT-QUEUE-LAG,In Review
NFR + Observability
Каталог NFR (таблица):
|
ID |
Область |
Требование |
Окно |
Метод проверки |
|---|---|---|---|---|
|
NFR-PERF-01 |
POST /v1/orders |
p95 ≤ 900 мс, p99 ≤ 1500 мс |
08:00–23:00 CET |
нагрузочный тест + SLI |
|
NFR-AVAIL-01 |
Orders API |
≥ 99.9% успешных запросов/мес |
календарный месяц |
SLO-дашборд |
|
NFR-SEC-03 |
Аутентификация |
OAuth2 + JWT RS256, scopes |
всегда |
инспекция + e2e |
|
NFR-OBS-02 |
Логи |
JSON-схема, traceId, PII masking |
всегда |
log-парсеры + smoke |
Observability (фрагмент):
- Логи: JSON со схемой, поля: timestamp, level, traceId, correlationId, route, status, duration_ms.
- Метрики RED (Rate, Errors, Duration) для ключевых эндпоинтов.
- Трейсинг: OpenTelemetry, спаны для обращений к PSP/Carrier.
- Алерты: p95 > SLO 5 мин, queue_lag > N, error_rate > X%.
AC/BDD (Gherkin фрагмент)
Feature: Payment timeout handling
Scenario: PSP does not respond within 25 seconds
Given an authorized order with amount "100.00" "RUB"
When client POSTs /v1/payments with Idempotency-Key "K1"
And PSP does not respond within "25" seconds
Then API returns "202" Accepted
And event "payment.pending.v1" is published within "2" seconds
UAT (минимальный план)
- Цель: подтвердить, что фича закрывает бизнес-цели Vision.
- Вход: RC v1.2.0, тест-окружение, учетные записи PSP/Carrier.
- Роли: Бизнес (A), SA (Driver), QA (C), DevOps (C).
- Критерии: 0 критических дефектов, SLO «зелёные», журнал решений подписан.
Как выбрать темы (3 портфельных проекта)
- Fintech/платежи: инвойс → платёж → рефанд (асинхронный PSP, идемпотентность, события).
- E-commerce/логистика: заказ → SLA доставки (DMN) → трекинг → возврат.
-
ERP/1C/CRM: заказ → счёт → отгрузка → оплата, маппинг ExternalId↔GUID, справочники/DQ.
(+ по желанию DWH/BI: CDC → витрины → Export API + NFR свежести).
Каждый проект — полный пакет разделов из §4.
Пошаговый план сборки портфолио (7–10 дней, 1–2 ч/день)
- День 1: Vision + глоссарий + C4 L1.
- День 2: SRS скелет (разделы 1–4), список REQ.
- День 3: BPMN (Collaboration), альтернатива/ошибки/таймеры.
- День 4: ER + словарь данных + DQ-правила.
- День 5: OpenAPI + каталог ошибок + примеры; события (JSON Schema).
- День 6: NFR + Observability; AC/BDD (3–5 сценариев).
-
День 7: RTM связки; UAT план; CHANGELOG; README-витрина.
8–10) Полировка, второй проект, единая лексика.
Качество и автоматические проверки (рекомендуется)
- OpenAPI линт: Spectral (правила: обязательные коды, описания, securitySchemes).
- BPMN линт: bpmn-lint (проверка висящих потоков, событий, End).
- YAML/MD: yamllint/markdownlint.
- SQL стиль: sqlfluff (если включаетe SQL-пример).
- Сборка: GitHub Actions/GitLab CI — запуск линтеров на PR.
- Метки качества: бейджи «CI passing», «Docs updated».
Витрина портфолио (README.md)
Структура:
- Что за домен и цель: 2–3 предложения.
- Цифры/результаты (симуляция ок): «SLO p95 ≤ 900 мс; SLA свежести D+1 99.7%».
- Карта артефактов: список с гиперссылками (SRS, BPMN, ER, OpenAPI, NFR, RTM, AC/BDD).
- Как проверить: команда/шаги для линтов/генерации HTML из OpenAPI (Swagger-UI).
- Версия и лицензия/НДА-примечание.
НДА и этика: как не «утечь»
- Переименуйте сущности/идентификаторы.
- Генерируйте синтетические данные.
- Схемы/контракты показывайте на упрощённых доменах.
- Явно пометьте «учебный/обобщённый пример», уберите логотипы/внутренние URL.
- В событиях/логах — нет PII (только токенизированные идентификаторы).
Типовые риски и как их закрыть
|
Риск |
Симптом |
Контрмера |
|---|---|---|
|
«Ковер» BPMN |
40+ элементов на листе |
Декомпозируйте на подпроцессы; ≤12 на уровень |
|
SRS «роман» |
Нет измеримости |
Переписать на shall + метрика + метод |
|
Разный UL |
Термины не совпадают |
Глоссарий; линк из каждого артефакта |
|
Пустой RTM |
Нельзя проследить покрытие |
Минимум CSV, автоматизируйте генерацию ссылок |
|
NFR «вода» |
«быстро/надёжно» |
SLO формула: метрика/окно/метод/владелец |
|
Без версий |
Непонятно, что поменяли |
CHANGELOG, semver, теги в Git |
|
PII в примерах |
Риски комплаенса |
Маскирование, выдуманные адреса/емейлы |
Примеры «как показать ценность» (буллеты в README/резюме)
- «Описал POST /orders с Idempotency-Key → –68% дублей в заказах (учебный стенд).»
- «DMN для SLA доставки (зоны/вес/cut-off) → +9 п.п. on-time (эмуляция).»
- «RTM REQ→AC→Tests→API → закрыли 100% требований тестами (портфельный кейс).»
- «Observability: RED-метрики + трассы PSP → MTTR –35% (симуляция инцидента).»
Практика (задание): собрать «проектную папку»
Домен на выбор: финтех (инвойс/платёж), e-com (заказ/доставка/возврат), ERP/1C (заказ→счёт→реализация→оплата), DWH/BI (CDC→витрины→Export API).
Что сдать:
- vision/vision.md (цели/персоны/метрики/риски).
- srs/srs.md (полный скелет + ≥10 REQ, ≥5 NFR).
- processes/bpmn_main.bpmn (Collaboration с events/timers/compensation).
- data/er.puml + data/dictionary.md (≥6 сущностей, ключи, DQ).
- contracts/openapi.yaml (≥5 эндпоинтов, 201/202/409/422, security).
- contracts/events/*.json (≥2 доменных события).
- quality/nfr_catalog.md + quality/observability.md.
- rtm/rtm.csv (покрыть все REQ).
- tests/ac_bdd/*.feature (≥3 файла).
- uat/uat_plan.md.
- c4/context_l1.puml, c4/containers_l2.puml.
- adr/ADR-0001-decision.md (одно ключевое решение).
- README.md (витрина, ссылки, как проверять).
Критерии зачёта:
- Трассируемость REQ→AC/BDD→Tests→API/Events/NFR соблюдена (RTM полный).
- В BPMN корректная семантика интеграций и обработка ошибок/таймаутов.
- В OpenAPI — идемпотентность, ошибки, безопасность, версионирование.
- ER согласована с API; словарь данных с DQ-правилами.
- NFR измеримы; Observability привязана к SLI/SLO; UAT имеет вход/выход/критерии.
- CHANGELOG присутствует; ссылки в README работают.
Вопрос–Ответ
В: У меня нет «боевых» кейсов. Это критично?
О: Нет. Два-три учебных проекта с релизным пакетом артефактов выглядят лучше, чем один «боевой» без документов. Честно пометьте симуляцию.
В: С чего начать — с данных или с процессов?
О: С Vision/глоссария и C4 L1, затем BPMN/Use Case → ER/словарь → OpenAPI/Events → NFR/Obs → RTM/AC → UAT.
В: Какой объём достаточно для показа на собеседовании?
О: 3–5 ключевых артефактов + RTM + NFR/Obs. Полный пакет держите «за спиной», но на встрече показывайте витрину (README) и кликабельные ссылки.
В: Можно ли использовать Notion/Confluence вместо Git?
О: Да, но Docs-as-Code проще версионировать и линтить. Делайте хотя бы экспорт/реплику в Git, чтобы давать один стабильный URL.
В: Как упаковать курсовые (Практикум/Stepik/Otus/SkillFactory)?
О: Сведите в единый капстоун по шаблону выше, сохраните артефакты как для реального релиза. Ссылки на исходники/диаграммы — обязательно.
В: Нужны ли диаграммы C4?
О: Да, короткие L1–L2 помогают быстро понять контекст и зависимости. Этого достаточно для портфолио.
Теория (почему портфолио работает)
- Снижение неопределённости для нанимающего: есть документы, по которым понятно, как вы мыслите.
- Реплика реальной работы: те же артефакты, что и в проде (SRS/RTM/NFR/OpenAPI/BPMN/ER).
- Отражение зрелости: идемпотентность, события, NFR/наблюдаемость — ключевые «маркеры» системного аналитика.
Шпаргалка-проверка перед публикацией
- README даёт карту и 5 кликов до всего нужного.
- Везде есть версии/владельцы/даты.
- BPMN читабелен (≤12 элементов на уровень), events/таймеры/compensation на месте.
- OpenAPI проходит линт, ошибки и security описаны, есть Idempotency-Key.
- ER согласована с API, словарь покрывает типы/домены/обязательность/DQ.
- NFR измеримы; Observability привязана к метрикам и алертам.
- RTM закрывает все REQ; AC/BDD связаны с тестами.
- Никакой PII/НДА в примерах.
- CHANGELOG обновлён; теги релизов созданы.



