Why English will never be a programming language
Learn how to respond when your CFO asks, "why are our devs still writing code?"
In my last post, I argued why you should still type code by hand. If you aren't writing code, you're programming in English (or German, Chinese, etc.) and asking an LLM to translate. Businesses love that idea because a lot more people speak English than write JavaScript and will work at overseas call center rates. Read on to learn why that won't work.
The spec for an email address. A precise spec is just code.
Thoughtworks is a software consultancy that developers and business execs look to for practical guidance in software engineering. In February, some of them got together1 to discuss coding with LLMs. There, someone asked this question2:
What would have to be true for us to ‘check English into the repository’ instead of code?
I felt disappointed to hear expert software practitioners considering this question, because it will be about thirty seconds before it is reframed as a LinkedIn post confidently proclaiming that code is dead. After that, it will be two minutes before your CFO posts it in a chat with your manager.
I'll grant that code is a cost center. Each line is a recurring operational expense that climbs for the life of the product. Just look at the pink line from my recent post on software failures. You can mentally substitute "failures" with "cost":
The cost of software maintenance is spiky and rises over time.
Your CFO would gladly shed this expense, and he hopes that LLMs are that golden ticket. You can stop this train wreck if you know where the railroad switch is. The language your leaders hear can switch the trajectory of the business before it careens off the cliff of LLM dependence and layoffs.
Below, you'll learn precisely what would have to be true for businesses to program purely in English, do away with those cumbersome programming languages, and fire those expensive programmers.
How the software sausage is made
In order to understand what it would take to replace code, we need to know the role that code plays when creating software. Let's start with a simplified model of software development:
[specification] ---> [code] ---> [executable] ---> [program] ---> [test]
The model above intentionally ignores details like iteration and feedback. Let's look at the transition between each step.
From spec to code
In general, software developers take a specification and turn it into code.
A spec describes, in language that a broad audience can understand, what the software must do or not do. It consists of one or more requirements. Here's an example requirement:
The app SHALL page the on-call engineer if the server is down or the response is slow and it's during business hours.
Creating a good spec can be difficult. Let's remember Brooks' wisdom that producing the spec is the hard part, not implementation:
The hardest part of the software task is arriving at a complete and consistent specification, and much of the essence of building a programi is in fact the debugging of the specification
-- Fred Brooks, No Silver Bullet, 1986
I already demonstrated Brooks' point. The paging requirement above is ambiguous. Did you notice? Look again.
To turn the paging rules above into code, a dev has to disambiguate between two possible meanings:
- Never page outside work hours:
(server_down OR response_slow) AND business_hours - Always page on outages, and only page on slowness during work hours:
server_down OR (response_slow AND business_hours)
Unlike English, code is an unambiguous language. To express the paging rules above in C, Python, or JavaScript, a programmer has to choose one of the precise interpretations. If they leave off the parentheses, the language's operator precedence rules determine which of OR and AND gets evaluated first.
Choosing the correct interpretation requires a conversation with someone who knows what the software is supposed to do.
Spec is legible; code is precise
You might think, "What idiot wrote that vague requirement?", but before you judge, remember that specs are imprecise on purpose. Precision and legibility are opposing attributes. "Ensure the email address is valid" is legible, but ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$ is precise. Both levels are necessary; one communicates intent, the other actually does the work. Similarly, "Round to two decimals" is legible, but the IEEE 754 rules for rounding occupy an 84-page document3.
It is of course possible to write a specification in English that contains no ambiguity. The cost of producing it would be greater than the cost to produce the equivalent code. That's because there's no program checking syntax and enforcing a type system. For example, I've read plenty of spec documents that used terms they did not define. Without some kind of automated correctness check, a precise English specification is likely to accumulate omissions and inconsistencies over time. This is especially likely for multiple documents made by multiple contributors.
Let's pretend that some organization succeeded in creating a software specification that is precise enough to replace code. The language of that document would be hard to read for the same reasons that code is hard to read. As others have said, "a sufficiently detailed spec is just code."4
From code to executable
Once we have some code, a program called a compiler reads the code and outputs an executableii. An executable is a file that contains the data and sequence of instructions that work on a specific processor.
The transformation from code to executable is deterministic: the compiler will always output the same executable, given the same code. We'll come back to that in a moment.
From executable to program
Once we have an executable, we can load it into memory and run it. We call that a program. Once we can run a program, we can test it in two ways:
Verification. We ask "Did we build the thing right?" We check if the code implements the spec. It can be done with manual interaction with the program, but it's best to use automated tests because humans are not fast or consistent.
Validation. We ask "Did we build the right thing?" We hand the executable to the user and ask for feedback. This pits the user's expectations against both the spec and code. Any of the three can change as a result.
How to replace code with English
Let's assume for the sake of argument that LLMs actually can parse English specifications, even ambiguous ones, and output the equivalent code that devs would. In that universe, we would delete the code and only store the spec in source control:
[specification] ---------------> [executable] ---> [program] --> [test]
On each build, the LLM would generate the code, build the executable, and run the tests. Then it would discard the code it had generated.
We do not live in that universe.
LLMs can't always resolve ambiguity. If the spec has issues, they'll need clarification, just like devs do. You'll be lucky if they ask for it. Do you want your deploy to prod to stop while an LLM waits for an email reply?
LLMs are not generally deterministic. I promised we'd circle back to this topic. If you give an LLM the same prompt twice, you'll get different output. This presents a problem for verification and validation. Since the artifact changes with each build even if the spec did not, the tests must validate a range of valid specs rather than just one. It's like hitting a bullseye with a bow and arrow. The more the tests constrain the set of executables that will pass, the harder the LLM has to work.
There's no opportunity to inspect the code the LLM generated and no value of doing so, since on each run it is different. This places further load on the test suite for proving correctness.
In light of these facts, here's what would have to be true to use English in the place of programming languages:
-
The specification would have to be unambiguous. It would be pedantic English that makes C++ look pleasant.
-
The tests would need to be comprehensive, automated, and epistemologically sound.
-
Tests serve as a forcing function that constrain the executable to one that satisfies the spec.
-
The tests have to actually verify the executable meets the spec.
Do you ask the LLM to write a test, then review the test, run it, and see it fail? Then stage the code changes? Then ask the LLM to pass the test? Then verify that the LLM did not change the test while passing it? Review the additional code change? Commit and repeat? If so, this sounds epistemologically sound. 5
-
The tests have to be written in code. If you write them in English and ask the LLM to generate test code, the bullseye moves on each build. Moreover, what verifies the generated tests?
-
-
The LLM would need to be deterministic, or your budget must be ready to absorb massive token spend. That's because on each CI run, the LLM would iterate in a test-edit loop until the tests pass.
The industry already tried to code in English
In the 1960s, the industry adopted two languages that look like English.
The hope behind COBOL was that business analysts would be able to implement their ideas without programmers.
ADD OVERTIME-HOURS TO TOTAL-HOURS GIVING WEEKLY-HOURS ROUNDED.
The above code can be expressed in JavaScript as const weeklyHours = Math.round(overtimeHours + totalHours);. The cosplay didn't protect workers from having to think hard and understand the problem they were solving.
Today, the small priesthood of surviving COBOL programmers are remunerated with airdrops of cash to keep the core of the world's banking infrastructure running.
SQL had similar goals. The query below looks friendly enough, but debugging it requires knowledge of set theory, query planners, indexes, and idiosyncrasies of the SQL flavor. These days, DBAs easily earn six figures.
SELECT FROM orders WHERE status = 'cancelled' AND created_at < '2025-01-01';
Edsger Dijkstra was probably to computer science what Einstein was to physics. The emergence of English-like languages caused him to pen a rather forceful essay6 which can be summed up with this sentence:
some still seem to equate "the ease of programming" with the ease of making undetected mistakes.
What to tell your CFO
Here's what you can tell your CFO when he asks why we still have devs on payroll:
Code is already the cheapest path to working, correct software. LLMs do not change the calculus because figuring out what to make is the expensive part, not coding it up. Skipping code makes the specification of what to make even more expensive and throws away the tools that keep precision affordable. Programming in English would be more expensive than just using a programming language.
Bookmark this page or save this paragraph. You'll need it soon enough.
Further reading
If this post clicked with you, I drum a similar beat about business, coding, and LLMs:
- AI: Accelerated Incompetence: "In software engineering, over-reliance on LLMs accelerates incompetence."
- LLMs are not Bicycles for the Mind: "LLMs are more like E-bikes. More assist makes you go faster, but provides less exercise"
- Who wins in an Arms Race?: "In a competitive landscape, LLMs, like supershoes, do not result in your benefit"
- Why you should still type code in 2026: "When you type code by hand, you get the best of LLMs without losing your coding skills"
Footnotes
- Historically, the industry used the term program as shorthand for program text, what today we call source code.
- I'm ignoring interpreted languages like JavaScript and Python. They aren't compiled. They produce the executable the moment you want to run it. I'm also ignoring languages that compile to intermediate representations, like Java or C#. These details don't matter for this discussion.