The post has been translated automatically. Original language: Russian
Most modern development tools try to speed up writing code.
New IDEs.
Auto-completion.
Function generation.
AI assistants.
They all answer the same question.:
How to write code faster?
But almost forty years ago, Danish scientist Peter Naur proposed an idea that is becoming more important today than the speed of generation.
He claimed that the program is not the source code.
The program is a theory.
The source code is just one of the possible implementations of this theory.
When I first got acquainted with this idea, it seemed too philosophical.
But during the development of the Memora8 processor, the Reganta OS operating system, and the Sekura JS programming language, it became clear that it best explained the main problem of complex engineering projects.
The code stores the implementation. But not an engineering solution.
Imagine that in three years you open your own repository.
You have tens of thousands of lines of code in front of you.
You can figure out how the function works.
You can trace the chain of calls.
An error can be found.
But it is almost impossible to answer other questions.
Why is architecture designed this way?
Why was this algorithm chosen?
Why did you abandon the alternative solution?
Why does the processor instruction look that way?
Why does the module interact with the system through this interface?
Why did the language get exactly this kind of semantics?
Git stores the file history perfectly.
But it almost does not preserve the history of engineering thinking.
This is where the code ends and the theory begins.
The most expensive part of development
During the development of Memora8, we noticed an interesting pattern.
The most expensive part of the project is not writing code.
The most expensive part is making an architectural decision.
Almost every major change starts the same way.
An idea appears.
It is being discussed.
Restrictions are checked.
Alternatives are being considered.
Counterarguments are emerging.
Some of the solutions are immediately discarded.
Sometimes the discussion takes several hours.
Sometimes for several days.
Sometimes it becomes clear that the original idea was wrong.
And only after that, the implementation begins.
It turns out a strange situation.
The most valuable work has already been done.
But only the code gets into the repository.
The whole logic of decision-making remains in the history of discussions or in the memory of engineers.
After a year, most of this information disappears.
What has changed with the advent of LLM
Large language models have unexpectedly changed this process.
Today, an engineer can discuss an architectural idea in much the same way he used to discuss it with colleagues.
You can ask them to find weak points.
You can test the hypothesis.
Alternative options can be considered.
You can try to prove to yourself that the chosen solution is really better than the others.
But here comes a new problem.
If the discussion remains only in the chat history, it will have to be conducted again after a few months.
It turns out a paradox.
LLMs help you think faster.
But the results of thinking begin to get lost again.
Why Chat History Doesn't become Engineering Knowledge
At first glance, it seems that it is enough to keep the correspondence.
But a long dialogue contains everything at once.
The first idea.
Erroneous assumptions.
Unsuccessful options.
Intermediate conclusions.
Contradictions.
And only somewhere in the end there is a final solution.
After a few months, the engineer has to reread dozens of pages again to understand which conclusion turned out to be correct in the end.
The history of discussion is a process of thinking.
But an engineering system needs the result of thinking.
That is why there is another mandatory step between the dialog and the code.
A new development cycle
While working on Noda, we gradually came to a new development cycle.
It looks like this:
Idea → Discussion with LLM → Canonical article in Noda → Implementation → Analysis → Fix the canon or fix the code → Next iteration
At first glance, the scheme seems simple.
But there is a fundamentally new question in it.
After the analysis, we ask not:
How can I fix the code?
But:
What turned out to be wrong — the implementation or the theory itself?
These are two completely different situations.
If the theory is correct, the code changes.
If the theory turns out to be incomplete or erroneous, the canon is changed first.
And only after that the implementation changes.
It turns out that theory becomes a full-fledged engineering artifact.
The canon appears before the code
Traditional documentation appears after development.
Sometimes after a few days.
Sometimes after a few months.
Sometimes never.
In the new process, the opposite is true.
After the discussion, a canonical article appears.
It records the engineering decision made.
And only after that, the implementation begins.
It turns out an interesting role reversal.
Documentation ceases to be a progress report.
It becomes the starting point of development.
Why the canon?
We've been trying to use a regular Wiki for a long time.
Markdown.
Technical documents.
Specifications.
But a familiar problem arose very quickly.
Several versions of the same solution appeared.
Drafts.
Outdated articles.
Documents that no one understood anymore, whether they were relevant or not.
As a result, the team started asking each other questions again.
We have come to the conclusion that it is not the documents that need to be stored.
You need to keep current engineering knowledge.
There is one canonical article for each architectural issue.
It becomes part of the general theory of the system.
Everything else is history.
The role of Noda in the new process
In this model, each tool gets its own task.
LLM helps to explore the solution space.
An engineer makes an architectural decision.
Noda turns this decision into canonical knowledge.
The code implements the canon.
Tests and analysis verify the compliance of the implementation with the accepted theory.
It turns out that Noda does not replace Git.
And it does not replace ChatGPT.
She connects them.
Git answers the question:
What has changed in the code?
Noda answers the question:
Why has the engineering solution changed?
LLM helps to discuss both.
This turned out to be especially interesting for single-player development.
When you work alone, it seems that there is simply no one to discuss architecture with.
That is why many decisions are made too quickly.
The advent of LLM has unexpectedly changed this situation.
Now you can spend hours discussing architecture.
Test hypotheses.
Argue.
Look for weak points.
But one thing is important to understand.
An LLM does not become an architect.
She doesn't make a decision.
class="paragraph"> It helps to explore the space of options.The final choice is made by the engineer.
After that, the decision becomes canon.
It is the canon that becomes the basis for further development.
It turns out a new working cycle of a single engineer:
Problem → Discussion with LLM → Canon → Implementation → Analysis → Correction of canon or implementation → Next iteration
In fact, the LLM becomes the most patient interviewee an engineer has ever received.
An example from the development of Memora8
Suppose an idea arises to change the mechanism of operation of a single processor instruction.
Previously, you could immediately open the editor and start changing the HDL.
The process looks different today.
First, the idea itself is discussed.
What consequences will it cause?
How will the ISA change?
Will this affect the compiler?
Do I need to change Sekura JS?
Will the change affect the Firmware Kernel?
After the discussion, a canonical article appears.
It is she who fixes the final decision.
Only then does the implementation begin.
Further analysis is carried out.
If a problem is found in the implementation, the code is corrected.
If the analysis shows that the architectural solution itself turned out to be erroneous, the canon changes.
After that, a new iteration begins.
It turns out that practice checks not only the code.
It tests the theory of the system itself.
Code and theory begin to evolve together
Traditionally, it is believed that documentation must match the code.
The new cycle works differently.
The code must conform to the canon.
But the canon must also stand up to the test of practice.
We get constant feedback.
Theory creates code.
The code verifies the theory.
If the theory has passed the test, the implementation develops.
If not, the theory itself develops.
That is why the canon ceases to be a static document.
It becomes a living part of the engineering process.
Peter Naur turned out to be surprisingly modern
When Naur wrote that a program is a theory, Git did not exist.
There were no cloud services.
There were no big language models.
The theory really lived only in the developer's head.
The situation has changed today.
LLMs help an engineer explore ideas.
Noda allows you to save the outcome of the discussion as canonical engineering knowledge.
The code becomes an implementation of the accepted theory.
And analysis allows you to develop both the code and the canon itself at the same time.
It turns out to be a completely new development cycle.
Not:
Code → Documentation.
But:
Idea → Discussion → Canon → Code → Analysis → Correction of the canon or code → The next iteration.
Instead of output
We used to consider the source code as the main result of development.
But perhaps this is no longer true.
The main result is an engineering solution.
LLMs help to formulate it.
Noda helps to preserve it.
The code helps to implement it.
And practice helps to test it.
Perhaps this is the main change that big language models have brought to software development.
They taught us how to write code faster.
But something else is much more important.
They have made possible a new engineering process in which the main object of development is not the program, but the knowledge from which this program is born.
Большинство современных инструментов разработки пытаются ускорить написание кода.
Новые IDE.
Автодополнение.
Генерация функций.
AI-ассистенты.
Все они отвечают на один вопрос:
Как быстрее написать код?
Но почти сорок лет назад датский ученый Питер Наур предложил мысль, которая сегодня становится важнее скорости генерации.
Он утверждал, что программа — это не исходный код.
Программа — это теория.
Исходный код — лишь одна из возможных реализаций этой теории.
Когда я впервые познакомился с этой идеей, она показалась слишком философской.
Но во время разработки процессора Memora8, операционной системы Reganta OS и языка программирования Sekura JS стало понятно, что именно она лучше всего объясняет главную проблему сложных инженерных проектов.
Код хранит реализацию. Но не инженерное решение.
Представьте, что через три года вы открываете собственный репозиторий.
Перед вами десятки тысяч строк кода.
Можно разобраться, как работает функция.
Можно проследить цепочку вызовов.
Можно найти ошибку.
Но практически невозможно ответить на другие вопросы.
Почему архитектура устроена именно так?
Почему был выбран этот алгоритм?
Почему отказались от альтернативного решения?
Почему инструкция процессора выглядит именно таким образом?
Почему модуль взаимодействует с системой через этот интерфейс?
Почему язык получил именно такую семантику?
Git прекрасно хранит историю файлов.
Но почти не хранит историю инженерного мышления.
Именно здесь заканчивается код и начинается теория.
Самая дорогая часть разработки
Во время разработки Memora8 мы заметили интересную закономерность.
Самая дорогая часть проекта — это не написание кода.
Самая дорогая часть — принятие архитектурного решения.
Практически каждое серьезное изменение начинается одинаково.
Появляется идея.
Она обсуждается.
Проверяются ограничения.
Рассматриваются альтернативы.
Появляются контраргументы.
Часть решений сразу отбрасывается.
Иногда обсуждение занимает несколько часов.
Иногда несколько дней.
Иногда становится понятно, что первоначальная идея вообще была ошибочной.
И только после этого начинается реализация.
Получается странная ситуация.
Самая ценная работа уже выполнена.
Но в репозиторий попадает только код.
Вся логика принятия решения остается в истории обсуждений или в памяти инженеров.
Через год большая часть этой информации исчезает.
Что изменилось с появлением LLM
Большие языковые модели неожиданно изменили этот процесс.
Сегодня инженер может обсуждать архитектурную идею практически так же, как раньше обсуждал ее с коллегами.
Можно попросить найти слабые места.
Можно проверить гипотезу.
Можно рассмотреть альтернативные варианты.
Можно попытаться доказать самому себе, что выбранное решение действительно лучше остальных.
Но здесь появляется новая проблема.
Если обсуждение остается только в истории чата, через несколько месяцев его придется проводить заново.
Получается парадокс.
LLM помогают быстрее думать.
Но сами результаты размышлений снова начинают теряться.
Почему история чата не становится инженерным знанием
На первый взгляд кажется, что достаточно сохранить переписку.
Но длинный диалог содержит все сразу.
Первую идею.
Ошибочные предположения.
Неудачные варианты.
Промежуточные выводы.
Противоречия.
И только где-то в конце появляется окончательное решение.
Через несколько месяцев инженер снова должен перечитывать десятки страниц, чтобы понять, какой вывод в итоге оказался правильным.
История обсуждения — это процесс мышления.
Но инженерной системе нужен результат мышления.
Именно поэтому между диалогом и кодом появляется еще один обязательный этап.
Новый цикл разработки
Во время работы над Noda мы постепенно пришли к новому циклу разработки.
Он выглядит так:
Идея → Обсуждение с LLM → Каноническая статья в Noda → Реализация → Анализ → Исправить канон или исправить код → Следующая итерация
На первый взгляд схема кажется простой.
Но в ней есть принципиально новый вопрос.
После анализа мы спрашиваем не:
Как исправить код?
А:
Что оказалось неверным — реализация или сама теория?
Это две совершенно разные ситуации.
Если теория правильная, меняется код.
Если теория оказалась неполной или ошибочной, сначала изменяется канон.
И только после этого меняется реализация.
Получается, что теория становится полноценным инженерным артефактом.
Канон появляется раньше кода
Традиционная документация появляется после разработки.
Иногда через несколько дней.
Иногда через несколько месяцев.
Иногда никогда.
В новом процессе все наоборот.
После обсуждения появляется каноническая статья.
Она фиксирует принятое инженерное решение.
И только после этого начинается реализация.
Получается интересное изменение ролей.
Документация перестает быть отчетом о проделанной работе.
Она становится исходной точкой разработки.
Почему именно канон
Мы долго пытались использовать обычную Wiki.
Markdown.
Технические документы.
Спецификации.
Но очень быстро возникала знакомая проблема.
Появлялось несколько версий одного решения.
Черновики.
Устаревшие статьи.
Документы, которые никто уже не понимал, актуальны они или нет.
В результате команда снова начинала задавать вопросы друг другу.
Мы пришли к выводу, что хранить нужно не документы.
Хранить нужно действующее инженерное знание.
Для каждого архитектурного вопроса существует одна каноническая статья.
Именно она становится частью общей теории системы.
Все остальное — история.
Роль Noda в новом процессе
В этой модели каждый инструмент получает собственную задачу.
LLM помогает исследовать пространство решений.
Инженер принимает архитектурное решение.
Noda превращает это решение в каноническое знание.
Код реализует канон.
Тесты и анализ проверяют соответствие реализации принятой теории.
Получается, что Noda не заменяет Git.
И не заменяет ChatGPT.
Она соединяет их.
Git отвечает на вопрос:
Что изменилось в коде?
Noda отвечает на вопрос:
Почему изменилось инженерное решение?
LLM помогает обсуждать оба.
Особенно интересно это оказалось для одиночной разработки
Когда работаешь один, кажется, что обсуждать архитектуру просто не с кем.
Именно поэтому многие решения принимаются слишком быстро.
Появление LLM неожиданно изменило эту ситуацию.
Теперь можно часами обсуждать архитектуру.
Проверять гипотезы.
Спорить.
Искать слабые места.
Но важно понимать одну вещь.
LLM не становится архитектором.
Она не принимает решение.
Она помогает исследовать пространство вариантов.
Окончательный выбор делает инженер.
После этого решение становится каноном.
Именно канон становится основой дальнейшей разработки.
Получается новый рабочий цикл одиночного инженера:
Проблема → Обсуждение с LLM → Канон → Реализация → Анализ → Исправление канона или реализации → Следующая итерация
Фактически LLM становится самым терпеливым собеседником, которого когда-либо получал инженер.
Пример из разработки Memora8
Предположим, появляется идея изменить механизм работы одной инструкции процессора.
Раньше можно было сразу открыть редактор и начать менять HDL.
Сегодня процесс выглядит иначе.
Сначала обсуждается сама идея.
Какие последствия она вызовет?
Как изменится ISA?
Повлияет ли это на компилятор?
Нужно ли менять Sekura JS?
Затронет ли изменение Firmware Kernel?
После обсуждения появляется каноническая статья.
Именно она фиксирует окончательное решение.
Только после этого начинается реализация.
Дальше проводится анализ.
Если проблема обнаружена в реализации — исправляется код.
Если анализ показывает, что ошибочным оказалось само архитектурное решение, изменяется канон.
После этого начинается новая итерация.
Получается, что практика проверяет не только код.
Она проверяет саму теорию системы.
Код и теория начинают развиваться вместе
Традиционно считается, что документация должна соответствовать коду.
Новый цикл работает иначе.
Код должен соответствовать канону.
Но и канон должен выдерживать проверку практикой.
Получается постоянная обратная связь.
Теория рождает код.
Код проверяет теорию.
Если теория выдержала проверку, развивается реализация.
Если нет — развивается сама теория.
Именно поэтому канон перестает быть статичным документом.
Он становится живой частью инженерного процесса.
Питер Наур оказался удивительно современным
Когда Наур писал, что программа — это теория, не существовало Git.
Не существовало облачных сервисов.
Не существовало больших языковых моделей.
Теория действительно жила только в голове разработчика.
Сегодня ситуация изменилась.
LLM помогают инженеру исследовать идеи.
Noda позволяет сохранить итог обсуждения как каноническое инженерное знание.
Код становится реализацией принятой теории.
А анализ позволяет развивать одновременно и код, и сам канон.
Получается совершенно новый цикл разработки.
Не:
Код → Документация.
А:
Идея → Обсуждение → Канон → Код → Анализ → Исправление канона или кода → Следующая итерация.
Вместо вывода
Мы привыкли считать исходный код главным результатом разработки.
Но, возможно, это уже перестает быть правдой.
Главным результатом становится инженерное решение.
LLM помогают его сформулировать.
Noda помогает его сохранить.
Код помогает его реализовать.
А практика помогает его проверить.
Возможно, именно в этом и заключается главное изменение, которое большие языковые модели принесли в разработку программного обеспечения.
Они научили нас быстрее писать код.
Но гораздо важнее другое.
Они сделали возможным новый инженерный процесс, в котором главным объектом разработки становится не программа, а знание, из которого эта программа рождается.