What Is Code?


History

Writing computer code has changed over time. The how, where, and when has evolved. In recent years, the software industry has rightly placed a huge emphasis on writing clean, readable, and maintainable code. This post explores the fundamental why behind this important trend. For experienced developers, this might seem obvious, but understanding these first principles is crucial context for those newer to the field.

We can trace the evolution of programming by going back in time. In modern times you can write a text file with instructions, feed it to an interpreter and the computer will execute those instructions. This is how Python, JavaScript and other scripting languages work. The code is interpreted in a runtime environment.

Before the advent of modern interpreters, code was compiled. Languages like Java, C# and Erlang compile source code to an intermediate representation, like bytecode. This bytecode is then executed by a virtual machine. This was a step towards platform independence.

Before that, languages like C and C++ were compiled directly into a binary representation that could be executed by the CPU. There was no virtual machine or interpreter. The compiled code was specific to the architecture of the machine it was compiled for.

Even before that, writing Assembly language used simple mnemonics to write down CPU machine instructions. These were then translated directly to the binary values that got stored in the memory and drove the computer.

Looking back, there is a clear progression to make things simpler for the people trying to make the computer do usefull tings. Assembly is easier than bit hacking, C is easier than Assembly, Java is more portable than C++ and so it continues. But the one thing that did not change is that the CPU still takes binary machine instructions from memory to make it go. Computer languages have not made computers smarter, it has allowed the operators to express more complicated ideas more easily.

Key Milestones

  • 1940s: Machine code and assembly language dominate
  • 1950s: FORTRAN and LISP introduce high-level abstraction
  • 1970s: C language enables system programming
  • 1990s: Java and JavaScript popularize object-oriented programming
  • 2010s: Rise of functional programming and domain-specific languages

Encoding Ideas

Computer code is not insructions for the computer. There is a long sequence of representations of ideas in modern code that eventually result in pure instructions for the CPU. But the code you write in Python, C#, Erlang, JavaScript etc is not that.

What the previous things lead to, is that computer source code is a way to express ideas. Usually in the form of instructions towards a desired outcome. This tool is quite sophisticated in expressing algorithms, states, checks, storing things and a myriad other things. But this expression is not what the computer actually works with, because it all gets reduced to machine instructions.

Computer source code is ultimately a structured human language that can be used to create machine instructions. But it is a language, which is a human thing, not a machine thing.

There are, of course, highly technical exceptions where the entire point is to optimize for the machine, but this is not the reality for most developers.

Literate Programming

The idea of code as a human language was championed by Donald Knuth in his “Literate Programming” paradigm, which argues that code should be written more for humans to read than for computers to execute.

Code Obfuscation

The concept of code as a human language becomes undeniable when we look at obfuscation. You can write code that is easy for other humans to read, or you can write code that is nearly impossible for them to read. From the perspective of the computer, both versions are identical. This highlights a key principle: you are primarily writing for the next human who will read your code, not just for the computer.

Here are two completely equivalent pieces of Javascript. The first is clear and readable by a human and the second is intentionally made difficult to read.

/**
 * Reverses an array using a standard for-loop.
 * @param {Array} arr - The array to reverse.
 * @returns {Array} A new, reversed array.
 */
function reverseWithForLoop(arr) {
  const reversedArray = [];
  for (let i = arr.length - 1; i >= 0; i--) {
    reversedArray.push(arr[i]);
  }
  return reversedArray;
}

// Example usage:
const originalArray = [1, 2, 3, 4, 5];
const reversedResult = reverseWithForLoop(originalArray);
// reversedResult is now [5, 4, 3, 2, 1]
// The same logic condensed onto a single line using chaining.
const reversedWithChaining = [1, 2, 3, 4, 5].map((_, i, a) => a[a.length - 1 - i]);

Large Language Models

This perspective on code as a human language offers a new way to think about Large Language Models (LLMs). The reason an LLM can write computer code is not because it possesses genuine intelligence, but because it is a master of manipulating language. Once you see that, the way you use the tool shifts. Don’t try to make it write code. Instead give it your ideas, insights and plans and let it give you new words for those things. Make sure the language it responds in is computer source code and suddenly it turns your simple axe into a chainsaw. But with great power comes great responsibility; you must still understand your tools and how they can fail.

Modern thinking tools are not tools that think for you. These are tools that help you to think; with language.

No comments yet. Be the first to share your thoughts!

Leave a Comment

This will be shown with your comment.
Maximum 2000 characters. HTML is not allowed.
Author's photo

About Heinrich Venter

A technology leader, he is passionate about mentoring developers and growing teams in learning environments that foster impactful solutions.