Английский вместо кода

Язык, который придумали, чтобы программисты стали не нужны, породил профессию, которая жива до сих пор и неплохо оплачивается, а другой язык назвали «структурированным английским», и думали, что на нем сможет писать любой бухгалтер, и он тоже породил новую специальность со своей зарплатной вилкой. А еще была попытка сделать «программирование без программистов к двухтысячному году», но и он дал обратный результат.
Думаю вы узнали COBOL, который по сей день ежедневно эксплуатируется и по разным оценкам стоит за 80% обычных (магазинных) банковских транзакций, а его кодовая база тянет на пару сотен миллиардов строк и до сих пор кормит десятки, если не сотни тысяч разработчиков. Правда, если копнуть эти красивые цифры, почти все они восходят к одному опросу конца девяностых, который потом бесконечно переэкстраполировали на весь мир, так что честнее считать их порядком величины, а не точными данными.
SQL породил особую касту DBA (Database Administrators) и Data Engineers и сегодня человек, который пишет «простые запросы», может легко зарабатывать на уровне мидла, а сам язык стал настолько сложным, что современные диалекты (PostgreSQL, Oracle) — это полноценные языки программирования с процедурной логикой, где можно написать всё что угодно, от генератора фракталов до игрового движка.
Семейство 4GL оказалось «золотой клеткой» и прекрасно работали, пока нужно было сделать типичную форму «ввод‑вывод», но как только требовалась нестандартная бизнес‑логика или интеграция с внешним сервисом, инструмент упирался в свои границы и программистам приходилось дописывать «костыли» на низкоуровневых языках, что превращало разработку в адский коктейль из визуального дизайна и грязных хаков. И вместо исчезновения программистов, 4GL создали «архитекторов корпоративных систем», которые (например, SAP ABAP), стали невероятно дорогими специалистами, и тоже не устранил программирование, а просто переместил его из зоны «универсальных языков» в зону «дорогих и капризных инструментов», привязывающих компанию к конкретному вендору.
Каждые десять‑пятнадцать лет индустрия торжественно объявляет, что писать код руками больше не придётся, продавая новый способ «объяснить машине задачу на нормальном человеческом языке». И каждый раз через несколько лет выясняется, что программистов стало не меньше, а больше, просто теперь они называются иначе. Предположу, что сейчас мы проживаем очередной виток этого цикла, и новое название таким людям будет вайбкодеры, и думаю этому инструменту, уготована та же судьба, что и у предыдущих попыток.
Идея «говорить с машиной на человеческом языке» старше самого понятия компьютера, ей полна фантастика первой половины двадцатого века, от «Метрополиса» Фрица Ланга, которому будет сто лет в обед, с его механическим двойником человека до рассказов, где машине отдают приказы голосом и она послушно их исполняет. Но как только в сороковых появились настоящие вычислительные машины, выяснилось, что проблема не в машине.
Конрад Цузе, который построил Z3 в сорок первом году и придумал один из первых высокоуровневых языков (Plankalkül), сформулировал эту проблему как «опаснее не то, что компьютеры станут как люди, а что люди станут как компьютеры». Многие знакомые мне разработчики на полном серьезе считают языки программирования просто худшей версией английского, не буду с ними спорить… Это не «плохая версия английского», а инструмент с принципиально другими свойствами, не хуже естественного языка и не лучше, просто он про другое.

