Skip to content

Написание качественных спецификаций

Вы редко пишете спецификацию с чистого листа. Вы описываете изменение простым языком, команда /opsx:propose составляет черновик требований и сценариев, а потом вы доводите их до ума. Эта страница посвящена последнему этапу — что такое «хорошая» спецификация и как подтолкнуть ИИ к её созданию.

Это дополнение к странице Проверка изменений: при проверке вы ищете слабые места в черновике, а при написании вы знаете, из чего состоит сильная спецификация.

Спецификация описывает поведение, а не код

Спецификация описывает, что делает ваша система, в терминах, которые может проверить любой человек — а не то, как она построена. Она состоит из требований (утверждений о поведении) и сценариев (конкретных примеров, подтверждающих их выполнение).

markdown
### Requirement: Session Timeout
The system SHALL expire a session after 30 minutes of inactivity.

#### Scenario: Idle timeout
- GIVEN an authenticated session
- WHEN 30 minutes pass with no activity
- THEN the session is invalidated and the user must re-authenticate

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

Из чего состоит хорошее требование

Хорошее требование описывает одно поведение, изложенное настолько просто, что вы можете передать его другому человеку для проверки.

  • Одно утверждение, один SHALL/MUST. Если в требовании есть три пункта с «а также», то на самом деле это три отдельных требования. Разделите их.

  • Проверяемое на практике. Человек, не работающий с кодом, должен иметь возможность определить, выполняется ли оно. Требование «Система SHALL показывать баннер с ошибкой, если размер загрузки превышает 10 МБ» является проверяемым. А «Система SHALL корректно обрабатывать большие загрузки» — нет.

  • Подходящая степень обязательности. OpenSpec использует ключевые слова из RFC 2119, и они имеют разное значение:

    Ключевое словоЗначение
    MUST / SHALLЖёсткое обязательство. Не подлежит обсуждению.
    SHOULDСильная рекомендация, с возможностью обоснованного исключения.
    MAYДействительно необязательно.

    По умолчанию используйте MUST/SHALL. Применяйте SHOULD только если вы действительно имеете в виду «если нет веской причины не делать этого».

Проверка требования: сможет ли тестировщик, который никогда не видел код, определить, выполнено ли оно? Если нет — требование нужно доработать.

Из чего состоит хороший сценарий

Сценарии — это то, ради чего требования и существуют. Каждый из них представляет собой конкретную последовательность GIVEN / WHEN / THEN, которую можно превратить в автоматизированный тест.

  • Он проверяет соответствующее требование. Сценарий, который просто перефразирует требование другими словами, ничего не проверяет. Сделайте его описанием конкретной ситуации с конкретным результатом.
  • Охватывайте важные случаи, а не только счастливый путь. Успешный вход в систему прост. Пустой ввод, истёкший токен, повторный клик, ситуация, в которой что-то пошло не так — именно в таких местах живут ошибки, и именно такие сценарии имеют наибольшую ценность.
  • Назовите случай в заголовке. «Scenario: Отклоняет истёкший токен» сразу говорит рецензенту, что проверяется; а «Scenario: Тест 2» — нет.

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

Выбирайте правильный тип дельты

Изменение описывает правки в спецификациях с помощью трёх типов разделов. Использование правильного типа позволяет сохранять достоверность архивированных спецификаций:

  • ## ADDED Requirements — совершенно новое поведение, которого раньше не существовало.
  • ## MODIFIED Requirements — поведение, которое уже существовало и изменяется. Укажите полную новую версию; краткое примечание о том, что изменилось, поможет рецензенту.
  • ## REMOVED Requirements — поведение, которое удаляется, с указанием причины.

При архивации раздел ADDED добавляется в конец основной спецификации, MODIFIED заменяет старую версию, а REMOVED удаляется. Если вы пометите реальное изменение как ADDED, у вас получится два противоречащих друг другу требования; если опишете новое поведение как MODIFIED, не будет ничего, что можно было бы заменить. Если сомневаетесь, откройте текущую спецификацию и проверьте, есть ли в ней уже это требование.

Подбирайте правильный размер изменения

Самая распространённая ошибка при написании — не плохо сформулированное требование, а изменение, которое пытается быть сразу тремя разными изменениями.

Хорошее изменение имеет одну цель, которую можно сформулировать в одном предложении. «Добавить переключатель тёмной темы». «Ограничить частоту запросов к конечной точке входа в систему». «Перенести сессии из куки». Если для описания изменения нужно много раз использовать «а также», это сигнал, что его нужно разделить.

Признаки того, что изменение слишком большое:

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

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

Бывает и обратное: исправление опечатки в одной строке не требует трёх требований и документа проектирования. Соотносите формальность процесса с важностью задачи.

Как подтолкнуть ИИ к созданию качественного черновика

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

  • Сформулируйте цель и границы. «Добавить переключатель тёмной темы, который при первой загрузке использует настройки операционной системы — не трогать существующий API тем.» Часть, описывающая, что не входит в область изменений, важна не меньше, чем часть с описанием целевой функциональности.
  • Назовите случаи, которые вас интересуют. «Убедитесь, что есть сценарий для пользователя, который уже вручную выбрал тему.» ИИ покрывает только то, на что вы ему укажете.
  • Затем отредактируйте результат. Это обычный Markdown. Уточните расплывчатое SHALL, удалите сценарий, который ничего не проверяет, добавьте случай, который ИИ пропустил — или попросите ИИ сделать это: «требование о таймауте слишком расплывчатое, зафиксируйте его значение в 30 минут.»

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

Краткий чек-лист

  • [ ] Каждое требование описывает одно проверяемое поведение и содержит SHALL/MUST.
  • [ ] В требованиях не встроены детали реализации.
  • [ ] Для каждого требования есть хотя бы один сценарий, который его реально проверяет.
  • [ ] Для важных пограничных случаев и сценариев ошибок есть соответствующие сценарии, а не только сценарии счастливого пути.
  • [ ] В дельтах правильно используются теги ADDED / MODIFIED / REMOVED относительно текущей спецификации.
  • [ ] Всё изменение имеет одну цель, которую можно сформулировать в одном предложении.

Дальнейшие шаги

  • Проверка изменений — быстрая проверка за две минуты, которая ловит то, что было пропущено.
  • Концепции — более подробная модель, лежащая в основе спецификаций, изменений и дельт.
  • Примеры и рецепты — реальные изменения от начала до конца.