Когда я был джуном, все эти типы требований казались мне бюрократией. В вузе нас учили писать их по ГОСТам — после такого сложно поверить, что требования могут быть полезными. Всё изменилось, когда я начал работать с дизайнером: мы долго не могли найти общий подход, пока не поняли, что ему нужны расписанные use case'ы — без них он проектировал интерфейс вслепую. Так функциональные требования перестали быть для меня формальностью.

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

В каждом артефакте я стараюсь держать структуру минимальной. У Стива Круга в «Не заставляйте меня думать» есть мысль: если что-то является коротким, у него больше шансов быть использованным. Он говорил про интерфейсы, но к документации это применимо один в один.

Моя структура функционального требования:

Use Case

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

Каждое функциональное требование содержит ровно один use case. Я описываю, с чего начинает пользователь, к какой цели он идёт и чего достигает. Признак хорошего use case — его легко превратить в блок-схему или BPMN-диаграмму.

Разберу на реальном примере. На одном из проектов мы разрабатывали календарь курсов — страницу, где пользователь подбирает курс и записывается на него.

  1. Пользователь заходит на портал

    1. Цель — записаться на курс

  2. Переходит на страницу «Календарь курсов»

  3. Задаёт нужные фильтры

    1. ЕСЛИ подходящих курсов не нашлось — отображается пустой календарь

  4. Выбирает курс на подходящие даты

  5. Кликает на курс и попадает на его страницу

  6. Нажимает «Записаться»

  7. Заполняет заявку и отправляет

  8. Служба поддержки связывается с пользователем и принимает заявку

  9. Пользователь записан на курс

Я специально не стал раскрывать пункт «Описание» раньше — это выжимка use case'а в одно-два предложения. Нужно, чтобы быстро ориентироваться в документации, не вчитываясь в логику целиком. Для нашего примера:

Требование описывает логику записи на курс пользователем при использовании календаря курсов

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

Кажется, что при описании use case'а ты покрываешь все сценарии. Но в ходе тестирования мы увидели, что пользователь вместо яркой кнопки кликает на меню слева. Каждый такой сценарий — это новое функциональное требование.

Тест-кейсы из use case'ов

Я спросил тестировщика в команде, как он работает с функциональными требованиями. Ответ был простой: он берёт логику из use case'а и формирует из неё шаги и ожидаемый результат для тест-кейсов. Не только из ФТ — но ФТ помогает.

К нефункциональным требованиям он тоже обращается и старается проверять их по возможности.

Трассируемость

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

Я придерживаюсь двух правил:

Каждое функциональное требование должно покрывать один или несколько критериев приёмки. Каждый критерий приёмки может быть покрыт одним или несколькими функциональными требованиями

Требования к данным, системным интерфейсам и графическим интерфейсам должны быть связаны с функциональными требованиями. Но не наоборот — ФТ не обязано иметь связанные ТД, СИ или ГИ

Вернёмся к примеру с календарём курсов. Критерии приёмки могут выглядеть так:

Дано

Когда

Тогда

КП-1

Пользователь выбирает параметры в фильтрах

Есть подходящие курсы

Система отображает курсы

КП-2

Пользователь на странице Календаря курсов

Кликает на курс

Система отображает страницу курса

Оба критерия покрываются нашим функциональным требованием. Это не все КП, которые оно покрывает, но для примера достаточно. Уточнение: те же критерии могут покрываться и другими ФТ.

«Нижняя» трассировка важна для документации: по ней видно, что задачи действительно покрывают весь функционал. И наоборот — что не появилось лишних задач, не связанных с фичей.

Добавим в наш пример нижние требования. ФТ может быть связано сразу с тремя типами, а может — ни с одним:

  • [СИ-5] GET /courses — получение информации по доступным курсам и датам их проведения

  • [ГИ-3] Отображение курсов в календаре

  • [ТД-2] Добавление временных промежутков проведения курсов

  • [ТД-3] Миграция данных курсов

Когда у ФТ нет связанных требований? Например, когда нужно зафиксировать существующее поведение системы. В нашем кейсе страница со списком курсов уже существовала — календарь лишь новое представление. Старый список никуда не девается, мы добавляем вид, а не заменяем. Новых запросов, изменений данных и правок интерфейса не требуется — но ФТ на это всё равно нужно.

Отдельно в функциональном требовании я указываю связанные бизнес-правила. Подробно о них я писал в статье — здесь лишь отмечу, что они живут в пользовательском требовании, а в ФТ только ссылаются.

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

# [ФТ-XX] Название функционального требования
> **Пользовательское требование:** ПТ-XX
>
> **Критерии приёмки:** КП-X, КП-X

## Описание

Краткое описание сути требования в 1-2 предложениях.

### Логика

1. Шаг
2. Шаг
3. **Если** условие → результат
4. **Если** иное условие → результат

## Бизнес-правила

* БП-XX

## Связанные требования

### Требования к данным
* ТД-XX

### Требования к интерфейсам
* СИ-XX
* ГИ-XX
Как выглядит на практике

[ФТ-1] Запись на курс через календарь курсов

Пользовательское требование: ПТ-1

Критерии приёмки: КП-1, КП-2

Описание

Требование описывает логику записи на курс пользователем при использовании календаря курсов.

Логика

  1. Пользователь заходит на портал

    1. Цель — записаться на курс

  2. Переходит на страницу «Календарь курсов»

  3. Задаёт нужные фильтры

    1. Если подходящих курсов не нашлось — отображается пустой календарь

  4. Выбирает курс на подходящие даты

  5. Кликает на курс и попадает на его страницу

  6. Нажимает «Записаться»

  7. Заполняет заявку и отправляет

  8. Служба поддержки связывается с пользователем и принимает заявку

  9. Пользователь записан на курс

Бизнес-правила

Связанные требования

Требования к данным

Требования к интерфейсам

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

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

Поэтому я фиксирую только то, что критично для конкретной фичи. В случае с календарём курсов не так важна надёжность, как скорость загрузки и удобство: в один день может быть семьдесят и больше курсов — нужно отобразить все, не перегрузив интерфейс.

Структура НФТ у меня проще, чем у функционального требования.

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

# [НФТ-XX] Название нефункционального требования
> **Пользовательское требование:** ПТ-XX

## Категория

Категория НФТ (например: Производительность, Надёжность, Удобство использования)

### Метрика и целевые значения

* **Метрика:** Что измеряем
* **Целевое значение:** Конкретное значение или условие

## Обоснование

Почему это требование важно для фичи.
Как выглядит на практике

[НФТ-1] Календарь курсов должен оставаться читаемым при большом количестве курсов в один день

Пользовательское требование: ПТ-1

Категория

Удобство использования

Метрика и целевые значения

  • Метрика: Читаемость календаря при максимальной загрузке

  • Целевое значение: При отображении 70+ курсов в один день календарь остаётся читаемым и помещается максимум в 2 экрана

Обоснование

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

Итог

Структура документации — не статичная штука. Она развивается вместе с командой и её потребностями. Моя структура ФТ сейчас закрывает запросы тестировщика, дизайнера и разработчиков — но через полгода всё может измениться.

Для чего ваша команда использует функциональные требования? Являются ли они формальностью или действительно рабочим инструментом?