The earliest computers to ever be made were one of the most difficult pieces of electronics in human history. Vacuum tubes, excessive power consumption, and expensive runtime made these machines among the most demanding endeavours humanity ever engaged in.
Then came programming them. Punch cards, taped together, were used for storing code — or more accurately, raw instructions in binary.
Rear Admiral Grace Hopper, an American mathematician and US Navy officer, thought that repeatedly writing instructions for machines was tedious, and decided to improve upon reducing the tediousness of writing instructions. Hopper and her team developed the A-0, the first compiler for code, which took higher-level code readable (in a sense) to humans and converted it into machine-readable instructions. This was one of the first abstractions in computer science, and it was a revolution, allowing programmers to write considerably more complicated programs with expanded capability.
Next, Hopper conceptualised programming using words instead of mathematical symbols, developing FLOW-MATIC — an ancestor of COBOL, which still powers banking backbones worldwide today. This was another abstraction. It is easier to conceptualise and visualise programming when words are used instead of mathematical symbols. Then, instead of raw machine code, we could write programs in Assembly. And then the bigger leap was compiling programs from high-level programming languages to assembly, allowing programmers to write pure program logic without wrestling with individual CPU instruction cycles.
High-level languages like C or C++ compile into machine code directly, without users needing to manually orchestrate CPU instructions. Compilers for high-level languages are among the most important inventions of the modern era, allowing the software humanity relies on to run effectively on any architecture.
With massive gains in computational power, we could simplify high-level languages and their syntax even further, automating memory management along the way. Languages like Java and Python do not require developers to manually allocate and free memory, abstracting away yet another layer of complexity programmers once lived with.
The Arms Race Away from the Machine
Computer science, since its inception, has fundamentally been about abstraction — the systematic removal of unneeded complexity. The operating systems we rely on today were developed so users could run a variety of programs reliably on a machine without handling CPU registers or paging manually. Libraries were built so programmers never had to rewrite existing solutions, drastically accelerating development cycles. Today, it is almost expected to search for solutions using AI, or platforms like Stack Overflow before it, and integrate working patterns directly into projects.
Therefore, computer science has always been an arms race of who can engineer the better layer of abstraction so programmers worry less about the underlying machine:
Garbage Collection → eliminates manual memory management
Operating Systems → eliminate hardware-level orchestration
With every layer of abstraction, we remove another factor the programmer had to think about. Which brings us to the inevitable question: What if the programmer has no need to think about the program itself?
From Instructions to Intent
Most historical abstractions simplified or reduced the effort of writing instructions — but the human programmer still had to craft those instructions. This paradigm shifted with the advent of modern AI and Large Language Models (LLMs), which predict text conditioned on vast corpuses of data. With sufficient scale, these models demonstrate capabilities that parallel human cognition. Whether an LLM “thinks” in the human sense remains a matter of deep philosophical debate; practically speaking, with adequate training, the model is smart enough.
Consequently, AI models can indeed write code and automate tasks across wide ranges of intellectual complexity. Programming using AI has rapidly expanded, with entire software systems being implemented with minimal direct human coding. AI is, in essence, an abstraction for producing the instructions themselves.
It is therefore not radical to view AI as simply another layer in the long genealogy of abstraction in computer science — abstracting away the very need to write code syntax for the machine. With AI, a human specifies an intended function or outcome, and the model constructs the implementation.
Moving the Complexity
The machine has progressively receded from the programmer's immediate awareness: first its individual binary gates, then its registers and memory, then its hardware architecture, and now, increasingly, the syntax of the software itself. AI pushes this progression one step further by allowing humans to specify an outcome without specifying the explicit program that produces it.
But abstraction does not make underlying complexity disappear. It merely moves it somewhere else.
A developer working in a high-level language does not need to understand machine opcodes, but the compiler still must. A Python developer does not manually free pointers, but the runtime still does. An AI user may not write the code, but the code, compiler, operating system, and silicon still operate beneath the prompt.
Perhaps this is the defining characteristic of computer science: we do not eliminate complexity. We keep moving it further away from the human.
And if that is true, AI may not be the end of the abstraction ladder. It may simply be the newest rung. The machine was abstracted into software. Software was abstracted into languages and interfaces. And now, software itself is being abstracted into pure intent.
The interesting question is no longer: how much can we abstract? It is what happens when we eventually forget what lies beneath the abstractions.