Четыре подхода, которые не конкурируют
В прошлом уроке мы разобрали, что спека — источник истины, а код — артефакт сборки. Теперь закономерный вопрос: чем это отличается от TDD, где «тест — источник истины»? Или от BDD с его «требованиями на языке бизнеса»?
Если не разобраться с этим сразу, SDD будет казаться очередным переименованием старых идей. Это не так — давайте разложим по осям.
Три оси сравнения
Зафиксируем три вопроса, по которым подходы реально различаются:
1. Уровень: функция/класс или система в целом?
2. Кто исполняет: разработчик, команда или AI-агент?
3. Что фиксируем: тест, сценарий поведения или системное требование?
flowchart TD
subgraph ByDev["Исполняет: разработчик"]
TDD["TDD<br>Уровень: функция/класс<br>Фиксирует: тест-assert"]
BDD["BDD<br>Уровень: поведение фичи<br>Фиксирует: Given/When/Then"]
end
subgraph ByHuman["Читают: люди"]
DD["Design doc<br>Уровень: система<br>Фиксирует: архитектуру"]
end
subgraph ByAgent["Исполняет: AI-агент"]
SDD["SDD<br>Уровень: система/фича<br>Фиксирует: требование + критерии"]
end
SDD -->|"порождает"| TDD
SDD -. "включает идеи" .-> DDTDD: тугой цикл на уровне кода
TDD — дисциплина разработчика, а не агента. Цикл Red–Green–Refactor занимает минуты: написал тест для одной функции → убедился, что он падает → написал реализацию → тест проходит → подчистил.
Главное: TDD работает на уровне конкретного кода. «Тест» здесь — это буквальный вызов функции с проверкой результата:
def test_password_hashed():
result = hash_password("secret")
assert result != "secret"
assert len(result) > 20Никакого агента. Разработчик пишет тест, видит красный прогон, пишет реализацию. TDD — про внутреннюю дисциплину написания кода, а не про то, что строить на уровне системы.
BDD: поведение на языке бизнеса
BDD вырос из TDD — как попытка поднять разговор на уровень выше. Синтаксис Given/When/Then (Gherkin) читаем не только разработчикам, но и менеджерам:
Scenario: Регистрация с уникальным email
Given пользователь ещё не зарегистрирован
When он отправляет форму с email "user@example.com" и паролем "securePass1"
Then система создаёт учётную запись
And отправляет письмо с подтверждениемПо оси «уровень» BDD поднимается выше TDD — фича целиком, а не одна функция. Но по оси «кто исполняет» — всё ещё разработчик: он пишет step definitions, которые превращают Gherkin-шаги в вызовы кода. Cucumber или pytest-bdd прогоняют сценарий как тест в CI.
Адресаты BDD — разработчик и бизнес. Но это всё равно тест, который команда поддерживает вручную.
Design doc: документ для людей
Design doc описывает, почему выбрали Redis вместо Memcached, как устроены компоненты, какие компромиссы приняты. Его читают люди — и только люди.
Ключевое отличие: design doc не исполняется никаким инструментом. CI его не прогоняет. Он может устареть, и никто не заметит, пока не прочитает и не удивится расхождению с кодом. По оси «кто исполняет» design doc вообще вне игры.
SDD: требования для агента
SDD занимает другое место по всем трём осям:
- Уровень — системный: спека описывает поведение фичи целиком, включает NFR, ограничения, edge-кейсы.
- Кто исполняет — AI-агент. Спека — структурированный контекст, который агент читает и превращает в код.
- Что фиксируем — требование плюс acceptance criteria плюс архитектурные решения — всё в одном месте.
Разница с design doc: спека предназначена для исполнения. Разница с BDD: спека — не тест, она порождает тесты как один из артефактов.
SDD порождает TDD-тесты
Это, пожалуй, главное, что нужно понять: SDD и TDD не конкурируют — они встроены в цепочку.
Вернёмся к примеру из прошлого урока. Спека содержит:
### FR-01 Регистрация через email
WHEN пользователь отправляет форму с email и паролем
THE SYSTEM SHALL создать учётную запись и отправить письмо с подтверждением.
Acceptance criteria:
- [ ] Дублирующийся email возвращает ошибку 409
- [ ] Пароль не менее 8 символов
- [ ] Письмо отправляется в течение 30 секундКогда агент получает задачу «написать тесты», он берёт каждый пункт acceptance criteria и превращает его в конкретный тест:
def test_duplicate_email_returns_409():
create_user(email="user@example.com")
response = client.post("/auth/register", json={
"email": "user@example.com",
"password": "securePass1"
})
assert response.status_code == 409
def test_password_min_length_8():
response = client.post("/auth/register", json={
"email": "new@example.com",
"password": "short"
})
assert response.status_code == 422Агент не выдумывает edge-кейсы — он трассирует их из спеки. Это принципиальное отличие от vibe coding, где тесты пишутся «по мотивам кода». Здесь тест отражает намерение, зафиксированное до написания строчки реализации.
Сводная таблица
| TDD | BDD | Design doc | SDD | |
|---|---|---|---|---|
| Уровень | функция/класс | поведение фичи | система | система/фича |
| Адресат | разработчик | разработчик + бизнес | команда (читают) | AI-агент |
| Что фиксируем | assert | Given/When/Then | архитектурное решение | требование + критерии |
| Исполняется в CI | да | да | нет | да (агентом) |
| Порождает тесты | является тестом | является тестом | нет | да, как артефакт |
Итог
Когда говорят «SDD — это как TDD, только для агентов» — это неточно в обе стороны. TDD работает на уровне функции и предполагает человека за рулём. SDD работает на уровне системы и адресован агенту. Но они прекрасно сочетаются: SDD-спека порождает TDD-тесты как артефакт, BDD-сценарии могут войти в acceptance criteria, а design.md в Kiro — это эволюция design doc, предназначенная для чтения агентом, а не только людьми.
В следующем уроке разберём анатомию рабочей спеки изнутри: файлы Kiro, нотацию EARS и как выглядит спека, которая действительно помещается в голову.