Все записи справочника — это отдельные навыки. Здесь они собираются в один проект. Мы ведём одну систему — MeetRoom, внутренний сервис бронирования переговорок — от первого разговора с заказчиком до эксплуатации в проде, и на каждом шаге показываем, какой артефакт аналитик производит и в какой записи разобран нужный навык. Путь: понять бизнес-смысл → выявить требования у стейкхолдеров → собрать SRS → спроектировать (HLD/LLD, зафиксировать выборы в ADR) → описать модель данных и жизненный цикл брони → задать API с ошибками и авторизацией → нарисовать интеграции (календарь по вебхуку) → продумать миграции, эксплуатацию и метрики. Это та самая сквозная нить, которой не хватает, когда теорию учат темами вразнобой: тут видно, как один документ перетекает в другой и почему порядок именно такой.
Когда я учился на аналитика, теория лежала в голове по полочкам: вот требования, вот нотации, вот API, вот базы данных. А потом меня посадили на реальный проект, и оказалось, что полочки не помогают — нужно было пройти путь от «нам нужна штука для переговорок» до работающего сервиса, и я не понимал, что за чем идёт и где какой навык включается. Полочки — это словарь, а проект — это связный текст. Эта запись — связный текст: одна система, проведённая через весь справочник от начала до конца.
Возьмём MeetRoom — внутренний веб-сервис, где сотрудники бронируют переговорки офиса. Та же система, на которой построены примеры в записях про SRS, HLD/LLD и авторизацию. Здесь мы соберём все её куски в один маршрут.
Шаг 1. Зачем это вообще: бизнес-контекст
Любой проект начинается не с требований, а с вопроса «зачем». Прежде чем проектировать MeetRoom, надо понять, какую боль он лечит и сколько она стоит: сотрудники тратят время на поиск свободной комнаты, переговорки занимают «по памяти» и конфликтуют, секретарь ведёт расписание в табличке и ошибается. Это деньги — потерянные часы и сорванные встречи. Как считать эту ценность и почему «зачем» важнее «как» — в записи про бизнес-контекст и деньги. И сразу понимаем, в каком окружении работаем и кто в команде сделает MeetRoom — про роли в записи кто все эти люди.
Чтобы «зачем» не повисло в воздухе, кладу на стол прикидку. В офисе ~200 сотрудников, средняя ставка ~1500 ₽/час. По интервью каждый теряет ~10 минут в день на поиск комнаты и разруливание конфликтов «кто здесь сидит» — это 200 × (10/60) × 1500 ≈ 50 000 ₽ в день, около миллиона в месяц сгоревшего времени. Цифра грубая, но именно она превращает «было бы удобно» в «вот сколько стоит ничего не делать» — и именно её спросит спонсор, прежде чем дать бюджет.
Шаг 2. Выявить требования, а не записать
Заказчик — офис-менеджер — приходит с готовым решением: «сделайте табличку со списком комнат и кнопкой занять». Наша работа — не записать это, а докопаться до проблемы: что на самом деле болит. Это выявление требований: интервью, наблюдение за тем, как комнаты бронируют сейчас, «5 почему». Параллельно составляем карту тех, кто влияет на продукт и может зарубить его на приёмке, — про это запись стейкхолдеры и RACI. Здесь всплывает безопасник с требованием «сотрудник не должен видеть чужие встречи» — стейкхолдер, которого легко пропустить, а его «нет» дороже всего.
Артефакт этого шага — не пересказ интервью, а вскрытый корень. «5 почему» по запросу заказчика выглядят так: хочу табличку с кнопкой «занять» → почему? → чтобы не приходили в занятую комнату → почему приходят? → бронь живёт в голове секретаря → почему в голове? → нет общего источника правды → почему нет? → никто не отвечает за расписание комнат. Корень — не «нет таблички», а «нет единого источника правды о занятости слота». Это и есть настоящее требование, и оно сразу диктует, что слот занятости — атомарная сущность, а не строка в Excel.
До того как писать SRS, решаем, что вообще делаем в первую очередь: бронирование и просмотр — да, оплата платных комнат и интеграция со СКУД — потом. Это MVP и приоритизация, а отделить «что выяснить» от «что строить» помогает дискавери против деливери. И сразу честно оцениваем объём — диапазоном, а не точкой: про это оценка задач.
Шаг 3. Зафиксировать: SRS
Выявленное превращаем в документ, иначе оно не существует. Для MeetRoom это SRS (спецификация требований, SRS) — полная спецификация: цель, границы (что в скоупе, что нет), акторы (сотрудник, офис-менеджер, внешний календарь), функциональные требования с ID (создать бронь, защита от двойного бронирования) и нефункциональные (NFR — нефункциональные требования) с числами (сетка доступности < 800 мс, доступность 99.5%, «сотрудник видит только свои брони»). Как из выявленного собрать читаемый документ — в записи как написать ТЗ; разница между функциональными и нефункциональными требованиями — в FR против NFR, а отдельные сценарии описываем как user story и use case.
Чтобы не оставаться на словах, вот как корень из шага 2 ложится в две строки SRS:
| ID | Тип | Требование |
|---|---|---|
| FR-03 | функциональное | Система отклоняет создание брони, если запрошенный слот пересекается по времени с уже подтверждённой бронью той же комнаты. |
| NFR-02 | нефункциональное | Сетка доступности комнат на день отдаётся за < 800 мс на 95-м перцентиле при нагрузке 50 RPS. |
Видно, чем они отличаются: FR — что система делает (проверяемо да/нет), NFR — насколько хорошо (проверяемо числом). Размытое «должно быть быстро» из NFR-02 превратилось в «< 800 мс на p95» — то, что можно поставить в alert.
Шаг 4. Спроектировать: HLD, LLD, ADR
SRS говорит «что», теперь «как». Сначала крупными блоками — HLD (крупный дизайн, high-level, HLD/LLD): веб-приложение, бэкенд MeetRoom, база, внешний SSO, внешний календарь, и поток создания брони между ними. Потом детали — LLD (детальный дизайн, low-level): схема таблицы броней, контракт POST /bookings, защита от двойного бронирования через уникальное ограничение в БД. А каждый неочевидный выбор фиксируем в ADR (журнал архитектурных решений, ADR), чтобы через полгода никто не «улучшил» решение обратно в баг. Какую диаграмму для чего рисовать — в записи про нотации BPMN, UML, C4.
ADR-001: PostgreSQL, а не Mongo — готовый ответ
Контекст: ядро MeetRoom — защита от двойного бронирования слота. Решение: хранилище — PostgreSQL. Почему: создание брони — это атомарная проверка-и-вставка против конфликта слота: «никто не занял этот промежуток — и тут же занимаю его сам». В реляционной БД это даётся ограничением из коробки (UNIQUE на пару room_id + слот, а для пересекающихся интервалов — EXCLUDE USING gist): два параллельных запроса на один слот — один проходит, второй получает отказ на уровне БД, без гонки. Документная БД (Mongo) гарантирует атомарность в пределах одного документа, но «нет ли пересечения с другими бронями» — это проверка через несколько документов, и её пришлось бы городить вручную: либо распределённой транзакцией, либо optimistic-lock с ретраями. Для MVP — лишняя сложность ради записи, которую реляционка делает декларативно одной строкой DDL. Цена: если в будущем брони станут schema-less (произвольные поля под разные типы комнат), за гибкость придётся доплатить миграциями — но на MVP этого требования нет.
Шаг 5. Данные и жизненный цикл брони
Проектируем данные на трёх уровнях — от сущностей бизнеса до таблиц PostgreSQL: модель данных: три уровня, а конкретику по ключам, связям и ACID — в базы данных для аналитика (если бы MeetRoom строили на документной базе, моделировали бы иначе — под паттерн доступа, см. моделирование в NoSQL). На физическом уровне центральная таблица bookings в первом приближении такая:
| Поле | Тип | Назначение |
|---|---|---|
| id | uuid PK | идентификатор брони |
| room_id | uuid FK → rooms | какая комната |
| organizer_id | uuid FK → users | кто забронировал (на нём держится «вижу только свои») |
| time_range | tstzrange | промежуток брони; на пару (room_id, time_range) висит ограничение от пересечений |
| status | enum | draft / confirmed / cancelled |
Отдельно описываем, как живёт сама бронь. Три статуса и разрешённые переходы: черновик (draft) → подтверждена (confirmed) → отменена (cancelled). Что разрешено, а что нет: из draft можно в confirmed или сразу в cancelled; из confirmed — только в cancelled; из cancelled — никуда (терминальное состояние). И отдельно запрещаем отменять бронь, время которой уже прошло. Это диаграммы состояний — и именно запрещённые переходы (вернуть отменённую бронь в активную, отменить прошедшую) ловят класс багов, который иначе всплывёт в проде.
Шаг 6. Контракт: API, ошибки, доступ
Чтобы веб-приложение и внешние системы общались с MeetRoom, задаём REST API: GET /rooms, POST /bookings, DELETE /bookings/{id}. Ключевой эндпойнт целиком, чтобы было что унести:
POST /bookings { "room_id": "...", "start": "2026-06-01T10:00:00Z", "end": "2026-06-01T11:00:00Z" }
201 Created — бронь создана, в теле id и status: "confirmed"
409 Conflict — слот уже занят (сработало ограничение из ADR-001)
422 Unprocessable — участников больше вместимости комнаты
Счастливый путь — это половина контракта; вторая половина — что вернётся при ошибке: 409 на занятый слот, 422 на превышение вместимости. Обратите внимание: 409 — это не баг, а штатный ответ, который фронт обязан показать пользователю человеческим текстом «слот заняли, пока вы выбирали». Это ошибки как часть контракта. Кто вошёл — решает аутентификация через OAuth2 (корпоративный SSO), а что кому можно — авторизация на уровне данных: NFR «сотрудник видит только свои брони» — это не фильтр в интерфейсе, а проверка на сервере, что строка принадлежит запрашивающему. Что из данных брони считать чувствительным (с кем встреча) — в записи про безопасность данных и PII.
Шаг 7. Интеграции: календарь по событию
MeetRoom не живёт один: создал бронь — событие должно улететь в корпоративный календарь. Делать это синхронно или асинхронно — развилка из записи синхрон, асинхрон, очереди; для уведомления календаря берём асинхронный путь — исходящий вебхук booking.created. Сам конверт события — тоже артефакт, который аналитик описывает в контракте:
POST {calendar_webhook_url}
{ "event_id": "evt_8f2a", "type": "booking.created",
"booking_id": "b_1042", "room_id": "r_07",
"start": "2026-06-01T10:00:00Z", "end": "2026-06-01T11:00:00Z" }
Поле event_id здесь не для красоты — это ключ идемпотентности: по нему календарь отличит повторную доставку от новой брони.
Сам сценарий «бэкенд создаёт бронь → шлёт событие календарю → тот подтверждает» удобнее всего нарисовать sequence-диаграммой — кто кого зовёт во времени. А поскольку событие может прийти дважды, обработчик на стороне календаря должен быть идемпотентным — про это идемпотентность (пример там на платеже, но для события booking.created механика ключа работает один в один).
flowchart TD A["Бизнес-боль:
хаос с переговорками"] --> B["Выявление
+ стейкхолдеры"] B --> C["SRS:
что строим"] C --> D["HLD/LLD + ADR:
как строим"] D --> E["Данные +
состояния брони"] E --> F["API + ошибки
+ авторизация"] F --> G["Интеграции:
календарь по вебхуку"] G --> H["Миграции +
эксплуатация"] H --> I["Метрики:
прижилось ли?"]
Схема показывает весь маршрут MeetRoom сверху вниз. Из бизнес-боли (хаос с переговорками) рождается выявление требований и карта стейкхолдеров; из них — SRS (что строим); из SRS — дизайн HLD/LLD с журналом решений ADR (как строим); дальше детализируются данные и жизненный цикл брони; затем — контракт API с ошибками и авторизацией; потом — интеграции с внешним календарём через вебхук; потом — миграции схемы и эксплуатация в проде; и в конце — метрики, которые отвечают, прижился ли сервис. Поток не строго водопадный: на практике он итеративный, и нижний шаг часто вскрывает дыру в верхнем (при проектировании API выясняется, что в SRS забыли requirement про отмену). Но порядок навыков именно такой — каждый следующий опирается на предыдущий. Тонкость: оглавление справочника учит темы в порядке «API → данные» (контракт проще для входа), а в проекте модель данных проектируют до контракта API — поэтому в маршруте шаг с данными идёт раньше. Это не противоречие: порядок обучения и порядок проектирования различаются намеренно.
Шаг 8. Эволюция и эксплуатация
MeetRoom выкатили — это не конец, а начало. Бизнес попросил хранить отдельно тему встречи и заметку вместо одного поля description — меняем схему работающей базы без даунтайма. Артефакт миграции — последовательность, а не один ALTER: (1) добавить нулёвые колонки title и note, (2) бэкфилл — старое description переложить в title пачками по 1000 строк, (3) переключить запись приложения на новые поля, (4) только потом удалить старую колонку. Каждый шаг обратим, на каждом сервис жив. Про это — миграции данных и бэкфилл. Сервис доезжает до пользователей через несколько окружений — CI/CD, крутится в контейнерах (Docker и K8s), быстро отдаёт сетку доступности за счёт кэширования. Чтобы понимать, что он жив и где тормозит, закладываем логи, метрики, трейсы; обещание доступности из SRS превращается в SLA/SLO, а один интегратор не должен уронить сервис всем — ставим rate limiting.
Время и часовые пояса — отдельный риск бронирования
MeetRoom — это сервис про слоты времени, и время здесь главный источник коварных багов. Правила, которые надо проговорить ещё в SRS, а не ловить в проде:
Хранить в UTC. В БД (поле time_range) и в API — всегда UTC с явным Z на конце: 2026-06-01T10:00:00Z. Никаких «локальных» времён в хранилище — иначе одну и ту же бронь два сервера в разных зонах поймут по-разному.
Показывать в зоне пользователя. Конвертация UTC → местное время — задача клиента (или слоя представления), на основе зоны браузера или профиля. Бэкенд не должен решать, в каком поясе рисовать сетку: офис в Москве и удалёнщик во Владивостоке видят один слот в своём времени, но это одна и та же запись в UTC.
Граница суток. «Сетка на сегодня» — это всегда «сегодня в зоне пользователя», а не в UTC. Иначе для Владивостока сутки в UTC закончатся в середине его рабочего дня, и часть утренних слотов уедет «на завтра». Границу суток считаем в локальной зоне, фильтруем по UTC.
Переход на летнее время. В зонах с DST (например, часть Европы) дважды в год сутки длятся 23 или 25 часов: одно локальное время может не существовать или встретиться дважды. Хранение в UTC снимает почти всю боль — UTC не прыгает; но на показе и при «повторить бронь на следующую неделю» проверяйте, что 14:00 по-прежнему 14:00 для пользователя, а не сдвинулось на час. Россия с 2014 года DST не применяет, но как только MeetRoom выйдет за её пределы — этот класс багов оживёт.
Шаг 9. Прижилось ли: метрики
Последний и часто забытый шаг: фичу выкатили — а она работает? Без цифр это вопрос веры. Для MeetRoom главная метрика — доля встреч, забронированных через сервис, а не «по памяти»; ставим цель в SLA-стиле: довести до 70% всех бронирований за два месяца (а через месяц мерим, идём ли к ней). Смотрим воронку и где отваливаются: открыл сетку (100%) → выбрал слот (60%) → подтвердил (45%) — если самый большой провал между «открыл» и «выбрал», значит больно не подтверждение, а поиск свободного слота: возможно, сетка грузится дольше тех самых 800 мс из NFR-02, и это уже гипотеза для A/B-теста. Всё это — в записи метрики, воронки, A/B. И когда копится словарь незнакомых терминов — держим открытым глоссарий.
Зачем смотреть на проект целиком
Каждый навык по отдельности — это инструмент в ящике. Но ценность аналитика не в том, что он знает, что такое SRS или sequence-диаграмма, а в том, что он умеет провести систему от размытой боли до работающего и измеримого продукта, не уронив ни один стык. Этот сквозной взгляд — то, что отличает человека, который «прошёл курс», от того, кто «сделал проект». Учите навыки по записям, но держите в голове весь маршрут MeetRoom: он показывает, как куски собираются в целое.
Как это спрашивают на собесе
Любимый формат сильного собеседования — не «что такое X», а «проведите меня по вашему проекту». Кандидата просят: «расскажите, как вы вели какую-нибудь систему от требований до прода» или «вот задача — спроектируйте сервис бронирования, рассуждайте вслух». Что проверяют: видите ли вы весь маршрут (а не только любимый кусок), не пропускаете ли выявление и метрики, помните ли про стыки — авторизацию, ошибки, идемпотентность, миграции. Слабый кандидат прыгает сразу в таблицы БД; сильный начинает с «а какую проблему решаем и кто стейкхолдеры» и доводит до «как поймём, что сервис прижился». Умение рассказать связный сквозной путь ценится выше, чем знание любого отдельного термина.
Частые вопросы
Это обязательный порядок шагов или можно иначе?
Порядок навыков — да, именно такой: каждый следующий шаг опирается на предыдущий (нельзя писать SRS, не выявив требования; нельзя проектировать API, не зная модель данных). Но сам процесс не строго водопадный, а итеративный: на практике вы постоянно возвращаетесь назад, потому что нижний уровень вскрывает дыру в верхнем — проектируя LLD, обнаруживаете, что в SRS забыли требование. Маршрут MeetRoom показывает логическую зависимость навыков, а не запрет ходить кругами.
Зачем нужен сквозной пример, если есть отдельные записи по каждой теме?
Отдельные записи учат навыкам — что такое SRS, как нарисовать sequence, чем RBAC отличается от ABAC. Но реальная работа аналитика — это не применение одного навыка, а проведение системы через все стыки так, чтобы ни один не рассыпался. Сквозной пример показывает, как один артефакт перетекает в другой (выявленное требование → строка SRS → блок HLD → таблица LLD → endpoint API) и почему порядок именно такой. Это превращает набор полочек в связный маршрут — то, что спрашивают на собесе и делают на проекте.
С чего начать, если я только учусь?
Идите по оглавлению справочника сверху вниз — он выстроен от фундамента к надстройке: контекст и роли → основы → требования → документы → процесс и продукт → API → интеграции → данные → эксплуатация → инструменты. А эту запись держите как карту: пройдя очередную тему, возвращайтесь сюда и смотрите, какое место навык занимает в маршруте MeetRoom. Так отдельные знания сразу укладываются в общую картину, а не повисают в воздухе.