Programmeren in absoluut binair
De eerste programmeurs schreven in absoluut binair: elke instructie & elk geheugenadres in ruwe binaire cijfers. Een enkele instructie zag er bijvoorbeeld uit als 01100101 00001010 — instructiecode & geheugenadres in binair.
Het spaghettie-code-probleem
Toen een fout het invoegen van een nieuwe instructie vereiste, stonden programmeurs voor een dilemma. Invoegen ter plaatse betekende dat elk volgend instructieadres met één verschoof — wat vereiste dat de programmeur elke adresverwijzing in het gehele programma bijwerkte. Catastrofaal.
De oplossing: vervang de instructie net voor het invoegpunt met een sprong naar leeg geheugen. Op die lege locatie: schrijf de overschreven instructie, voeg de nieuwe instructies toe, spring dan terug. Toen fouten in de correcties verschenen, pas dezelfde truc opnieuw toe met ander leeg geheugen.
Resultaat: het uitvoeringspad door het programma sprong naar ogenschijnlijk willekeurige locaties. Hamming noemde dit 'een blikje spaghetti.' Het controlestroom-pad, op papier getekend, zag er precies uit als verstrengelde spaghetti.
De ontsnappingsroutes
Twee onmiddellijke verbeteringen: octale notatie (groepeer binaire cijfers in groepen van 3) en hexadecimaal (groepen van 4, met A–F voor waarden boven 9). Deze reduceerden schrijffouten maar losten het fundamentele adresprobleem niet op.
Symbolische assembler (bijv. IBM's SAP — Symbolic Assembly Program — en SOAP — Symbolic Optimizing Assembly Program op de IBM 650) stelde programmeurs in staat instructienamen (ADD, MOVE) & symbolische adresetiketten in plaats van binair te schrijven. De assembler vertaalde bij invoer naar binair, beheerde adrestoewijzingen automatisch.
SOAP voerde een extra optimalisatie uit: het rangschikt instructies op de roterende trommel zodat de volgende instructie op de leeskop arriveerde net toen de vorige voltooid was — minimale latencie-codering. SOAP compileerde zelfs zichzelf: programma A verwerkt als gegevens om B te produceren, B op A uitgevoerd om te meten hoeveel zelf-compilering het verbeterde.
Bibliotheken & verplaatsbare code
Hamming merkte op dat het idee van herbruikbare software (wiskundige bibliotheken) zeer vroeg ontstond — Babbage had het bedacht. Het probleem: een bibliotheek met absoluut adres vereiste dat elke routine dezelfde geheugenlocaties innam telkens wanneer deze werd gebruikt. Toen de totale bibliotheek te groot groeide, concurreerden programma's om dezelfde adressen.
De oplossing: verplaatsbare code. De assembler genereert instructies die geheugen relatief refereren — offsets vanaf een basisadres — in plaats van absolute adressen. Een linker lost de uiteindelijke adressen bij laadtijd op.
Von Neumann's onuitgegeven rapporten (ruim verspreid) beschreven de noodzakelijke programmeertrucs. Het eerste gepubliceerde programeerboek (Wilkes, Wheeler & Gill, EDSAC, 1951) codificeerde deze technieken.
De taalontwerp-splitsing
FORTRAN (1957, IBM) & ALGOL (1958, internationaal comité) vertegenwoordigen twee ontwerpfilosofieën die radicaal verschillende resultaten produceerden.
FORTRAN
John Backus leidde het FORTRAN-project (FORmula TRANslation) bij IBM. Het ontwerpoogmerk: maak de taal gemakkelijk te gebruiken voor wetenschappers & ingenieurs. FORTRAN accepteerde wiskundige notatie die voelde voor de gebruikers: A = B + C * D in plaats van ADD B, C; STORE T; MULTIPLY T, D; STORE A.
FORTRAN overleefde 60+ jaar. Het blijft actief gebruikt in wetenschappelijk rekenen, vloeistofdynamica, klimaatmodellering, & computationele fysica. Hamming merkte deze duurzaamheid op als bewijs van succesvol ontwerp.
ALGOL
ALGOL (ALGOrithmic Language) werd ontworpen door een comité van logici & informaticawetenschappers met het doel wiskundige nauwkeurigheid: een logisch schone, formeel definieerbare taal. De Backus-Naur Form (BNF)-notatie voor het beschrijven van grammatica's werd uitgevonden om ALGOL op te geven.
ALGOL mislukte in de praktijk. Ondanks zijn logische elegantie & zijn enorme invloed op volgende taalontwerp (Pascal, C, & vrijwel elke moderne taal stammen uit ALGOL's grammaticaconcepten), werd ALGOL zelf nooit veel ingezet. Hamming's vonnis: logisch ontworpen, voor mensen onbruikbaar.
De hiërarchie van talen
Hamming beschreef een natuurlijke hiërarchie van machinecode via assembler, talen op hoger niveau, & uiteindelijk een 'probleemgerichte taal' dicht bij hoe beoefenaars hun probleemdomein denken. Elk niveau voegt menselijke leesbaarheid toe ten koste van machine-efficiëntie.
Hamming's vier taalontwerpcriteria
Hamming destilleerde de les van FORTRAN vs ALGOL tot vier criteria voor een succesvolle programmeertaal:
1. Gemakkelijk te leren — een beginner kan snel productief worden
2. Gemakkelijk te gebruiken — alledaagse taken vereisen minimale formaliteit
3. Gemakkelijk te debuggen — fouten produceren betekenisvolle, localiseerbare berichten
4. Gemakkelijk subroutines te gebruiken — hergebruik & abstractie vereisen geen superhuman moeite
Hij voegde een structuurlopmerking toe: menselijke taal draagt ongeveer 60% redundantie; geschreven taal ongeveer 40%. Talen met lage redundantie (zoals APL) produceren elegante eenliners die experts mooi vinden & beginners ondoorzichtig — & die ondetecteerbare fouten bevatten wanneer een enkel teken betekenis verandert.
De implicatie: een taal ontworpen voor logische elegantie optimaliseert voor de verkeerde lezer. De programmeur is menselijk; mensen hebben redundantie nodig om fouten op te vangen & intentie te communiceren.
Psychologisch vs logisch taalontwerp
Hamming keerde terug naar het FORTRAN/ALGOL-contrast als een les in institutionele & menselijke dynamiek, niet alleen taalontwerp.
FORTRAN werd psychologisch ontworpen — voor de mensen die het zouden gebruiken, met name wetenschappers die dachten in wiskundige notatie. ALGOL werd logisch ontworpen — voor formele correctheid & theoretische elegantie.
De paradox die Hamming identificeerde: een logisch correcte taal die mensen weerstaan mislukt; een pragmatisch ontworpen taal die mensen aannemen slaagt, zelfs als deze logisch rommelig is.
Hij noemde APL als het uiterste geval: logisch elegant, eenregels uitdrukbaar, met zijn eigen speciale karakterset. Experts hielden ervan. Normale programmeurs vonden het onleesbaar. Een enkel karakterverandering kon stiekem het betekenis van een programma transformeren. APL heeft een kleine toegewijde gemeenschap & vrijwel geen mainstream gebruik.
Het menselijke redundantie-argument: gesproken taal is ongeveer 60% redundant (herhaalde context, verduidelijkende woorden, voorspelbare structuur). Geschreven taal ongeveer 40% redundant. Deze redundantie dient foutdetectie — mensen zijn onbetrouwbaar, dus taal evolueerde om genoeg herhaalde informatie te dragen om fouten op te vangen & te corrigeren. Een taal met lage redundantie verwijdert dit veiligheidnet.
De compilerhiërarchie
Hamming beschreef de compiler/interpreter-gelaagdheid: een programma kan een taal op hoger niveau lezen & vertalen naar een op lager niveau. Stack deze lagen — elk vertaalt één niveau omlaag. Helemaal bovenaan: een domeinspecifieke taal die experts op een gebied (biologie, financiën, fysica) natuurlijk schrijven. Helemaal onderaan: machinecode. Elke transitie is een compiler of interpreter.
Taaloverleving voorspellen
Tegen 1993 had Hamming veel talen zien slagen & mislukken. FORTRAN (1957) overleefde. ALGOL (1958) mislukte. COBOL (1959) overleefde decennia in zakencomputing. LISP (1958) overleefde in AI-onderzoek. PL/I (1964) probeerde alles te verenigen & mislukte.
Het herhaalde patroon
Hamming's softwaregeschiedenis-hoofdstuk bevat een herhaalde structuur:
1. Een pijnlijke beperking bestaat (absolute adressen, binaire notatie, niet-onderhoudbare code)
2. Iemand vindt een abstractielaag uit die de beperking verbergt
3. De abstractie maakt nieuwe schaal mogelijk, wat nieuwe pijnlijke beperkingen creëert
4. Herhaal
Binair → octaal/hexadecimaal → symbolische assembler → FORTRAN → gestructureerd programmeren → objectgeoriënteerde talen → domeinspecifieke talen. Elk niveau lost het meest acute pijnprobleem van de voorganger op terwijl een nieuwe klasse probleem wordt geïntroduceerd.
De spaghettie-code-probleem (absolute adressen) leidde tot symbolische assembler. Grote assembler-programma's leidden tot FORTRAN. Grote FORTRAN-programma's leidden tot gestructureerd programmeren & vervolgens objectoriëntatie. Hamming's lezing eindigde voordat deze latere transities, maar het patroon gaat door.
Zijn les voor ingenieurs: je lost altijd het pijn blootgesteld door de vorige abstractie op. Het begrijpen van de laag waarop je momenteel bent vereist het kennen van waarom de laag eronder bestaat.