Инженерия ПО
Требования и спецификации
Knight Capital, 2012: ошибка в требованиях к одному флагу - 440 миллионов долларов потеряно за 45 минут. Healthcare.gov, 2013: 1.7 миллиарда потрачено, сайт не работал в день запуска. Исправить ошибку в требованиях стоит 1x. В коде - 10x. После релиза - 100x. Требования - самый дешёвый и самый игнорируемый этап.
- **Здравоохранение**: Healthcare.gov (2013) - портал за 1.7 миллиарда не работал в день запуска из-за хаотичных требований от 55 подрядчиков
- **E-commerce**: Amazon описывает каждую фичу как пресс-релиз **до** разработки - это заставляет формулировать ценность заранее
- **Банки**: Ошибка в требованиях к округлению привела к потере 500 миллионов долларов в Knight Capital за 45 минут торгов
От PERT к Agile: 60 лет требований
1957 год: US Navy и Lockheed создают метод PERT для управления программой Polaris - первая формализованная система требований для сложного проекта. 1968 год: НАТО Software Engineering Conference - рождение термина software crisis. Проекты срываются именно из-за неясных требований. 1986 год: Том ДеМарко публикует "Structured Analysis" - первая методология для фиксации требований через диаграммы. 2001 год: Agile Manifesto - «Реакция на изменения важнее следования плану». Полвека споров о требованиях привели к одному выводу: требования меняются всегда, процесс должен это принимать.
Предварительные знания
Функциональные требования
Knight Capital, 2012. За 45 минут торгов алгоритмическая система потеряла 440 миллионов долларов. Причина - ошибка в требованиях к обработке флага, который был переиспользован с другим значением после рефакторинга. Никто не зафиксировал изменение семантики. **Функциональные требования** описывают поведение системы: что принимается на вход, что обрабатывается, что выдаётся на выход.
**Функциональные требования** описывают **поведение** системы: что она принимает на вход, что обрабатывает и что выдаёт на выход. Это ответ на вопрос «ЧТО система делает?»
Классический инструмент описания - **Use Case** (вариант использования). Описывает взаимодействие актора (пользователя, внешней системы) с системой для достижения цели.
Шаблон функционального требования: **Actor -> Action -> Result**. Каждое требование должно быть **конкретным**, **проверяемым** и **однозначным**.
| Плохое требование | Почему плохое | Хорошее требование |
|---|---|---|
| Система должна быть быстрой | Неизмеримо. Быстрая - это как? | Страница загружается за < 2 секунды |
| Пользователь может управлять товарами | Что значит «управлять»? | Пользователь может добавить, редактировать и удалить товар |
| Система надёжная | Неконкретно | Система доступна 99.9% времени (< 8.76 часов даунтайма/год) |
| Удобный интерфейс | Субъективно | Регистрация занимает не более 3 шагов |
**Правило 1:10:100**: исправить ошибку в требованиях стоит **1x**. На этапе разработки - **10x**. После релиза - **100x**. Час, потраченный на уточнение требований, экономит недели отладки.
Вопрос для проверки: «Как проверить, что это требование выполнено?» Если ответа нет - требование нужно переформулировать.
Какое из требований сформулировано правильно?
Нефункциональные требования
Healthcare.gov, 2013. Портал за 1.7 миллиарда долларов не работал в день запуска - 55 подрядчиков, хаотичные требования, никто не проверил нагрузку. 250 000 одновременных пользователей против проектировочного расчёта на 50 000. Это провал нефункциональных требований. Функциональные требования описывают **ЧТО** система делает. Нефункциональные - **КАК** она это делает.
Нефункциональные требования (NFR) часто называют **quality attributes** - атрибуты качества. Они определяют «-ilities»: scalability, reliability, availability, security, maintainability.
| Категория | Что измеряет | Пример требования | Как проверить |
|---|---|---|---|
| Performance | Скорость отклика | API отвечает за < 200ms (p95) | Load testing (k6, JMeter) |
| Scalability | Рост нагрузки | Система обрабатывает 10K RPS | Stress testing |
| Availability | Доступность | 99.9% uptime (< 8.76 ч/год) | Monitoring (Prometheus) |
| Security | Защита данных | Пароли хранятся в bcrypt, данные - TLS | Penetration testing |
| Reliability | Отказоустойчивость | Потеря 1 сервера не влияет на пользователей | Chaos engineering |
| Maintainability | Простота изменений | Новый разработчик продуктивен за 2 недели | Onboarding tracking |
**Компромиссы неизбежны.** Нельзя иметь максимальную производительность, безопасность, доступность и простоту одновременно. Шифрование данных увеличивает latency. Распределённая система повышает availability, но усложняет consistency (CAP-теорема).
NFR определяют **архитектуру**. Если требование - 100 RPS, хватит одного сервера. Если 100K RPS - нужна распределённая система, балансировщики, кэши. Изменить NFR после начала разработки часто означает **переписать всё с нуля**.
NFR всегда фиксировать **числами**. Не «быстро», а «< 200ms p95». Не «надёжно», а «99.9% availability». Числа можно проверить автоматически.
Команда строит систему с требованием 99.99% availability. Текущая архитектура - один сервер. Что нужно изменить?
User Stories
Amazon перед каждой крупной фичей пишет press release - как если бы продукт уже вышел. Это заставляет сформулировать ценность до написания кода. Схожая идея в Agile - **User Story**: лёгкий формат требования с точки зрения пользователя. Use Cases подробны и формальны - отлично для документации, но тяжелы для повседневной работы команды.
Формат User Story: **As a** [роль пользователя], **I want** [действие/возможность], **so that** [бизнес-ценность/причина]. Три компонента: КТО хочет, ЧТО хочет, ЗАЧЕМ хочет.
Хорошая user story соответствует критериям **INVEST**:
| Буква | Критерий | Что значит | Пример нарушения |
|---|---|---|---|
| I | Independent | Не зависит от других stories | "Сначала нужно сделать story #42" |
| N | Negotiable | Можно обсуждать детали | "Сделай ровно так, как написано" |
| V | Valuable | Приносит ценность пользователю | "Рефакторинг базы данных" |
| E | Estimable | Можно оценить в story points | "Интеграция с непонятным API" |
| S | Small | Помещается в спринт | "Построить всю систему оплаты" |
| T | Testable | Можно написать acceptance test | "Система должна быть удобной" |
User story - это **приглашение к разговору**, не исчерпывающая спецификация. Карточка в Jira - напоминание обсудить детали с командой.
Какая user story нарушает принцип INVEST?
Acceptance Criteria и Definition of Done
Разработчик говорит «готово». QA открывает тикет: «Нет обработки ошибок при отказе шлюза». PM добавляет: «А на staging задеплоено?» Три человека, три разных понимания слова «готово». User story описывает **ЧТО** нужно. Acceptance Criteria описывают **КОГДА** это считается готовым.
**Given-When-Then** (формат Gherkin) - стандартный способ записи acceptance criteria. Родом из BDD (Behavior-Driven Development). Читается как сценарий: при каких **условиях**, после какого **действия**, ожидается какой **результат**.
Gherkin-сценарии - это не просто документация. Инструменты вроде **Cucumber**, **Jest-Cucumber** или **SpecFlow** превращают их в **автоматические тесты**. Сценарий на человеческом языке = исполняемая спецификация.
**Definition of Done (DoD)** - общекомандное соглашение о том, когда task/story считается завершённой. Это чек-лист, применяемый к каждой задаче.
Без DoD каждый понимает «готово» по-своему. Разработчик: «Код написан». QA: «А тесты?» PM: «А на staging?» Результат - хаос и переоткрытые задачи.
Требования фиксируются в начале проекта и не должны меняться. Изменения требований - признак плохой подготовки.
Требования неизбежно меняются, потому что бизнес, рынок и понимание задачи эволюционируют. Agile принимает изменения - главное управлять scope.
Waterfall пытался зафиксировать требования - и 53% проектов выходили за бюджет вдвое (CHAOS Report). Agile признаёт: заказчик сам не знает, чего хочет, пока не увидит работающий прототип. Изменения неизбежны - инженерный процесс должен их поддерживать.
Что НЕ является преимуществом формата Given-When-Then?
Ключевые идеи
- **Функциональные требования**: ЧТО система делает. Actor -> Action -> Result. Конкретно, проверяемо, однозначно
- **Нефункциональные требования**: КАК система это делает. Performance, availability, security - числа, не прилагательные
- **User Stories**: As a / I want / so that. Лёгкий формат для Agile. INVEST-критерии для качественных stories
- **Acceptance Criteria**: Given-When-Then. Превращаются в автоматические тесты. Definition of Done - чек-лист готовности
- Knight Capital потерял 440 миллионов долларов из-за одной неверно задокументированной семантики флага - Given-When-Then сделал бы изменение явным
Куда дальше?
Требования описывают ЧТО строить. Архитектура определяет КАК это организовать:
- Архитектурные паттерны — Как структурировать систему, чтобы она выдержала изменения требований
- Что такое Software Engineering — Фундамент - зачем нужны требования в инженерном процессе
Вопросы для размышления
- Вспомните случай, когда команда «построила не то». Какой тип требований был упущен?
- Какие нефункциональные требования критичны для текущего проекта? Они записаны числами?
- Попробуйте описать одну фичу проекта в формате Given-When-Then. Стало ли понимание яснее?
Связанные уроки
- se-01 — Основы Software Engineering задают контекст инженерного процесса
- se-03 — Архитектурные паттерны определяют КАК строить систему по требованиям
- se-07 — Agile и Scrum - процессы управления требованиями в итерациях
- se-10 — Domain-Driven Design - моделирование домена через ubiquitous language
- devops-14 — Definition of Done и pipeline-as-code связывают требования с деплоем
- se-05 — Тестирование: acceptance criteria становятся автоматическими тестами
- sd-02-requirements