Рубрика бэк ту скул: почему мы всегда писали спецификации и что изменилось, когда их начала читать машина?
Когда говорят о spec-driven development, часто можно услышать такую историю:
Spec-driven development: новая практика, придуманная под ИИ. До появления кодовых агентов никто не писал спецификацию первой, все писали код.
Звучит логично, но исторически это не совсем так.
Писать спецификацию первой: одна из самых старых идей в индустрии, и её переоткрывают примерно раз в десятилетие. Проваливалось никогда не само письмо. Проваливалось то, что единственным читателем спецификации был человек, не обязанный замечать, что документ перестал быть правдой.
Вот эта часть и изменилась.
Статья, которую все считают истоком waterfall
В 1970 году Уинстон Ройс опубликовал небольшую работу об управлении разработкой больших программных систем. Её помнят как исток водопадной модели, и это досадно: слова waterfall в тексте нет вообще.
Зато в тексте есть та самая последовательная диаграмма, которую все воспроизводят, и сразу за ней собственный вердикт Ройса: сама концепция ему нравится, но такая её реализация рискованна и напрашивается на провал.
А ещё там есть вот это, про раннюю фазу проекта:
На ранней фазе разработки документация и есть спецификация, и есть дизайн.
Не «описывает» дизайн. Является дизайном. Тезис о том, что спецификация является первичным артефактом, придуман не в 2025 году. Это едва ли не старейший тезис в профессии, и лежит он в той самой статье, которую цитируют, когда хотят посмеяться над привычкой записывать.
Жизненный цикл, выросший из неё, узнает любой инженер:
SOFTWARE DEVELOPMENT LIFECYCLE "SDLC"
┌──────────────────────────────┐
PRD ───►│ PLANNING & DESIGN │
└───────────────┬──────────────┘
│
╭╌╌ cycle ╌╌╌╌╌╌╌╌╌╌╌╌╌│╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮
╎ ▼ ╎
╎ ┌──────────────────────────────┐ ╎
╎ ┌─►│ IMPLEMENT │ ╎
╎ │ └───────────────┬──────────────┘ ╎
╎ │ │ ╎
╎ │ ▼ ╎
╎ │ ┌──────────────────────────────┐ ╎
╎ │ │ TESTING / QA │ ╎
╎ │ └───────────────┬──────────────┘ ╎
╎ └──────────────────┤ tests fail ╎
╰╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌│╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯
▼
┌──────────────────────────────┐
│ DEPLOYMENT │
│ dev → staging → production │
└───────────────┬──────────────┘
│
▼
┌──────────────────────────────┐
│ MAINTENANCE │
└──────────────────────────────┘
Почему документ всегда проигрывал
Если идея была верна ещё в 1970-м, возникает очевидный вопрос: почему документы получались настолько плохими.
Честный ответ дали Дэвид Парнас и Пол Клементс в 1986 году, в работе с говорящим названием A Rational Design Process: How and Why to Fake It. Аргумент ровно такой, как в заголовке. Рационального процесса проектирования вы не выдержите никогда: информация приходит не в том порядке, а на середине пути вы меняете решение. Что вы можете, так это выпустить постфактум ту документацию, которую выпустили бы, если бы выдержали.
Парнас же задал критерий приёмки для документа требований, и он строже, чем принято думать:
всё, что нужно знать, чтобы написать программу, устраивающую заказчика, и ничего сверх того
Организованное как справочник, а не как текст для чтения от корки до корки.
Обратите внимание, чего здесь нет: механизма. Ничто не проверяло, что документ всё ещё соответствует программе. Спецификация и реализация могли расходиться годами, и замечал это один-единственный новичок, однажды и болезненно.
Как спецификацию пытались сделать принудительной
Дальше появились два семейства решений, и разошлись они в противоположные стороны.
Первое занесло спецификацию внутрь программы. Design by Contract Бертрана Мейера, опубликованный в 1992 году, описывает предусловия и постусловия процедуры как контракт между вызывающим и поставщиком, причём вина распределяется механически: нарушено предусловие, значит, виноват вызывающий. Мейер прямо возражал против документации как отдельного продукта, который сопровождают отдельно от кода.
Второе сделало точной саму прозу. RFC 2119 в 1997 году зафиксировал значения MUST, SHOULD и MAY так, чтобы два независимых разработчика прочитали протокол одинаково, и тут же, в собственном заключительном разделе, предупредил, что пользоваться этими словами следует осторожно и экономно. Двадцать лет спустя RFC 8174 пришлось сузить правило ещё раз: слова нормативны, только если написаны заглавными.
Оба решения работают. Ни одно не сделало спецификацию исполняемой целиком. Контракт покрывает интерфейс, а не замысел. Нормативное слово делает однозначным предложение, а не систему.
Сначала тест, потом поведение
Следующей попыткой было заставить спецификацию исполняться.
Test-driven development Кента Бека обычно пересказывают как «сначала тест, потом код». Его собственное каноническое описание начинается на шаг раньше: с записанного списка сценариев, которым должно удовлетворять изменение, ещё до того, как появился хоть один тест. Спецификация предшествует тесту, а не только коду.
Дэн Норт переименовал словарь в 2006 году по конкретной причине: слово тест и было тем, что мешало людям понять практику. Стоило назвать это поведением, и те же вопросы начали отвечать на себя сами. Гойко Аджич позже упаковал коллаборативную версию как Specification by Example, целясь в документацию, которая остаётся живой, потому что исполняется.
Каждый шаг сдвигает первичный артефакт на позицию выше по течению:
step TRAD TDD SDD
╔════════════╗ ┌────────────┐ ┌────────────┐
1st ║ CODE ║ │ TEST │ │ SPEC │
╚═════╤══════╝ └─────┬──────┘ └─────┬──────┘
▼ ▼ ▼
┌────────────┐ ╔════════════╗ ┌────────────┐
2nd │ DOCS │ ║ CODE ║ │ DESIGN / │
└────────────┘ ╚════════════╝ │REQUIREMENTS│
└─────┬──────┘
▼
┌────────────┐
3rd │ IMPLEMENT │
└─────┬──────┘
▼
╔════════════╗
4th ║ CODE ║
╚════════════╝
╔══╗ = CODE: первый в TRAD, второй в TDD, ПОСЛЕДНИЙ в SDD.
Но тест остаётся примером, а не правилом. Он говорит, что произойдёт на этих входных данных. Он не может запретить дизайн, которого ещё не существует, и не хранит в себе ответа, почему ожидаемое значение именно такое.
Пресс-релиз вперёд продукта
У той же идеи есть нетехническая ветка. Практика working backwards в Amazon, публично описанная Вернером Фогельсом в 2006 году, требует написать пресс-релиз и FAQ до того, как продукт появится.
Это спецификация, которую читает человек, принимающий решение, а не компилятор. Её задача не породить что-либо, а сделать отказ от плохой идеи дешёвым: на бумаге, до того как кто-то начал строить.
Запомните этот механизм: именно на нём и держится сегодняшний инструментарий.
Промпт как спецификация, которую выбрасывают
Теперь современная часть.
Vibe coding, то есть разговор с моделью до тех пор, пока результат не начнёт выглядеть правильно, по-настоящему хороший способ работать. Он быстрый, приятный, и для одноразового скрипта или разведочного изменения его трудно чем-то перебить.
VIBE CODING
───────────
┌─────────────────────────────────┐
│ User w/ prompt │
└────────────────┬────────────────┘
│
▼
┌─────────────────────────────────┐
│ AI generates code │
└────────────────┬────────────────┘
│
▼
┌─────────────────────────────────┐
┌───▶│ EDIT PROMPT │ ?
│ └────────────────┬────────────────┘
│ │ regenerate
│ ▼
│ ┌─────────────────────────────────┐
│ │ AI CODE │ ?
│ └───┬────────────┬────────────────┘
│ │ │
└────────┘ not right │ looks right
▼
┌─────────────────────────────────┐
│ Desired State │
└─────────────────────────────────┘
? непонятно, почему модель решила именно так
? непонятно, сколько витков займёт цикл
Но посмотрите, что этот цикл сохраняет, а что выбрасывает. Код коммитится. Промпт, который его породил, не коммитится. Рассуждение тоже. Прогоните один и тот же промпт сто раз и получите сто защитимых программ, без всякой записи о том, какое ограничение заставило модель остановиться именно на этой. Замысел до репозитория не доезжает.
Читатель сменился
Spec-driven development возвращает стадии ревью на место и ставит их до того, как что-либо построено.
SPEC CODING
───────────
┌────────────────────────────────┐
│ Prompt Spec │
└────────────────┬───────────────┘
│
▼
┌────────────────────────────────┐
│ Requirements │◀────┐
└────────────────┬───────────────┘ │
│ │
happy? ───┴─── no ──▶ EDIT ─────┘
│
yes
▼
┌────────────────────────────────┐
│ Design │◀────┐
└────────────────┬───────────────┘ │
│ │
happy? ───┴─── no ──▶ EDIT ─────┘
│
yes
▼
┌────────────────────────────────┐
│ Implement │
└────────────────────────────────┘
code · tests · docs
Промпт описывает поведение и ограничения, а не реализацию. Из него получается документ требований, который ревьюят и либо утверждают, либо правят. Утверждённые требования становятся дизайном, который проходит ту же процедуру. И только потом агент пишет код.
Это механизм Amazon (отказаться дёшево, на бумаге), применённый к генератору вместо продуктового комитета. Ворота посильны ровно потому, что ещё ничего не построено.
И вот в чём настоящая новизна, и она не в том, что мы начали писать спецификации.
Пятьдесят лет единственным читателем спецификации был коллега, который мог тихо её проигнорировать. Теперь читатель заново порождает из неё код.
Устаревание перестаёт быть проблемой документации и становится проблемой сборки. Впервые за всю историю практики держать документ правдивым стало кому-то непосредственно выгодно.
Сколько спецификация стоит
Это самый сильный довод «за». Честный разбор обязан включать и счёт.
Spec-driven development не убирает неоднозначность. Он её переносит. Неоднозначность в коде находима: машина его исполняет и сообщает вам. Неоднозначность в прозе находит только внимательный читатель, а спецификация, достаточно точная, чтобы неоднозначности не осталось, становится программой, написанная на наименее пригодном для этого языке.
Мартин Фаулер прошёл этот путь ещё в 2003 году под другим именем, UML as programming language, и пришёл к выводу, что подъём уровня абстракции не освобождает от работы программирования.
Ещё три статьи расходов, и ни одна не гипотетическая:
- ворота, которые нельзя исполнить: сорок страниц, сгенерированных за двадцать секунд и прочитанных один раз одним усталым человеком. Генерация подешевела до нуля, чтение не подешевело;
- гниение спецификации стало активным, а не пассивным. Устаревшую вики игнорируют. Устаревшую спецификацию скармливают агенту, и она инструктирует следующую генерацию;
- спецификация сама превращается в источник дефектов. Команда одного из ведущих инструментов публикует ровно это и обращается с неоднозначностью в требованиях как с классом багов, у которого есть собственный проход анализа.
И наконец: первичный артефакт
Если убрать инструментарий, останется простое утверждение о первичности. Первичный артефакт это файл, который вы правите, когда хотите изменить поведение; файл, о котором спорит ревьюер; файл, чью историю кто-то будет читать через год. Spec Kit от GitHub формулирует амбицию без обиняков: спецификация является первичным артефактом, а код лишь её выражением.
На практике это выглядит скромнее риторики:
┌────────────────────────────────┬────────────────────────────────┐
│ VIBE CODING │ SPEC CODING │
├────────────────────────────────┼────────────────────────────────┤
│ "need /login for users auth" │ Feature: User Auth │
│ │ ├─ Endpoint: /login POST │
│ одно предложение замысла │ ├─ Accepts: {user, pass} │
│ → ~30 законных реализаций │ ├─ Fails: 400 if missing user │
│ │ └─ Tests: valid creds → 200 │
├────────────────────────────────┼────────────────────────────────┤
│ ┌─→ AI generates code ──┐ │ spec ─┬─→ implementation │
│ │ │ │ ├─→ tests │
│ └──── edit the prompt ←─┘ │ └─→ docs │
│ │ │
│ цикл, пока не выглядит верно │ одно прочтение, не тридцать │
└────────────────────────────────┴────────────────────────────────┘
Где индустрия оказалась на самом деле, тоже стоит заметить. Форма из трёх документов (requirements, design, tasks) реальна, и к ней действительно сходятся; а EARS, нотация требований, которую взял один из популярных инструментов, придумана в Rolls-Royce в 2009 году и к ИИ отношения не имеет. При этом Thoughtworks по-прежнему держит spec-driven development в кольце Assess, отмечая, что определение не устоялось. Первая академическая попытка это определение дать, в 2026 году, начинается с признания: общего словаря пока нет. А формат, на котором экосистема действительно сошлась, это AGENTS.md, файл инструкций, а не спецификация.
Итог
Если сильно упростить историю развития идей, получается такая цепочка:
Документация как спецификация
↓
Гниение документации
↓
Имитация рационального процесса
↓
Design by Contract
↓
Нормативная проза
↓
Исполняемые примеры
↓
Утверждение до реализации
↓
Машина как второй реализатор
↓
Повторное порождение из текста
↓
Spec-Driven Development
Поэтому наиболее корректно рассказывать эту историю так:
Spec-driven development появился не потому, что инженеры заново открыли пользу записывать. Записывать рекомендовали всегда, и записанное всегда протухало, потому что единственный читатель мог себе позволить его игнорировать. Изменилось то, что у спецификации появился читатель, который строит из неё систему. А документ, который исполняют, это документ, который наконец кому-то выгодно держать правдивым. Переживёт ли эта выгода встречу с сорока страницами, которые никому не успеть прочитать, остаётся открытым вопросом.
Полезные ссылки
Winston W. Royce, Managing the Development of Large Software Systems (1970)
https://web.archive.org/web/2018id_/http://www-scf.usc.edu/~csci201/lectures/Lecture11/royce1970.pdfDavid L. Parnas and Paul C. Clements, A Rational Design Process: How and Why to Fake It (1986)
https://users.ece.utexas.edu/~perry/education/SE-Intro/fakeit.pdfBertrand Meyer, Applying "Design by Contract" (1992)
https://se.inf.ethz.ch/~meyer/publications/computer/contract.pdfScott Bradner, RFC 2119: Key Words for Use in RFCs to Indicate Requirement Levels
https://www.rfc-editor.org/rfc/rfc2119.txtKent Beck, Canon TDD
https://newsletter.kentbeck.com/p/canon-tddDan North, Introducing BDD
https://dannorth.net/blog/introducing-bdd/Werner Vogels, Working Backwards
https://www.allthingsdistributed.com/2006/11/working_backwards.htmlGojko Adzic, Specification by Example
https://gojko.net/books/specification-by-example/Martin Fowler, UmlAsProgrammingLanguage
https://martinfowler.com/bliki/UmlAsProgrammingLanguage.htmlGitHub, Spec Kit: the spec-driven development methodology
https://github.com/github/spec-kit/blob/main/spec-driven.mdAlistair Mavin, EARS: Easy Approach to Requirements Syntax
https://alistairmavin.com/ears/Thoughtworks Technology Radar, Spec-driven development
https://www.thoughtworks.com/radar/techniques/spec-driven-development