Программа может строго следовать каждой вашей инструкции и при этом полностью сломаться, именно потому что все инструкции были выполнены безупречно.
Проблема логического тупика
Представьте CRM-систему для онлайн-школы. Вы даете Claude задачу: «Если ученик оплатил курс, открой ему доступ к урокам». Затем добавляете: «Если доступ открыт, проверь статус оплаты, чтобы убедиться в валидности». На первый взгляд, это логично. Однако в реальности система может попасть в бесконечную петлю: доступ не откроется, пока не подтверждена оплата, а оплата не считается завершенной, пока система не увидит открытый доступ для проверки. Это пример того, как отсутствие четкой декомпозиции системы на входе приводит к созданию архитектурного «узла», который ИИ не сможет распутать самостоятельно.
Основные концепции расплывчатой архитектуры
Когда мы работаем в парадигме Spec-First, мы переносим проектирование из головы в мета-файлы описания (Spec Files). Если эти файлы содержат размытые формулировки, возникают три фундаментальные проблемы:
- Циклические зависимости в логике: Это ситуация «курицы и яйца», где две сущности (Entities) или функции ждут действий друг от друга. В программной логике это приводит к зависанию или аварийному завершению работы.
- Амбивалентность инструкций: Когда фраза может быть истолкована двояко. Для человека «сделай красиво» — это эстетика, для ИИ это может означать «добавь 50 новых визуальных элементов», что перегрузит контекстное окно и создаст хаос.
- Галлюцинации структуры: Если ваша спецификация файловой структуры (File Tree) не строгая, ИИ начнет «придумывать» новые файлы для решения задач, нарушая изоляцию функционала. Вместо того чтобы править один файл, он создаст три дубликата в разных папках.
Это рождает архитектурный долг нетехнического разработчика. В отличие от программиста, который копит плохой код, вы копите плохую логику. Каждое нечеткое решение наслаивается на предыдущее, пока система не становится настолько хрупкой, что любое изменение в потоках данных обрушивает всё приложение.
Минимальный пример: Конфликт спецификаций
Рассмотрим фрагмент Spec-файла, который описывает логику CRM. Здесь допущена критическая ошибка в определении состояний.
Разбор примера
В этом коде мы видим, что payment_status зависит от access, а access зависит от payment_status.
- Почему это написано так? Разработчик хотел гарантировать, что оплата не будет считаться успешной, если пользователю по какой-то причине не выдали доступ.
- Что происходит на самом деле? Система входит в «ступор». При попытке провести оплату она проверяет правило 2. Правило 2 требует
access = 'GRANTED'. Чтобы получить этот статус, нужно выполнить правило 1. Но правило 1 требует payment_status = 'PAID', который еще не установлен, так как мы только пытаемся его установить в правиле 2.
Расширенный пример: Метод итеративной валидации
Чтобы избежать таких проблем, используется метод итеративной валидации спецификации. Это процесс пошаговой проверки логики перед написанием кода. Мы разбиваем задачу на логические единицы действия, которые не зависят друг от друга напрямую.
Распространенные ошибки
Самая частая ошибка — использование слов-паразитов в спецификациях: «автоматически», «правильно», «соответствующим образом».
- Как это проявляется? Вы пишете: «Система должна автоматически обновлять статус». Для ИИ «автоматически» может означать «каждую секунду», что приведет к перегрузке базы данных.
- Как исправить? Замените на событие: «При изменении поля X в таблице Y, функция Z должна обновить поле A».
- Галлюцинации структуры: Если вы не описали иерархическую организацию контекста, Claude может решить, что логика оплаты должна лежать в папке
/ui/components (интерфейс), а не в /core/logic (ядро). Это создаст путаницу, где визуальная кнопка управляет деньгами напрямую.
Реальное применение: CRM онлайн-школы
В реальном кейсе CRM онлайн-школы проблема циклической зависимости обычно решается через введение третьего состояния — «Ожидание активации».
Вместо того чтобы связывать «Оплату» и «Доступ» напрямую, мы создаем поток данных, где:
- Оплата переходит в состояние
COMPLETED.
- Это событие порождает запись в журнале транзакций.
- Модуль доступа сканирует журнал и, видя новую запись, меняет состояние доступа на
ACTIVE.
Такой подход гарантирует изоляцию функционала: модуль оплаты ничего не знает о том, как работает доступ, а модуль доступа просто следит за «фактами» в журнале. Это и есть грамотная архитектура без расплывчатых границ.