Что на самом деле делает язык программирования
Что значит для бухгалтера фраза «посчитай сотрудникам премии за квартал»? В начале моей карьеры занесло меня в небольшую конторку, которая плодила энтропию в этом мира и занималась написанием чего‑то вроде 1C движка для подсчета зарплат, поэтому я немного коснулся этого болота. Живому человеку этой фразы было достаточно, чтобы достроить десятки умолчаний: кому именно начислять, по какой формуле, что делать с теми, кто пришёл в середине квартала, что с уволенными, округлять ли и в какую сторону, в какой валюте, что делать если по человеку вообще нет данных. Естественный язык работает именно потому, что слушатель затыкает эти дыры контекстом, здравым смыслом и общими знаниями, которых у него много, потому что он работает в этой сфере.
Программа, именно программа, код… так не умеет. Каждое из этих решений должно быть где‑то зафиксировано, подперто, написано процедурой, иначе результат получится недетерминированым, а недетерминированная бухгалтерия это уже не бухгалтерия, а повод для разговора с налоговой. И часто даже опытные бухгалтеры не все могли учесть сразу, поэтому короткая фраза на естественном языке разворачивается в вот что‑то такое:
"посчитай премии за квартал"
▼
- за какой именно квартал (календарный? финансовый? от даты найма?)
- кто попадает в расчёт (штат? совместители? уволенные в середине?)
- база начисления (оклад? оклад + переработки? средний за период?)
- формула (процент? фикс? прогрессивная шкала?)
- пропорция для неполного квартала (по дням? по месяцам? вообще нет?)
- округление (математическое? вниз? до рубля? до копейки?)
- валюта и курс (на какую дату берём курс?)
- отсутствующие данные (пропустить? считать ноль? упасть с ошибкой?)
Восемь других вопросов из одного, и это я ещё поленился, и каждый вопрос порождает еще вопросы, а когда вопрос перестает порождать другие вопросы, то его можно описать терминами язков программирования.
Язык программирования существует не вопреки этой занудной точности, а ради неё, потому что даёт синтаксис, в котором двусмысленность физически невыразима, и семантику, в которой одна и та же программа всегда означает одно и то же. Программист, который «переводит» пожелание менеджера и бухгалтера в код, на самом деле занят не переводом техзадания в код, но принимает вот эти восемь или больше вопросов и берёт на себя ответственность за ответы.
Просто скажи по‑…
.не работает. Есть причины, по которым «естественный язык вместо кода» упирается в потолок, они про нас… человеков, не про тулы, компиляторы, стандартные библиотеки или ограниченность существующих языков программирования, и основная будет в неустранимой двусмысленности естественных языков.
Что вы сделаете если вас попросят «удалить все файлы старше 30 дней в этой папке»? Скорее всего вы просто выделите файлы по дате изменения и удалите их… кажется, что это простое действие, но вы своим опытом ответили на 90% подвопросов. А этих подвопросов очень немало, если начать формализовать базовый вопрос:
— Старше по дате создания или по дате изменения?
— Подпапки и файлы там трогаем?
— А скрытые файлы удаляем?
— А симлинки, ссылку удалим или сам файл?
… и тд
Чтобы убрать двусмысленность, надо либо задать кучу уточняющих вопросов и тем самым фактически написать спецификацию (код программы) словами, либо принять решения за того кто спросил и возможно сделать не то, что он хотел. Языки программирования решают возникающие подвопросы грубой логикой, потому что у каждой конструкции есть ровно одно значение, и mtime никогда внезапно не станет ctime.
Но даже ответив точно на все вопросы и связные вопросы мы упираемся в теорему Райса, довольно скучный математический трактат 1953 года с невесёлым практическим следствием для нас человеков, который звучит так: никакое нетривиальное семантическое свойство программы нельзя проверить алгоритмически в общем случае. Т.е. нельзя автоматически гарантировать, что сгенерированный код делает именно то, что просили, и значит, кто‑то должен проверить, что получилось. А чтобы проверять, надо читать код, а чтобы читать код, нужен формальный язык. Круг замкнулся.
Косвенно вылезает ещё одно свойство, уже не про Райса, а про сам естественный язык. Чем более сложную композицию мы хотим построить, тем хуже она ложится на слова. По‑русски это звучит так, что маленькую функцию описать словами можно, получится даже неплохо и понятно, а вот систему на миллион строк словами описать нельзя, и дело не в том, что слов не хватит, просто естественный язык не композируется, а смысл может накладываться, перетекать от предложения к предложению или зависеть от соседних предложений, захватывая абзацы, а иногда и более крупные участки произведения.
Дальше будет сложный блок, я спрячу его под спойлер, и если лингвистика вам не заходит, можете пролистать до следующего раздела, мысль там повторится через понятные для разработчика вещи и сравнения.
Но если интересно, откуда вообще берётся эта «несводимость к словам», то её давно и подробно описали лингвитсы, задолго до всякого ИИ. Они пытались формально записать и посчитать значения обычной человеческой фразы, и обнаружили, что значение предложения нельзя посчитать, глядя только на само предложение. Любой текст на естественном языке не может быть переложен как есть в другие формы представления без потери контекста или значения отдельных частей. Процесс переложения требует выполнения некоторой работы по разделению общего контекста на части, оценка сущностной сложность задачи (essential complexity).
В этом состоянии пребывает программист перед написанием любого кода, называется оно… барабанная дробь… аналитический паралич (иногда еще называют ступор Брукса, как процесс превозмогания той самой essential complexity). Об это состояние спотыкается и идея «просто скажи машине словами» и спущенное сверху «вот тебе ТЗ словами, напиши программу на…», поэтому имеет смысл заглянуть, что там нарыли за сорок лет.
Про Райса, Кампа и DRT

