Что теперь программирует настоящий программист?
Вы открываете задачу и пишете одну строку:
Добавь идемпотентность в API создания заказа.
Через некоторое время перед вами diff в незнакомом репозитории. Изменены обработчик API, модель данных, тесты и документация. Все проверки проходят. При этом вы не написали ни одной строки кода.
AI-исполнитель сам нашёл модуль заказов, принятый формат ошибок и существующую обёртку над Redis. На ревью вы заметили опасное предположение о двух одновременных запросах. Вместо разового замечания вы потребовали закрепить инвариант в контракте и конкурентном тесте. Исполнитель исследовал соседний модуль, исправил решение и снова запустил проверки.
Так кто же автор этого изменения?
Если назвать автором AI, мы выбросим из картины выбор задачи, границ, допустимого риска и критериев готовности. Если назвать автором человека, придётся не заметить, что всю работу от исследования до работающего кода выполнил другой участник.
Моя гипотеза: новым уровнем программирования становится не промпт, а подготовленная среда. Разработчик 2.0 программирует не последовательность действий и не подробное поручение. Он создаёт условия, в которых короткое намерение превращается в проверяемое изменение.
Это не первая такая перемена. История программирования — история того, как мы постепенно передавали машине всё более крупные фрагменты работы:
инструкция процессора
↓
выражение на языке высокого уровня
↓
вызов библиотечного API
↓
декларация желаемого состояния
↓
намерение в подготовленной среде
Мы перестали выставлять биты переключателями, помнить числовые коды инструкций, писать драйвер диска для сохранения заказа и переносить файлы на сервер перед каждым релизом. Ничто из этого не исчезло. Между замыслом человека и работой машины просто появлялись новые исполнители, способные самостоятельно разложить крупное описание на множество мелких действий.
Каждый новый слой встречал сопротивление. Настоящий программист должен понимать ассемблер, сам управлять памятью, сам писать SQL, сам настраивать сервер и, разумеется, помнить весь синтаксис. В этих возражениях была доля правды: абстракция не отменяет реальность, а лишь откладывает встречу с ней. Когда обещание верхнего слоя нарушено, приходится спускаться вниз.
С AI происходит тот же переход, но единица работы стала непривычно крупной. Машине можно передать уже не строку или функцию, а часть цикла разработки: исследование, выбор действий, изменение и проверку результата. Человек снова поднимается на уровень выше и передаёт исполнителю более крупную единицу работы.
Только теперь такой единицей становится намерение.
Версии здесь условны. В течение одного дня тот же человек может быть 0.5, разбираясь с поведением сокета, 1.0, выбирая продуктовый компромисс, и 2.0, настраивая контур делегирования. Это режимы работы, а не карьерная лестница или оценка квалификации. Чтобы понять новый интерфейс, быстро пройдём по предыдущим.
Разработчик 0.1. Программирует машину
В начале программа была почти физическим объектом. Инструкция означала конкретную операцию конкретного процессора, данные жили по конкретным адресам, а ошибка могла оказаться неверно установленным переключателем или перепутанной перфокартой.
Даже увеличение счётчика требовало выбрать адрес, загрузить значение в регистр, выполнить операцию, записать результат и учесть переполнение. Большая часть внимания уходила не на предметную задачу, а на обслуживание самого вычисления.
Одной из первых почти незаметных сегодня абстракций стали символические имена. Ассемблер позволил написать инструкцию и метку перехода, а транслятор сам вычислял адреса и превращал текст в машинный код.
Машине передали расчёт адресов и перевод обозначений. Человеку остались порядок инструкций и состояние процессора. Вместе с удобством появилась новая зависимость: при ошибке символическое описание всё равно приходилось сопоставлять с реальной машиной.
Эта сделка будет повторяться на каждой ступени: меньше ручной работы, больше доступный масштаб и новый класс ошибок на границе слоёв.
Разработчик 0.2. Программирует вычисление
Языки высокого уровня изменили главный вопрос. Вместо «какие инструкции должен выполнить процессор?» стало возможно спросить: «какое вычисление я хочу описать?»
Цикл, функция, структура данных и выражение относятся уже не к устройству железа, а к человеческой модели задачи. Компилятор выбирает регистры и строит низкоуровневые операции, пока разработчик думает об алгоритме и структуре программы.
Доверие возникло не сразу: компилятор мог создать неоптимальный код, а автоматическое управление памятью казалось расточительным. Спор о неидеальном машинном коде обычно заканчивался примерно одновременно с приближением дедлайна.
Запись users.sort() избавляет от ручной перестановки элементов, но не отвечает на важные вопросы. По какому признаку сортировать? Можно ли менять исходную коллекцию? Что произойдёт на миллионе записей?
Машине передали механику. Человеку достались представление задачи и выбор алгоритма. Возник и новый тип ошибки: компьютер мог безупречно выполнить совершенно неверный замысел.
Знание процессора не стало бесполезным, но перестало быть ежедневным интерфейсом к работе. Механика стала дешевле, решение — важнее.
Разработчик 0.5. Программирует платформу
Операционная система предложила удобную фикцию: будто программа работает не с дисковыми секторами, страницами физической памяти и сетевой картой, а с файлами, процессами и сокетами.
Файл — не физическая вещь, а контракт. Мы просим открыть имя и прочитать последовательность байтов; операционная система решает, где лежат данные, как использовать кеш и кто имеет к ним доступ. Процесс создаёт похожую иллюзию отдельной машины, хотя делит ресурсы с множеством соседей.
Разработчику интернет-магазина больше не нужно писать драйвер диска, чтобы сохранить заказ. Он вызывает системную функцию — часто через несколько библиотечных слоёв — и занимается моделью заказа.
Но контракт работает ровно до того момента, когда начинает протекать. Файл может записаться не целиком, системный вызов — прерваться, а отправленные одним вызовом данные — приехать несколькими фрагментами. Виртуальная память выглядит безграничной, пока внезапно не заканчивается физическая.
Платформа забрала работу с устройствами. Человеку достались ресурсы и их контракты. Новый профессиональный навык состоял в том, чтобы верить этим контрактам в обычной работе и знать их пределы во время сбоя.
Разработчик 0.7. Программирует из готовых блоков
Большая часть современного приложения написана не его авторами.
Парсер JSON, TLS, маршрутизация HTTP, часовые пояса, повторные запросы, логирование и компоненты интерфейса уже имеют готовые реализации. Менеджер пакетов превращает подключение многолетней чужой работы в одну строку конфигурации.
Если достаточно долго спускаться по дереву зависимостей, где-то внизу почти наверняка обнаружится libcurl. Современная облачная архитектура — это иногда Kubernetes, сотня контейнеров и Даниэль Стенберг, который снова чинит нам интернет.
Единицей разработки стала композиция: выбрать блоки, соединить их контрактами, настроить поведение и дописать то, что действительно отличает продукт. Во фреймворке уже не наш код вызывает библиотеку, а чужая архитектура вызывает наш код.
Один человек получил возможность собрать систему, для которой раньше понадобилась бы отдельная команда. Но десять строк конфигурации могли активировать миллионы строк зависимостей. Запись стала короче, поведение — не обязательно проще.
Готовые блоки забрали реализацию типовых механизмов. Человеку достались выбор границ, оценка зависимостей и ответственность за всю композицию, включая код, которого он никогда не видел.
Разработчик 0.9. Программирует поставку
Долгое время граница программы совпадала с исходным кодом. Разработчик писал приложение, а кто-то другой устанавливал его на сервер, настраивал окружение и разбирался с релизами.
Потом инфраструктура тоже стала программируемой. Контейнер описал окружение, конвейер — путь изменения до продакшена, облачный API превратил серверы и сети в создаваемые по запросу ресурсы.
Особенно важным стал переход от инструкции к желаемому состоянию. Вместо «запусти три процесса, проверь каждый и перезапусти упавший» можно написать:
spec:
replicas: 3
Две строки не содержат алгоритма восстановления. Они задают цель, а контроллер сравнивает описание с реальностью и сам выбирает следующие действия.
Если приложение падает, оркестратор обеспечит высокую доступность падения сразу в трёх экземплярах.
Одновременно изменилось понятие законченной работы. Функции на ноутбуке автора стало недостаточно: изменение должно пройти проверки, безопасно попасть к пользователю, стать наблюдаемым после выпуска и иметь путь отката. Тесты, сборка, права доступа, алерты и миграции стали частями одной программируемой системы.
Инфраструктурному исполнителю передали маршрут к желаемому состоянию. Человеку остались само состояние, ограничения и обратная связь. Ошибки тоже поднялись уровнем выше: теперь система могла безупречно поддерживать неверную конфигурацию.
Эта ступень напрямую подводит к AI. Автоматизация безопасна не потому, что всегда выбирает правильное действие, а потому, что вокруг неё существуют границы, проверки и наблюдение.
Разработчик 1.0. Программирует продукт
Современного разработчика редко оценивают по числу написанных строк. Хороший результат может удалить код, заменить собственный сервис готовым или выяснить, что проблема вообще решается изменением процесса.
Иногда высшая форма инженерного мастерства — закрыть задачу словами «это не нужно делать». Правда, GitHub не засчитает это в статистику коммитов.
Работа начинается раньше редактора. Нужно понять, кому мешает текущее поведение, отделить симптом от причины, определить границы задачи и выбрать компромисс. После кода остаются совместимость, миграция данных, выпуск, метрики и обратная связь пользователей.
Вернёмся к заказу из начала статьи. «Добавить идемпотентность» звучит как техническая задача, пока не начинаются вопросы. Как клиент передаёт ключ? Сколько он живёт? Что возвращать при повторе? Как изолировать магазины? Что произойдёт при двух одновременных запросах? Можно ли хранить тело запроса?
Разработчик 1.0 замечает эти развилки до того, как случайные ответы закрепятся в коде. Он сам исследует продукт, принимает решения, меняет обработчик и модель данных, пишет тесты и готовит изменение к выпуску. Код остаётся точным носителем решения, но уже не является целью.
На этом уровне человек программирует изменение продукта. Но даже после принятия всех решений он вручную проходит длинную цепочку микродействий. Инструменты помогают на каждом шаге; сам цикл управления всё ещё находится у разработчика в голове.
Разработчик 1.5. Менеджер AI-разработчика
Автодополнение сократило набор текста, поиск ускорил навигацию, шаблоны убрали повторение. Однако человек по-прежнему замыкал на себе весь контур управления: посмотреть на состояние, выбрать следующее действие, выполнить его и оценить результат.
На уровне 1.5 часть этого цикла берёт на себя AI. Ему можно поручить законченный фрагмент работы: исследовать репозиторий, выбрать реализацию, изменить несколько файлов, запустить тесты и отреагировать на ошибки. Человек перестаёт управлять каждым действием и становится менеджером отдельного AI-разработчика.
Слово «менеджер» здесь условно. У AI нет карьерного плана, ему не нужны встречи один на один и он вряд ли уйдёт к конкурентам после пересмотра зарплаты. Но рабочий цикл до смешного знаком: поставить задачу, проверить результат и вернуть на доработку.
Снова попросим добавить идемпотентность. В неподготовленном репозитории короткая фраза из начала статьи оставляет слишком много неизвестного. Менеджер компенсирует недостаток среды подробным поручением.
Цель: повторный
POST /ordersс тем же заголовкомIdempotency-Keyв течение 24 часов должен вернуть первоначальный идентификатор заказа и не создавать новую запись.Контекст: обработчик находится в модуле
orders; в проекте уже есть обёртка над Redis и принятый формат ошибок API. Сначала найди существующие примеры их использования.Ограничения: сохрани поведение клиентов без этого заголовка; не добавляй новую зависимость; изолируй ключи по магазину; не сохраняй в Redis тело запроса и персональные данные.
Проверка: добавь тесты на обычный запрос, последовательный повтор и два конкурентных запроса. Запусти тесты модуля и общую проверку типов. Если текущая архитектура не позволяет надёжно обработать конкуренцию, остановись и объясни ограничение до изменения схемы данных.
В какой-то момент постановка становится длиннее будущего diff. Мы вроде бы перестали писать код, но получили язык программирования без подсветки синтаксиса.
Это хорошее поручение. Оно оставляет исполнителю свободу реализации, но сохраняет за человеком решения с высокой ценой ошибки. Проблема в другом: человек вручную собирает продуктовый контекст и компилирует его в промпт для каждой задачи.
Так работает разработчик 1.5: он не пишет реализацию построчно, но управляет каждым поручением отдельно. Промпт становится временной программой, которую после выполнения задачи выбросят.
Архитектурные ограничения, команды проверок и продуктовые соглашения приходится повторять снова и снова. Они существуют в голове менеджера, но ещё не стали свойствами среды.
Следующий уровень начинается не с более подробного промпта. Он начинается в момент, когда значительную часть промпта можно удалить.
Разработчик 2.0. Техлид AI-команды
У уровня 1.5 есть скрытое ограничение: контекст по-прежнему живёт в голове человека. Чем больше задач он делегирует, тем больше времени тратит на пересказ устройства продукта. Менеджер становится ручным сериализатором знаний команды.
Разработчик 2.0 действует как техлид: переносит знания из личных объяснений в архитектуру, правила и инструменты. Под AI-командой здесь понимается не обязательно несколько моделей, а вся система разработки: исполнитель, доступные ему инструменты и навыки, тесты, правила проекта и человек, принимающий решения в точках высокого риска.
Короткое поручение возвращается
На уровне 2.0 постановка снова выглядит так:
Добавь идемпотентность в API создания заказа.
Это та же строка, с которой началась статья. Теперь её достаточно не потому, что AI научился читать мысли. Контекст переехал из разового промпта в постоянную среду.
В условном репозитории перенос контекста из промпта в среду может выглядеть так:
docs/api/idempotency.md срок хранения и ответ при повторе
src/shared/idempotency изоляция ключей по магазину
policies/data-handling.md запрет сохранять персональные данные
tests/orders/idempotency конкурентный сценарий
AGENTS.md обязательные проверки
Если схема заказов не позволяет гарантировать результат при конкуренции, зрелый исполнитель не маскирует пробел правдоподобным кодом. Он останавливается и возвращает вопрос:
Последовательные повторы можно обработать существующими средствами. Для двух одновременных запросов в схеме нет надёжного инварианта уникальности. Можно ли добавить его на уровне базы данных?
AI не угадал ответ. Среда помогла ему обнаружить место, где ответа пока нет.
Подготовленная среда не отменяет продуктовые решения. Она лишь избавляет от необходимости заново пересказывать уже принятые. Если срок хранения ключа ещё не определён, AI нечего искать в репозитории — решение должен принять человек.
|
Уровень |
Роль человека |
Где находится контекст |
|---|---|---|
|
1.0 |
Сам реализует изменение |
В голове разработчика и частично в репозитории |
|
1.5 |
Управляет одним AI-разработчиком |
В промпте конкретной задачи |
|
2.0 |
Проектирует работу AI-команды |
В репозитории, продуктовых контрактах, инструментах и обратной связи |
Менеджер готовит поручение для AI-разработчика. Техлид готовит среду, в которой команде почти не требуются дополнительные объяснения.
Репозиторий становится средой исполнения
Компилятору нужны исходный код и параметры сборки. Контроллеру инфраструктуры — декларация ресурсов. AI-исполнителю нужна среда, из которой можно восстановить правила работы.
Многое уже находится в репозитории:
-
типы описывают допустимые данные;
-
тесты фиксируют наблюдаемое поведение;
-
структура проекта показывает архитектурные границы;
-
история изменений объясняет происхождение решений;
-
документация сообщает то, что нельзя надёжно вывести из кода.
Для человека всё это было полезной информацией. Для AI становится исполняемым контекстом — постоянной программой верхнего уровня.
Файлы вроде AGENTS.md делают правила явными: как запустить проверки, где находятся ключевые модули, каких зависимостей избегать и что считать законченной задачей. Повторяемые навыки добавляют процедуру: как подготовить миграцию, проверить интерфейс, выпустить пакет или расследовать сбой.
AGENTS.md — это документ для адаптации, у которого наконец появился читатель, не обещающий ознакомиться с ним позже.
Подготовленный к делегированию репозиторий полезен не только модели. Новый человек тоже быстрее получает обратную связь и реже вынужден угадывать. Разница в том, что AI делает цену неявных знаний заметной немедленно.
Тесты становятся органами чувств
Когда код пишет человек, тест проверяет его предположение. Для AI тест дополнительно становится сигналом управления: исполнитель меняет систему, получает результат и корректирует следующее действие.
Без быстрой и содержательной обратной связи он движется вслепую. Чем длиннее путь от изменения до сигнала, тем больше шансов накопить правдоподобные, согласованные между собой ошибки.
Отсюда парадокс: чем меньше деталей мы хотим повторять в поручении, тем точнее результат должен быть описан постоянными свойствами среды. Контракт API, схема данных, тест на свойство, ограничение типов и бюджет производительности уменьшают пространство неверных решений. Не потому, что AI лучше слушается, а потому, что система быстрее отвергает неподходящий вариант.
Старые инженерные практики внезапно получают нового клиента. Ясные границы модулей, быстрые тесты, воспроизводимое окружение и актуальная документация теперь экономят время не только людям.
Теперь код пишется быстрее, чем читается
Когда производство кода дешевеет, узким местом становится способность команды проверить изменение. AI может быстро создать diff, на чтение и осмысление которого человеку потребуется гораздо больше времени. Если просто увеличить поток изменений, очередь переедет из разработки в ревью.
Зелёные тесты сами по себе не спасают: исполнитель способен написать проверку, подтверждающую его собственное неверное понимание задачи. Нужны независимые источники истины — продуктовый сценарий, контракт, инвариант данных, наблюдение в работающей системе.
Техлид выбирает размер автономного шага. Слишком маленькая задача превращает AI в дорогое автодополнение. Слишком большая для неподготовленной среды оставляет ему столько скрытых решений, что ревью становится дороже самостоятельной работы.
Рабочий контур выглядит так:
намерение
↓
подготовленная среда
(контракты, примеры, права, проверки)
↓
исследование и изменение AI
↓
автоматическая проверка
↓
инженерная оценка человеком
↓
обратная связь или принятие
Человек выбирает задачу, формулирует инварианты, выдаёт доступ, оценивает риск и принимает ответственность. Его внимание перемещается с каждого промежуточного действия на устройство всего контура.
Поэтому производительность разработчика 2.0 измеряется не объёмом сгенерированного кода, а объёмом изменений, которые команда способна понять, проверить и безопасно доставить пользователю.
Что теперь становится суперсилой
Если написание типового кода дешевеет, дорожают навыки вокруг него.
|
Суперсила |
Что это означает на практике |
|---|---|
|
Декомпозиция |
Выделить фрагмент работы с понятными границами и ограниченным радиусом последствий. |
|
Спецификация среды |
Закрепить повторяющиеся требования в контрактах, типах и тестах, а не пересказывать их в каждом промпте. |
|
Навигация по системе |
Сделать источники истины доступными и помочь исполнителю определить, какие компоненты затронет изменение. |
|
Проектирование обратной связи |
Построить короткий цикл из тестов, типов, анализаторов и метрик. |
|
Оценка результата |
Отличить решение задачи от убедительной имитации решения. |
|
Управление риском |
Соотнести размер автономного шага, доступ и строгость контроля с ценой ошибки. |
Ни один из этих навыков не появился вместе с языковыми моделями. AI просто резко увеличил их ценность.
Кто вырастит следующего техлида?
Здесь возникает неприятный вопрос. Если AI заберёт задачи, на которых раньше учились начинающие разработчики, откуда возьмутся люди, способные проверять его решения?
Работающее изменение можно получить раньше, чем появится внутренняя модель системы. Легко пропустить этап, на котором человек учится строить гипотезу, читать ошибку и связывать наблюдаемое поведение с устройством программы. Расстояние между «получилось» и «я понимаю почему» становится больше.
Значит, ускорение работы нельзя путать с ускорением обучения. В учебном режиме полезно сначала предсказывать результат, просить AI показывать альтернативы и объяснять, какое предположение подтвердил каждый тест. Иногда небольшой фрагмент стоит выполнить самостоятельно — не из уважения к ручному труду, а потому, что без собственной практики невозможно проверять чужую работу.
Готовые библиотеки и поисковые ответы создавали ту же проблему. Новый слой лишь увеличил масштаб того, что можно собрать без понимания.
Самая опасная ошибка выглядит законченной
Вернёмся к идемпотентности. Допустим, решение надёжно обрабатывает последовательный повтор, но два одновременных запроса успевают создать две записи до сохранения результата. Тесты, написанные тем же исполнителем, проверяют только удобный сценарий. Изменение аккуратное, объяснение связное, все проверки зелёные.
Именно способность имитировать законченность отличает новую абстракцию. Неверный машинный код часто падал. Неверный системный вызов возвращал ошибку. Здесь ошибка может выглядеть как готовое решение.
Любая абстракция надёжна до тех пор, пока продакшен не решит познакомить вас с её реализацией.
Типовые точки отказа уже видны:
-
модель не нашла скрытое требование и разумно заполнила пробел;
-
локально корректное изменение нарушило системный инвариант;
-
тест подтвердил реализацию, а не требуемое поведение;
-
устаревшая документация стала ложным источником истины;
-
слишком широкие права превратили ошибку рассуждения в реальное действие.
Поэтому «я использую AI» почти ничего не говорит о зрелости процесса. Важно, какие решения ему разрешено принимать, какие доказательства он обязан представить и как быстро система обнаружит ошибку.
Разработчик 2.0 не тот, кто делегирует больше всех. Это тот, кто умеет выбирать, что можно делегировать безопасно.
Компилятор не притворяется, что понял
Здесь аналогия с предыдущими уровнями начинает ломаться. Компилятор работает по формальным правилам: одинаковая программа при одинаковых параметрах должна дать предсказуемый результат. Поставленная естественным языком задача почти всегда недоопределена, а повторный запуск модели может предложить другую реализацию — и обе будут выглядеть разумно.
Компилятору не нужно понимать, зачем существует функция. AI восстанавливает намерение по неполному контексту и иногда продолжает именно там, где должен остановиться и задать вопрос. Поэтому его нельзя сделать надёжным одной удачной инструкцией.
Историческая роль всё же знакома: новый исполнитель принимает более крупную единицу человеческого замысла и раскладывает её на действия нижнего уровня. Но вместо одной формальной гарантии ему нужны внешние опоры — ограниченные права, типы, тесты, наблюдение и человеческое решение в точках высокого риска.
AI — не новый компилятор. Но считать его новым уровнем абстракции полезно, если помнить: этот уровень вероятностный и по умолчанию недоверенный.
Это всё ещё программирование?
Если программирование — только запись точных инструкций на формальном языке, часть новой работы действительно находится за его пределами. Но это определение давно не описывает профессию целиком. Мы проектируем API, выбираем зависимости, задаём политики и описываем инфраструктуру, хотя не каждое из этих действий похоже на функцию на C.
Полезнее считать программированием создание воспроизводимого поведения вычислительной системы. Тогда AI добавляет вероятностный уровень трансляции между замыслом и реализацией. Его нельзя проверить только синтаксисом; ему нужны ограничения, наблюдение и итерация.
Мы стали на одну ступень дальше от отдельной строки кода — и на одну ступень ближе к ответственности за то, зачем она существует.
Заключение. Чем выше абстракция, тем важнее ответственность
Каждая ступень этой истории убирала рутину и одновременно расширяла область ответственности разработчика.
Когда одна строка управляет регистром, ошибка обычно локальна. Когда декларация создаёт кластер, короткая запись получает большой радиус действия. Когда одно поручение меняет десятки файлов, его автор отвечает уже не за подробность промпта, а за качество среды, из которой исполнитель восстанавливает контекст и критерии проверки.
Будущее разработки поэтому вряд ли сведётся к особенно хитрым промптам. Подробное поручение — инструмент менеджера уровня 1.5. Дольше проживёт навык техлида: превращать продукт в систему, где короткое намерение можно правильно понять, а результат — увидеть и проверить.
Фундаментальные знания от этого не становятся менее важными. Чем выше мы поднимаемся, тем реже вручную используем нижние уровни — и тем ценнее способность спуститься к ним, когда верхний слой нарушает обещание.
Так кому всё-таки принадлежит изменение из начала статьи? AI написал значительную часть кода. Человек выбрал желаемое поведение, подготовил источники истины, заметил риск и принял ответственность за результат. А программой верхнего уровня стала среда, связавшая короткое намерение с проверяемым изменением.
Разработчик 2.0 не перестаёт программировать. Он программирует условия, в которых правильное действие становится вероятнее, а неправильное — быстрее заметно.
Просто один человек сможет поручить машине гораздо больше.
Автор: how


