Richard Hamming · Chapter 4
A History
of Software
The Art of Doing
Science and Engineering
A discussion of Chapter 4. The chapter moves from programming directly in binary to the abstraction layers we use to express and discover what we want.
The illustrations are fictional, AI-generated editorial artwork from the earlier edition. The recurring character is the pocket terminal.
The chapter
Four threads
- 01Binary to abstraction
- 02Composition & reuse
- 03Language & its limits
- 04Programming as an art
Prescient commentary. Controversial takes. Quotes worth discussing.
The original framing: this is a longer chapter with many relevant topics, amazingly prescient commentary, and controversial takes. The discussion uses quotations with commentary on top.
Reveal the four threads one at a time. The last thread returns at the end: programming can help us discover the problem itself.
01 · Abstraction
Absolute binary
“In the beginning we programmed in absolute binary, meaning we wrote the actual address where things were in binary, and wrote the instruction part also in binary!”
Richard Hamming, The Art of Doing Science and Engineering, Chapter 4. The quotation is reproduced from the supplied discussion slides.
The burden includes both selecting an instruction and knowing the actual address of the relevant storage.
01 · Abstraction
Patching by detour
“If [you] wanted to insert some omitted instructions, then you took the immediately preceding instruction and replaced it by a transfer to some empty space.”
- 01
Jump outReplace the preceding instruction.
- 02
Run the patchOriginal instruction, then additions.
- 03
Jump backResume the main program.
“If [you] wanted to insert some omitted instructions, then you took the immediately preceding instruction and replaced it by a transfer to some empty space. There you put in the instruction you just wrote over, added the instructions you wanted to insert, followed by a transfer back to the main program”
Hamming, Chapter 4. The main slide shows an excerpt. This is the full quotation from the supplied slides.
The next discussion thread is the move from monolithic programs to procedures and functions. A patching detour illustrates control transfer, but does not by itself give us a reusable procedure.
01 · Abstraction
Symbolic instructions
ADD
01100101
“Someone got the idea a short piece of program could be written which would read in the symbolic names of the operations (like ADD) and translate them at input time to the binary representations used inside the machine (say 01100101).”
Hamming, Chapter 4. The binary value is Hamming's illustrative example, not an asserted opcode for a particular instruction set.
Symbolic instruction names reduce one burden. Symbolic addresses reduce another: a name can refer to storage without hard-coding its numeric location. Registers and stack variables are related conveniences, but symbolic addresses are not equivalent to either.
02 · Composition
Composability
Monolithic programs
Procedures
Functions
A small set of simple operations.
Complex behavior through composition.
The supplied slides propose “Composability as a general catalyst to emergence.” This is a discussion lens: small actions can combine repeatedly into complex behavior.
The progression is an organizing idea, not a claim that all software history followed a single linear path. What properties let primitives compose? What constraints stop them from composing?
01 · Abstraction
Virtual machines
“When, and only when, you have a totally virtual machine will you have the ability to transfer software from one machine to another without almost endless trouble and errors.”
Richard Hamming
Hamming, Chapter 4. Treat “when, and only when” as Hamming's strong claim to discuss. Portable behavior depends on the guarantees of the abstraction and whether the program stays within them.
The following slide uses “machine” broadly to invite examples of different abstraction surfaces. They are not all the same kind of virtual machine.
01 · Abstraction
Which machines
do we program?
What other successful
“virtual machines”
come to mind?
| Java | JVM |
|---|---|
| LLVM | IR & toolchain |
| Browsers | JavaScript engines |
| Ethereum | EVM |
| Python | Interpreter |
| Operating systems | Process & syscall interface |
Different abstractions. Different portability guarantees.
The supplied deck starts with Java/JVM and LLVM, then asks for more examples before revealing browsers, Ethereum/EVM, Python, and operating systems.
LLVM is a compiler infrastructure with an intermediate representation. An OS provides a process and system-call interface. They belong in a discussion of abstraction, but should not be equated with the JVM or EVM.
References: LLVM Project; Python glossary: interpreted. Names and examples otherwise follow the supplied deck.
02 · Composition
Canonical primitives
UNIX's organizing idea
Everything
is a file
“It’s all just
________
(and ________).”
Which set of primitives
do you find elegant?
The supplied slides discuss opinionated frameworks, the UNIX “everything is a file” idea, and finding a canonical set of primitives.
“Everything is a file” is an organizing maxim, not a literal claim that every operating-system resource has identical semantics. The question is about the power and cost of choosing a shared interface.
03 · Language
Thought & code
The language of
our thoughts.
The language of
the machine.
Is the gap a limitation of our languages,
or of how clearly we know what we want?
The supplied slides ask about closing the seemingly infinite gap between the language of our thoughts and the language of the machine's thoughts. Can we ever close it?
Pause after the question. One limitation can be the expressive language. Another can be the fact that we have not yet made our own intent precise.
03 · Language
Trusting
Trust
“To what extent should one trust a statement that a program is free of Trojan horses?”
“Perhaps it is more important to trust the people who wrote the software.”
Ken Thompson · Reflections on Trusting Trust
The source deck recommends Ken Thompson's Reflections on Trusting Trust and supplies the full quotation, split here into a question and an answer.
Ken Thompson, Communications of the ACM 27(8), 1984, pp. 761–763. Original article. Abstraction reduces what we need to know, while introducing dependencies we may need to trust.
03 · Language
Standardization
& individuality
We yearn to reduce uncertainty.
Too little structure
Anarchy.
Nothing composes.
Too much structure
Uniformity.
No room to differ.
When does a shared standard enable individuality,
and when does it suppress it?
The supplied slides frame uncertainty reduction as a fundamental human labor and place the extremes at “nihilism, anarchy” and “loss of individuality, pluribus!” The comparison on this slide is a discussion framing, not an empirical law.
A useful distinction to explore: a standard at the interface can make unlike parts work together. A standard imposed on the parts themselves can restrict their variation.
03 · Language
The expert’s blind spot
“That a language is easy for the computer expert does not mean it is necessarily easy for the non-expert…”
Hamming expected non-experts to do
the bulk of the programming.
“That a language is easy for the computer expert does not mean it is necessarily easy for the non-expert, and it is likely non-experts will do the bulk of the programming (coding, if you wish) in the near future.”
Hamming, Chapter 4. The slide splits the full quotation into an excerpt and a paraphrase of his prediction. This is his forecast, not a claim about current measured usage.
03 · Language
What language
do you reach for?
Where you have expertise
Go
Where you have no expertise
English
Ask the room first. Reveal Go, then English. These are the presenter's examples from the supplied slides, not a general prescription.
What does English let a non-expert express? Which details are left implicit? Does knowing the domain change the language we choose, or the precision we can achieve in it?
04 · Discovery
Programming
as discovery
“One trouble with much of programming is simply that often there is not a well-defined job to be done; rather, the programming process itself will gradually discover what the problem is!”
And that can be a good thing.
Hamming, Chapter 4. This full quotation is reproduced from the supplied slides. The presenter's response is “I think this is a good thing!”
Writing a program can force a vague intention to become concrete. The next slide ties this to Peter Naur's Programming as Theory Building.
04 · Discovery
Does the
process still
discover
the problem?
Peter Naur
Programming as Theory Building
The original closing question: “Does the ‘programming process’ still help discover the problem?”
Related reading: Peter Naur, Programming as Theory Building, Microprocessing and Microprogramming 15(5), 1985, pp. 253–261. Original article.
Naur argues that programming builds an understanding of how the problem is solved. A useful discussion question: when implementation becomes easier to delegate, which parts of that understanding still require our direct participation?