Но у естественного языка есть другая беда, это уже не про Райса. Могут быть сами предложения нелогично устроены, утроены, смазаны да наперёд‑задом напридуманы, перекручены‑перепутаны, шиворот‑навыворот скроены и вкривь да вкось заплетены, так что дорожек не одна в том словеном саду, а что есть расходятся середь фразы, и вы понимаете это, только дочитав до конца, а то и перечитав с начала. Не то, чтобы я был великим лингвистом, но в конце десятых пришлось дописывать матерный фильтр в одном из приложений, а уж в великом и могучем послать по матушке можно было очень разными способами, так что пришлось немного коснуться и этой темы. Но вернемся к нашим баранам… то есть словам.
Пока мы говорим маленькими фразами вроде «удали файл», всё в порядке и фраза целиком помещается в голове и не тянет за собой хвост контекста. Но стоит попробовать описать словами что‑то посложнее, и выясняется, что слова начинают «мешать друг другу» или «зависеть друг от друга» через границы предложений, а переменная в нормальном языке программирования зависеть должна только от четкого контекста, где используется.
Классическая фраза «каждый крестьянин, у которого есть осёл, бьёт его» понятная, любому русско‑говорящему человеку, читается обычно без запинок. А теперь попробуйте разбить её на части и сохранить значение каждой части отдельно, как это делает компилятор с выражением.
«У которого есть осёл» теперь просто утверждает существование осла у некоторого крестьянина, а «бьёт его» отдельно от всего остального вообще непонятно кого бьёт, потому что «его» появляется уже после того, как «осёл» успел мелькнуть и с формально вышел из области видимости.
Человек это не замечает, потому что держит в голове весь кусок целиком и достраивает эту связь на лету, а вот функция, которая вычисляет значение предложения по кусочкам слева направо, как это делает любой нормальный парсер, будет ломаться, либо будет настолько сложной, что о её практическом применении речь уже не идет.
Для программиста это будет переменная, которая объявлена внутри одной функции, а видна она и в следующей, без явной передачи и без global, потому что где‑то зацепили контекст применения. Ни один язык такого не разрешает и области видимости придуманы именно затем, чтобы подобное было невозможно by design, а естественный язык только этим и живёт, у него «осёл» протекает сквозь границу предложения, и это считается нормальным поведением.
Утечку контекста описали лингвисты задолго до всякого ИИ, Ханс Камп в начале восьмидесятых в работе про динамические семантики и почти одновременно Ирен Хайм в диссертации про file change semantics, оба независимо упёрлись в то, что значение предложения нельзя посчитать, не притащив с собой то, что было сказано раньше.
Так родилась дискурсивная теория репрезентации, DRT, чей единственный практический вывод для нас программиста звучит скучно и нерпименимо, потому что он в «естественной среде обитания» работает вне DRT. Нельзя формально гарантировать, что кусок текста можно понять в отрыве от соседних кусков, а значит нельзя и требовать от языка, которым вы объясняете машине задачу, чтобы он вёл себя как код, оставаясь при этом естественным языком.
Естесвенная среда программиста это Код, а Код от этой болезни избавлен и вызов calculateAge(1985, 2026) означает одно и то же, воткните вы его в игровой цикл или в отчёт для налоговой, и за ним не тянется невидимый хвост из предыдущих строк, которые меняют его смысл.
И задача программиста собрать Большую Систему из независимых кусков, и это можно только если куски не меняют своё значение от того, куда их поставили, а естественный язык на это принципиально не способен, у него состояние маленького предложения плывёт от размера контекста, в который его засунули. Вряд ли кому‑то понравится, если результат sum(a + b) вдруг начал бы зависеть от длины вызывающей функции.
Надеюсь я вас не сильно утомил этим дискурсом?
Если все еще интересно про DRT
Для начала можно посмотреть статьи Stanford Encyclopedia of Philosophy, “Discourse Representation Theory” и «Dynamic Semantics», они бесплатные, вычитанные специалистами и написаны доступным языком, а не как оригинал Кампа.
Следующий уровень это первоисточники, работа «A Theory of Truth and Semantic Representation» и диссертация Ирен Хайм «The Semantics of Definite and Indefinite Noun Phrases». Их полезно хотя бы полистать, чтобы увидеть, что это не эзотерика, а попытка в до ИИ эпоху построить ту самую «функцию над контекстом».
Вся эта литература действительно трудная, и неспециалисту кажется водяной водой в ведре с водой, но обратите внимание, чего стоило формально описать всего лишь один уровень мысленных представлений (DRS) семантики естественного языка и даже это не закрывает теорию язык целиком.
Современные большие языковые модели на DRT не построены, это статистические трансформеры, а не теория Кампа, поэтому это не фундамент ИИ, а история почему функции над контекстом упираются в такую сложность и терабайты оперативной памяти, чтобы вы могли спросить и модели день рождения Ленина. Ну и для понимания, почему идея сделать естественный язык точным языком спецификаций, выглядит наивно. Это то, что сейчас продают вайбкодеры в качестве мечты «английский вместо кода»

