512kg / dima

A precise specification is already code

Dima ·

For decades the same prediction has come back again and again in software engineering: source code will disappear.

In the early years of computing, it was said that COBOL would let business managers develop software directly. In the 1980s, fourth-generation languages (4GL) promised to end the need for professional programmers. In the 1990s and 2000s, CASE tools and executable UML claimed that drawing diagrams would be enough for software to be built automatically from visual representations.

None of these promises came true.

We are now watching the most ambitious version of the same prediction. With the arrival of large language models (LLMs) and agent-based development environments, the story has changed: it is no longer diagrams that will replace code, but instructions written in natural language.

Some prominent figures in the industry argue that English has become the new programming language and that, in the near future, source code will be a historical relic. In this view, artificial intelligence will generate code as if it were an intermediate language, compile it and hide it from humans.

This debate featured prominently at the Future of Software Development Retreat, held in February 2026. Yet as the year goes on and the adoption of artificial intelligence grows, code repositories remain fundamental. Git is still the shared reference for storing, reviewing and versioning software.

Engineers use artificial intelligence intensively, but they use it to write, modify, refactor and understand more code, not to do without it.

Why is that?

The historical evolution of abstraction

To understand why code persists, we first have to understand what programming really means.

Programming is not simply typing characters into a text editor. It is a rigorous process of formalising thought: turning human intentions, often vague and ambiguous, into an explicit and deterministic model of execution.

For the last seventy years, the software industry has moved steadily towards higher levels of abstraction.

We started by plugging cables into control panels. Then came assembly language, structured languages such as C and, later, the object-oriented and functional paradigms represented by technologies such as Java, Python and TypeScript.

Each step made it possible to write software that was more readable, more understandable and more portable.

There is, however, a fundamental pattern: raising the level of abstraction has never eliminated code; it has only changed its form.

When we moved from assembly to C, we did not stop programming. We stopped worrying directly about processor registers in order to concentrate on structures such as loops and functions.

When we adopted modern frameworks, we stopped managing certain aspects of memory by hand in order to focus on business logic and domain models.

Generative artificial intelligence is the next logical step in this evolution. It works as a flexible, context-sensitive interface that sits above existing programming languages.

But reading AI as a technology destined to eliminate code means ignoring one of the fundamental constraints of any computer system: the need for precision.

The epistemological barrier: precision versus ambiguity

Human language is an extraordinary tool for collaboration precisely because it is flexible, ambiguous and dependent on context.

If I ask a colleague to build a checkout process that calculates sales tax automatically, they will probably understand the general goal. They will use what they know, ask which jurisdictions have to be covered and take into account the exceptional cases they consider relevant.

Computers, including those that use neural networks, need behaviour defined precisely at the boundaries of execution.

It is not a new objection. Edsger Dijkstra wrote it down around 1978 in “On the foolishness of ‘natural language programming’”: formal symbols are not a burden, but what rules out the nonsense that natural language lets through.

When we give an ambiguous instruction to a language model, it can generate syntactically correct fragments of code from probabilistic patterns learned during training.

For a standalone script or a simple helper function, this mechanism usually works very well.

The problem appears as the complexity of the system grows. As requirements and their interdependencies pile up, so does the number of situations that have to be considered.

The tax example is enough. “Calculate the VAT on the order” looks like a complete instruction. Three items at €0.35, at 21%:

from decimal import Decimal, ROUND_HALF_UP

def cents(x):
    return x.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)

prices, rate = [Decimal("0.35")] * 3, Decimal("0.21")

per_line = sum(cents(p * rate) for p in prices)   # 0.21
on_total = cents(sum(prices) * rate)              # 0.22
Fig. 1 — One sentence, two correct programs. The same order, three items at €0.35 with 21% tax, computed both ways in the page. Rounding each line gives €0.21; rounding the total gives €0.22. The instruction did not choose.

Both are correct readings of the sentence, and they differ by one cent. The sentence did not say whether to round per line or on the total, or with which rounding rule, and the program cannot leave it undecided. Someone decides: whoever writes the code, or the model in their place, without saying so.

