Skip to content

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

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

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

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

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

markdown
### Требование: Тайм-аут сессии
Система ДОЛЖНА завершать сессию после 30 минут бездействия.

#### Сценарий: Простой тайм-аут
- ДАНО аутентифицированная сессия
- КОГДА проходит 30 минут без активности
- ТО сессия становится недействительной, и пользователь должен пройти повторную аутентификацию

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

Что делает требование хорошим ​

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

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

  • Наблюдаемость. Кто-то вне команды разработки должен иметь возможность определить, выполняется ли оно. «Система ДОЛЖНА показывать баннер об ошибке, когда размер загрузки превышает 10 МБ» — это наблюдаемо. «Система ДОЛЖНА корректно обрабатывать большие загрузки» — нет.

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

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

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

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

Что делает сценарий хорошим ​

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

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

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

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

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

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

При архивации добавленные (ADDED) требования добавляются в основную спецификацию, измененные (MODIFIED) заменяют старую версию, а удаленные (REMOVED) исключаются из нее. Удалите последнее требование возможности (capability), и вы ее деактивируете: вместо того чтобы оставлять пустую спецификацию, архив удаляет файл openspec/specs/<capability>/spec.md. Поскольку это единственный шаг архивации, удаляющий файл, он должен выполняться явно — добавьте retire_capabilities: true в .openspec.yaml изменения, рядом с уже необходимым там полем schema:. Без этого архив прервется и сообщит вам об этом. Деактивация удаляет весь файл целиком, поэтому она также отклоняется, если спецификация содержит что-либо помимо заголовка, раздела ## Purpose и блоков требований — например, раздел ## Notes или комментарий под требованием. При прерывании указываются номера этих строк; переместите их в ## Purpose или в требование, либо удалите спецификацию вручную. Для спецификации в рабочей копии вызывающего проекта вывод архива также указывает команду git checkout, восстанавливающую зафиксированный файл; выбранные хранилища получают рекомендации по восстановлению, ограниченные областью проверки. Если вы пометите реальное изменение как ADDED, у вас получится два конкурирующих требования; если вы опишете новое поведение как MODIFIED, нечего будет заменять. Если сомневаетесь, откройте текущую спецификацию и посмотрите, есть ли там уже это требование.

Еще один раздел стоит знать. Когда ваша дельта создает возможность (capability), которой еще не существует, откройте её разделом ## Purpose — предложением или двумя о том, для чего нужна эта возможность. Архив использует его как цель создаваемой им основной спецификации; пропустите его, и вы получите заполняемый вручную плейсхолдер TBD. У существующей спецификации уже есть Цель, поэтому цель дельты там игнорируется — отредактируйте openspec/specs/<capability-path>/spec.md напрямую, чтобы изменить её. Здесь <capability-path> — это путь к директории относительно specs/, например user-auth в плоском проекте или identity/user-auth в проекте, организованном по доменам.

Правильно масштабируйте изменение ​

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

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

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

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

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

Происходит и обратное: исправление опечатки в одну строку не требует трех требований и документа дизайна. Соответствуйте церемонии уровню важности.

Как направить ИИ к хорошему черновику ​

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

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

Черновик, уточнение, повтор. Несколько таких циклов создают спецификацию, которой можно доверять, в чем и заключается вся суть.

Быстрый чек-лист ​

Куда двигаться дальше ​