Это уже пробовали. И не раз…
История знает несколько крупных заходов на тему «избавимся от программистов через язык, близкий к английскому». Забавно, что каждый из них давал один и тот же побочный эффект, когда старые программисты оставались, но рождались новые специализации, давая работу новому поколению программистов.
COBOL (1959) создавался с целью дать возможность менеджерам и бизнес‑аналитикам читать и писать программы. Поэтому и синтаксис специально сделали похожим на английские предложения, ADD SALARY TO TOTAL GIVING NEW-TOTAL, читается как почти обычное предложение, ну им в Америках… обычное. В результате появилась профессия COBOL‑программиста, которая жива до сих пор и на которой всё ещё крутится изрядная часть банковских и государственных систем, я об этом сказал в начале статьи. А вот менеджеры, что характерно, писать на нём так и не начали, продолжив писать отчеты руками, в ворде, в виде таблиц и схем, и давать задания, теперь уже COBOL‑разработчикам.
Потом настала эпоха SQL (1974), который изначально назывался SEQUEL, то есть Structured English Query Language, и назван так именно потому, что должен был позволить нетехническим людям задавать вопросы «программе» на почти‑английском. Позже его переименовали в SQL по рекламно‑денежными причинам, но замысел «английский для запросов» остался зашит прямо в имени. Сегодня SQL‑разработчик это отдельная профессия, а «нетехнический человек‑менеджер», встретивший LEFT JOIN с тремя подзапросами и оконной функцией, обычно идёт искать технического, которые понимает этот трехэтажный, великий и могучий.
Потом были 4GL и CASE (Computer‑Aided Software Engineering, восьмидесятые), которые считаются языкам четвёртого поколения «естественных языков программирования», и опять обещали сделать «программирование без программистов». Реклама звучала из каждого утюга и была настолько мощной, что в конце восьмидесятых многие реально опасались эффекта пустых офисов, когда большинство приложений будет создаваться без написания кода, а разработчики массово потянутся к «свободной кассе». Но опять к двухтысячному году индустрия не только не избавилась от программеров, а обзавелась целой плеядой новых высокооплачиваемых специалистов по SAP, Oracle и проприетарным фреймворкам.
Оказалось, что «естественность» 4GL‑систем такая же иллюзия, как COBOL и SQL до него, просто скрывающая за фасадом из визуальных блоков чудовищную сложность конфигурации и непредсказуемое поведение системы. Чем больше CASE‑инструменты пытались автоматизировать написание кода, тем больше времени программисты тратили на борьбу с ограничениями самих этих инструментов, превращаясь из творцов логики в «архитекторов системных интеграций» и в итоге вместо исчезновения разработчиков мы получили их дефицит, а «программирование без программистов» просто переехало в другую плоскость, где теперь вместо написания кода на C++ или Pascal нужно учиться понимать «тайное знание» конкретного вендора, превращая визуальный конструктор в очередной, пусть и очень дорогой, инструмент программирования.
Действительно дорогой, потому что зарплата обычного SAP‑разработчика легко улетает за 100к$ плюс обучение плюс годовые экзамены, а сверху к этому идёт обучение по Xk$ и обязательная ежегодная переаттестация, без которой сертификат просто протухает, и всё это завязано на платную подписку самого вендора.
Потом пришел черед UML и Model‑Driven Architecture (девяностые‑нулевые) с красивой идеей рисования диаграмм, которые будут генерировать код. А на практике UML выжил как средство документации и схема для разработчиков, которые потом код всё равно пишут руками, а иногда рисуют диаграммы уже по написанному коду, что как бы намекает. Потом денег в UML стало сильно меньше, и люди, продававшие Model‑Driven Architecture, в начале десятых массово потянулись в No‑Code и Low‑Code стартапы и конторы, всех видов и размеров, что тоже как бы намекает.
Bubble, Webflow, OutSystems, Mendix начали продавать всем желающим «теперь любой бизнес соберёт себе приложение сам», а на практике это свелось к типовым задачам, формам, CRUD‑интерфейсам и автоматизациям со своим тренерами, школами, инструментами и поддержкой. Но опять же, как только нужна нестандартная логика, интеграция или производительность, приходится городить костыли их блоков внутри платформы, либо нанимать разработчика, который знает именно эту платформу и умеет писать «обычный» код на C++/Java/Swift/выберете свое. То есть появилась, сюрприз… ещё одна специализация. Оказалось, что индустрия, которая продавала мечту «вам больше не нужен разработчик», за небольшой гешефт параллельно продаёт сертификат «я разработчик под эту штуку». Настал черед LLM…
Вы находитесь здесь, и она качественно отличается от предыдущих, потому что впервые инструмент стал работать с произвольным естественным языком, а не с ограниченным DSL в виде блоков, схем, специальных слов. Это очень большой скачок, сравнимый с COBOL/SQL/UML и остальными, тут я говорю безо всякой иронии. Но фундаментальные ограничения в виде двусмысленности, проверяемости и воспроизводимости, никуда не делись, потому что они не про инструмент, а про природу задачи. Кто‑то всё равно должен сформулировать задачу, сформулировать её точно и небольшими порциями, прочитать сгенерированный код и ответить за то, что это код будет делать в проде в три часа ночи.
Если вы оглянитесь назад, на этот список, то увидите, что каждая волна действительно убивала какой‑то пласт ручной работы, но каждая же волна создавала новый пласт работы поверх себя.