To get an artificial intelligence to build a complex business system correctly from natural-language instructions, one would have to specify, among other things:

  • The exact rules for validating data.
  • The race conditions and the limits of concurrency.
  • The specific procedures for handling errors and alternative states.
  • The regulatory requirements and the parameters needed to guarantee compliance.

When we refine the instructions until every relevant ambiguity is gone and the AI no longer has to guess how the system should behave, we end up building a specification.

And here lies the central argument: a precise and unambiguous specification of a computer system fulfils, in essence, the same function as source code.

It does not matter whether it is written in Python, in a highly structured dialect of Markdown or as a set of strict logical assertions. If it precisely defines the behaviour a machine must execute, it is doing the job of code.

Abstraction can change the format of the specification, but it does not remove the need to define the behaviour of the system.

The symmetrical problems of speed, maintenance and security

It is beyond dispute that artificial intelligence has accelerated the production of code.

Tools such as GitHub Copilot, Windsurf and Cursor have gone from promising experiments to standard components of modern development environments.

In a controlled experiment, developers using Copilot completed one specific task, writing an HTTP server in JavaScript, 55.8% faster than the control group.

The opposite result exists too. In another trial, 16 experienced developers, working on mature open-source projects, took 19% longer when they were allowed to use AI, and still believed they had gone faster. The difference between the two results is the task: a new, isolated function versus a mature system that has to be understood before it is touched.

Writing code quickly is only a small part of the challenge of developing software.

There is a well-known maxim in engineering: code is read many more times than it is written.

The cost of understanding code

Imagine that an artificial intelligence generates 500 lines of code in three seconds from a short instruction.

Who is responsible for checking that those 500 lines are correct?

The developer has to review the result, understand how it works and verify that it meets the requirements.

Although AI models are effective at many low-level tasks, they can struggle with complex architectural decisions and with the overall design of systems.

If engineers start treating generated code as a black box they do not need to inspect, they give up an essential part of their ability to diagnose errors when the system fails under real conditions or grows in scale.

Generating code faster does not remove the work of understanding it. It can even move the effort from writing to reviewing, debugging and maintaining.

The dilemma of transparency and security

Hiding source code behind a layer of AI generation introduces significant risks for transparency and security.

Models can produce code with vulnerabilities that are not evident at first sight.

If we stop maintaining a codebase that is accessible, inspectable and under version control, we lose a fundamental tool for auditing software.

That makes it harder to detect vulnerabilities, to check licence compliance and to discover possible insertions of malicious code.

Source code provides an explicit record of the intended behaviour of the system and makes it possible to examine the changes made to it.

Although having source code does not by itself guarantee security, its accessibility makes review, auditing and the identification of errors easier.

Replacing the transparency of code with an opaque layer of automatic generation is therefore a risk that should not be ignored.

An architecture of collaboration between humans and artificial intelligence

Where does all this lead?

Source code is not disappearing, but our relationship with it is changing fundamentally.

We are gradually leaving a stage in which a developer’s work consisted largely of writing instructions by hand, and entering another in which their main role will be to design architectures, define requirements and review the results generated.

Instead of eliminating code, a model of collaboration is emerging in which each party takes on different tasks.

The developer defines the architecture, sets the intentions of the system, determines the domain models and supervises the important decisions.

Artificial intelligence acts as an assistant able to carry out repetitive tasks continuously: generating code structures, writing unit tests, proposing refactorings and speeding up the implementation of features.

In this model, source code continues to play an essential role.

It is the formal contract, stored and reviewed through a version control system, that connects human intentions with predictable execution by a computer.

Artificial intelligence can make the translation of those intentions into code enormously easier. But as long as systems need behaviour that is precise, verifiable and maintainable, there will have to be a formal representation in which to define and examine it.

The evolution of programming is not about eliminating code, but about raising the level of abstraction and changing the way humans produce it, understand it and maintain it.

Sources

  1. Thoughtworks (2026). Future of Software Development Retreat.
  2. Fowler, M. (2026). Future Of Software Development.
  3. Dijkstra, E. W. (c. 1978). On the foolishness of “natural language programming” (EWD 667).
  4. Peng et al. (2023). The Impact of AI on Developer Productivity: Evidence from GitHub Copilot.
  5. Becker et al. (2025). Measuring the Impact of Early-2025 AI on Experienced Open-Source Developer Productivity.