Парадокс Джевонса
В 1865 году Уильям Стэнли Джевонс заметил, что чем эффективнее становятся паровые машины и чем меньше угля требуется каждой для выработки единицы работы, тем больше в целом угля стали потреблять, потому что подешевевшая единица работы открыла столько новых применений, что суммарный объем нужной работы вырос.
Каждый раз, когда инструмент делает написание кода дешевле, спрос на софт растёт быстрее, чем падает стоимость его производства. Так число программистов выросло с нескольких тысяч в начале пятидесятых до сотен тысяч в девяностные, миллионов в двухтысячные и десятки миллионов сегодня, и это несмотря на то, что современный разработчик с фреймворком, IDE, пакетным менеджером и поиском…
Иногда по ошибке выдавая за день столько, сколько его коллега из прошлого века писал дни и месяцы, потому что производительность обычного программиста выросла на порядки, и его занятость тоже выросла, потому что дешёвый код сделал выгодными проекты, которые раньше никто бы не начал. Так что если ваша интуиция подсказывает «инструмент делает работу за меня, значит работы станет меньше», то у Джевонса есть для вас плохие новости, которым сто шестьдесят лет.
Что меняется на самом деле
Из всего сказанного однако не следует, что не меняется ничего — меняется, и довольно сильно, просто не в ту сторону, которую мы видим. Уходит низ рынка в виде шаблонного кода, простых CRUD‑систем, верстки и генерации бойлерплейта, вся та работа, где решение уже известны и надо его напечатать. Тут нейронки реально хороши.
Но растёт верх в виде проектирования систем, понимания доменной области, отладки, оптимизации производительности (одна из областей где даже всемогущий Клод плавает аки топор и говноклодит, только успевай комиты реджектить), безопасности, и встраивания компонентов в системы, которые обязаны работать предсказуемо. Кто‑то же должен проверять, что нагенерил генератором генератор генератора? И этот кто‑то должен понимать Систему, нет уже даже не Код… глубже, чем тот, кто его сгенерировал, потому что что тот, кто его сгенерировал упирается в теорему Райса и работы Кампа.
Можно сказать, что граница «что умеет машина» сдвигается, и быстро, но граница «что нужно бизнесу» сдвигается ещё быстрее. Программисты в этой среде не исчезают, но у них меняется состав работы, теперь печатать ручками надо меньше, думать больше, и отвечать по‑прежнему за всё.
Бессмертно ли программирование
Языки программирования держит на плаву не синтаксис, привычки разработчика или сопротивление индустрии переменам, хотя сопротивления тоже хватает. Языки программирования решают задачу, для которой естественный язык (в какой бы инструмент его не обернули) в принципе не приспособлен, ни в виде схем, ни в виде md файлов или планов, ни в виде диалога с клодом. Язык программирования однозначно описывает поведение систем, которые обязаны работать предсказуемо.
Пока существуют системы, для которых «примерно правильно» означает потерю прибыли, времени или получение ущерба, а это примерно все банки, вся медицина, вся авиация, и возможно, большинство обычного бизнеса, то будет нужен формальный способ описать, что именно они должны делать. Этот формальный способ и есть язык программирования, как бы он ни выглядел к 2050 году, хоть текстом, хоть голосом, хоть мыслью напрямую из головы.
Машина, которая принимает «я хочу миллион долларов» и волшебным образом исполняет, это все еще фантастический сюжет начала прошлого века, а не инженерная реальность, потому что кому‑то придётся сказать машине, откуда эти деньги, в какой валюте, на какой счёт перевести и что делать, если вместо денег пришли ребятки в коротких пиджаках. Этот кто‑то и есть программист, разве что кроме случая с ребятками, независимо от того, печатает он transfer(amount, account) руками, общается с чатиком или диктует ассистенту голосом.
Я подвожу вас к выводу, что всегда было основой профессии программиста. Vibe coding не убрал необходимость точно формулировать задачу, а всего лишь сдвинул момент, когда вы платите за неточность формулировок. И получается, что проблему опять не решили, и решить её нельзя, но, как обычно, её можно вынести на уровень технического человека, только теперь его будут называть как‑то иначе Senior Opus Engineer, например, а лет через десять кто‑нибудь на Хабре напишет статью о том, откуда взялась новая профессия со своей зарплатной вилков. Согласны?
Автор: dalerank

