(zuerst veröffentlicht in RETURN #60)
In der Liste der Eigenschaften von BASIC zählte der im vergangenen Jahr verstorbene Mitentwickler Thomas E. Kurtz als einen entscheidenden Punkt auf, dass die Zeilennummern eines BASIC-Programms zugleich auch als Sprungziele im Programmcode dienen, was die Programmflusssteuerung gerade Programmieranfängern erleichtern könnte. Diese Idee, die sich bereits in einer der ersten höheren Programmiersprachen – Fortran – fand und an die Verwendung von Speicheradressen als Sprungziele in Maschinen- und Assemblersprachen erinnert, charakterisierte BASIC bis Mitte der 1990er-Jahre. Die Verwendung von GOTO löste eine regelrechte Kontroverse in der Informatik aus – sowohl die Software-Ingenieure, die um die Wartbarkeit größerer Programmierprojekte bangten, als auch die Didaktiker, die sich mit unsaubereren Stilen konfrontiert sahen, erblickten in GOTO eine der Hauptursachen für den sogenannten Spaghetticode. Werfen wir einen Blick auf das Phänomen und wie es die Programmierer und ihre Programme geprägt hat.
Wer schon einmal versucht hat, ein längeres BASIC-Programm lesend zu verstehen – etwa, während er es aus einer Zeitschrift abgetippt hat, oder beim Versuch, darin einen Programmierfehler zu finden –, der wird vielleicht auf einige Verständnisschwierigkeiten gestoßen sein. Diese haben vor allem damit zu tun, dass Code nicht wie normaler, natürlichsprachlicher Text von links nach rechts und von oben nach unten gelesen und verstanden werden kann. Anders als bei Prosa entfaltet sich der Sinn in Programmcode nicht linear entlang des normalen Leseflusses, sondern sprunghaft (im Überspringen von Codeteilen vorwärts und rückwärts), zirkulär (in Schleifen) und manchmal rekursiv (also in Codebestandteilen, die sich selbst aufrufen). Experimente in der Programmierdidaktik, bei denen Probanden einen Programmierfehler in kurzen Sourcecodes unterschiedlicher Programmiersprachen finden sollten und deren Augenbewegungen dabei mit einem Eye-Tracking-System verfolgt wurden, haben diese Unterschiede deutlich gezeigt: Selbst im Vergleich mit den Bewegungen, die die Augen beim Lesen von abstrakten Gedichten vollziehen, zeigt sich das Codelesen als noch sprunghafter, teilweise wirr und stockend.
Während wir also dem nichtlinearen Aufbau von Code kaum zu folgen in der Lage sind, haben die Computer allerdings keinerlei Schwierigkeiten damit, selbst die verworrendsten Verzweigungsstrukturen korrekt auszuführen:
10 GOTO 100
20 NEXT N
30 END
50 PRINT N,
60 GOTO 20
100 FOR N=10 TO 15
110 GOTO 50
Dieses kleine BASIC-Programm zeigt den komplexen, nichtlinearen Aufbau eines gegen alle Regeln der Kunst programmierten BASIC-Listings. Die Verwendung der GOTO-Statements darin ist das hauptsächliche Problem. Dass die meisten BASIC-Dialekte es erlauben, aus Schleifen (hier aus einer FOR-Schleife) heraus oder in sie hinein zu springen, ist das zweite Problem, das hier sogar dazu führt, dass der NEXT-Befehl im Listing noch vor dem FOR-Befehl, auf den er sich bezieht, auftauchen kann.
Selbst dieses kleine Codebeispiel ist schon geeignet, Leseprobleme (für den menschlichen Leser) zu verursachen, weil es die gewohnten Programmierweisen unterläuft. Man stelle sich nun vor, solche Konstruktionen tauchten in viel längeren Programmen auf. Die RAM-Speicher der in den 1980er-Jahren verfügbaren Homecomputer waren teilweise bis zu 128 Kilobyte groß – Platz für hunderte von Zeilen lange BASIC-Programme. Und so künstlich das obige Beispiel auch wirkt, wäre es nicht ungewöhnlich, dass solche Konstrukte beabsichtigt oder unbeabsichtigt tatsächlich in Programmen auftauchen. Vor allem dann, wenn Speicherplatz gespart oder Geschwindigkeit gewonnen werden muss, wurden und werden Programmiertricks genutzt, die solche und ähnliche Konstrukte hervorbringen.
Softwarekrise
Das 1964 veröffentlichte BASIC scheint mit dieser Art der Programmierung vor dem historischen Hintergrund seiner Zeit betrachtet allerdings nur ein Symptom einer Entwicklung zu sein, die in der zweiten Hälfte der 1960er-Jahre eine nahende Katastrophe ankündigte. IBM hatte zu Beginn des Jahrzehnts durch den Aufzug der Minicomputer (von DEC und anderen Firmen) seine quasi monopolistische Marktmacht verloren, was auch daran abzulesen war, dass Computer und Peripherien nicht mehr kompatibel zu IBM-Systemen sein mussten. Gleichzeitig existierten aber erst wenige Standards, die verbindliche Regeln bei Software-, Hardware- und Protokollentwicklungen vorschrieben. So hatte zum Beispiel erst 1962 ASCII (der American Standard Code for Information Interchange) Einzug in die Datenkommunikation gefunden, sodass sich unterschiedliche Geräte verschiedener Hersteller miteinander „unterhalten“ konnten. Dadurch wurde IBMs EBCDIC als Quasi-Standard abgelöst. Und auch unter den Programmiersprachen herrschte zu dieser Zeit eine regelrecht babylonische Vielfalt. In den immer größer werdenden Softwareprojekten fanden sich mangels Programmierstandards (und fehlender Ausbildungen, in denen „ordentliches“ Programmieren gelernt werden konnte) immer mehr und immer gravierendere Fehler.
Weil Software aber damals nicht nur im ökonomischen oder wissenschaftlichen Umfeld eingesetzt wurde, sondern auch beim Militär, und vor allem immer mehr wichtige Schaltstellen des strategischen Nuklearwaffenprogramms auf Computer umgestellt wurden, musste gehandelt werden, um durch Computerfehler verursachte Katastrophen zu verhindern. Deshalb trafen sich 1968 im bayerischen Garmisch-Partenkirchen wichtige Vertreter der NATO zu einer Konferenz, um der „Softwarekrise“, wie sie das hier skizzierte Problem apostrophierten, Herr zu werden. Beschlossen wurde nicht nur eine Standardisierung von Hard- und Softwareschnittstellen, sondern auch eine Leitlinie zum „ordentlichen” Programmieren. Auch eine neue Programmiersprache namens ADA erblickte das Licht der Welt – eine Sprache, bei der es möglich sein sollte, die Funktion von Programmkonstrukten mathematisch zu beweisen. Das Entstehen von BASIC mit seiner eingebauten Möglichkeit, „Spaghetticode“ zu erzeugen, war also offenbar auch dem technikhistorischen Hintergrund geschuldet. Hätten Kurtz und Kemeny ihre Sprache vier Jahre später – nach der NATO-Konferenz – konzipiert, hätte sie vielleicht ganz anders ausgesehen …
GOTO considered harmful
Historisch bedeutender als die Sprache ADA, die es heute immer noch gibt, wurde jedoch der Ruf nach sauberer Programmierung. Er wurde gehört von dem niederländischen Informatiker Edsger Wybe Dijkstra, der im Rahmen dieser Kolumne schon häufiger zitiert wurde (etwa mit seinem Bonmot „It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration“). Dijkstra, selbst Professor für Informatik, der Studierenden das Programmieren beibringen sollte und wollte, hatte bereits vor dem Ausrufen der „Softwarekrise“ damit begonnen, Paradigmen für das sogenannte „strukturierte Programmieren“ aufzustellen. Dazu gehörten ein modularer Aufbau von Programmen, eine sichtbare Binnenstrukturierung von Code (durch hierarchische Einrückungen), konsequente Kommentierung und die Nutzung von Kontrollstrukturen und Schleifenoperationen zur Regulierung des Programmflusses.
Letzteres sollte vor allem die GOTO-Nutzung überflüssig machen. 1968 veröffentlichte Dijkstra einen Aufsatz mit dem Titel „Go To Statement Considered Harmful“, in welchem er die schädlichen Konsequenzen für Programme auflistete, die beim Verwenden ungezügelter Sprünge auftreten könnten. Jeden Versuch, einen (für Menschen) übersichtlichen Code zu entwickeln, vereitelten GOTOs durch das Unterlaufen (oder Überspringen) aller zuvor penibel gestalteter Ordnung. Natürlich sah Dijkstra mit Sorge die aufkeimende BASIC-Programmierbewegung, die vor allem Schüler und Studenten, und bei diesen vor allem diejenigen, denen informatische Prinzipien guten Programmierens unbekannt oder gleichgültig waren, an die Tastaturen brachte. Dieser Popularisierung des Programmierens sollte professionelle Kritik und eine Didaktik für das Software-Engineering entgegengestellt werden. Die GOTO-Kontroverse wäre aber keine Kontroverse, wenn in ihr keine widersprüchlichen Meinungen aufgetreten wären. So erschienen nach Dijkstras „Aufschlag“ Beiträge mit dem Titel „‚GOTO considered harmful‘ considered harmful“ oder „Structured Programming considered harmful“ usw., in denen versucht wurde, Dijkstras Argumente zu entkräften.
Ordnung im Chaos
Von der Warte des Computerhistorikers und -archäologen aus betrachtet ist die Auseinandersetzung um die Verwendung von GOTO, das strukturierte Programmieren und im Kontrast dazu die Verwendungsweisen der Programmiersprache BASIC überaus spannend und bunt. Die Versuche, dem Wildwuchs der Hobbyprogrammierung Einhalt zu gebieten und wenigstens die Schulen mit einer „ordentlichen“ Lehrsprache zu versorgen, mündeten hierzulande etwa in der Entwicklung der Sprache ELAN (Educational Language), die zusammen mit Pascal BASIC verdrängen sollte – allerdings mit mäßigem Erfolg. In den Schulen standen längst Heimcomputer, für die es kein ELAN und kaum Pascal-Compiler gab, und die Zeitschriften waren voll mit hobbyistisch erstellten BASIC-Listings zum Abtippen für die verschiedensten Systeme. Die meisten Programmierlehrgänge erschienen für BASIC, sowohl in Buchform als auch als Radioprogramme und sogar im Fernsehen.
Interessant wird es, wenn man sich die Codes, die in dieser Sprache entwickelt wurden, einmal vor diesem Hintergrund ansieht: Waren die BASIC-Programme der Hobbyisten wirklich so chaotisch? Welchen Einfluss hatten die verschiedenen BASIC-Dialekte auf die Struktur der Programme? Und lässt sich die stilistische Qualität eines BASIC-Programms vielleicht sogar bemessen? Im Rahmen meiner Forschung zu den Programmierpraktiken damaliger BASIC-Coder versuche ich genau diese Fragen zu beantworten und stelle dafür eine Liste mit Eigenschaften zusammen, die auf die Codestruktur Einfluss nehmen können. Nur ein paar Beispiele hierfür:
Code Style Matters
Die BASIC-Interpreter geben zum Beispiel vor, ob Leerzeichen zwischen Befehlen und Funktionen notwendig sind (wie zum Beispiel beim Locomotive BASIC für Amstrad CPC), ob sie fakultativ sind (Commodore BASIC V2) oder ob sie sogar vom Interpreter nachträglich eingefügt werden (Atari Shepardson BASIC). Manche Interpreter lassen den Programmierern nur wenige Freiheiten im Programmentwurf (Sinclair BASIC), andere stellen alle möglichen Vorgehensweisen zur Auswahl (BBC BASIC). Bei einigen Interpretern ist es egal, ob Befehlswörter groß oder kleingeschrieben werden; andere verlangen Großschreibung (BBC BASIC) oder wandeln klein geschriebenen Code automatisch in Großbuchstaben um (Locomotive BASIC). Teilweise lassen BASIC-Interpreter die Einrückung von Code zu, sodass Programmstrukturen leichter erkennbar sind. Beim Atari werden alle Einrückungen jedoch automatisch entfernt; beim C64 kann man sich durch Verwendung eines „:“ am Zeilenanfang behelfen. Das IS BASIC der Enterprise-Computer erkennt Programmstrukturen sogar und rückt untergeordnete Zeilen automatisch ein.
Aufseiten der Programmierer kann auch einiges zur Programmver(un)deutlichung getan werden: So sorgt neben der Anzahl der verwendeten GOTO-Anweisungen vor allem eine hohe Anzahl von pro Zeile gegebenen Befehlen (was seit den HP-BASIC-Dialekten durch Nutzung von Trennzeichen wie „:“ oder „/“ ermöglicht wird) für Unübersichtlichkeit. Der Zugriff auf die Hardware durch POKE-Anweisungen, PEEK-Funktionen sowie der Aufruf von Maschinensprache-Routinen durch USR-, SYS-, CALL- oder ähnliche Anweisungen und das Hinterlegen solcher Routinen in DATA-Zeilen machen Programme vor allem für plattformfremde Programmierer schwer nachvollziehbar. Auch Bedingungsprüfungen mit verschachtelten oder verketteten logischen Operatoren verursachen intensives Kopfzerbrechen beim menschlichen Nachvollziehen.
Ebenso kann auch auf der Makroebene einiges für die Nachvollziehbarkeit des Codes getan werden (oder auch dagegen, wenn man Code absichtlich obfuskieren möchte): Etwa, indem Programmfunktionen in sauber voneinander getrennten Programmblöcken deponiert werden, in die nicht willkürlich hinein- und aus denen nicht willkürlich herausgesprungen wird. Die Wahl der Zeilennummerierung kann hier ebenfalls zur Verdeutlichung beitragen (etwa, wenn jeder Programmblock mit einer neuen Hunderter- oder Tausender-Zeilennummer begonnen wird). Zu guter Letzt kann die Verwendung von REM-Kommentaren als Überschriften von Programmblöcken zusätzliche Klarheit in die Funktion des Blocks bringen.
Real Programmers …
„Real Programmers aren’t afraid to use GOTOs“, schrieb der Tektronix-Hacker Ed Post 1983 in seinem viel zitierten Essay „Real Programmers Don’t Use Pascal“. Und schaut man sich die existierenden historischen BASIC-Listings an, so stellt man schnell fest, dass zu keiner Zeit Angst vor der GOTO-Nutzung geherrscht hat oder gar konsequent auf die Einhaltung der Regeln strukturierten Programmierens geachtet wurde. BASIC-Programmieranleitungen, in denen stylisher und lesbarer Programmcode das Ziel der Übung war, blieben Rufer in der Wüste. Es existiert vielmehr die gesamte Bandbreite an Stilen und Verwendungsweisen von Programmiersprachen – manchmal sogar unter Umgehung der Interpreter-Regeln, wie spektakuläre BASIC-One-Liner für den ZX Spectrum.
Diese Vielfalt an Programmierstilen erscheint im Rückblick als eine echte kulturelle Bereicherung, gibt sie uns doch Einblick in die unterschiedlichen Programmierniveaus, Programmiertechniken und Systemkenntnisse ihrer Entwickler. Ganz ähnlich wie bei natürlichen Sprachen entwickelten BASIC-Programmierer regelrechte Individualstile. An den Programmcodes ließen sich auf diese Weise nachträglich Autorschaften, Übernahmen fremder Codefragmente und stilistische Einflüsse innerhalb von Programmier-Communitys ermitteln. Meine Suche nach den oben genannten Metriken verfolgt genau dieses Ziel: Dass mit ihrer Hilfe massenweise BASIC-Programme mit dem Einsatz linguistischer Software analysiert werden können, um aus der Flut historischer Spaghetticodes Erkenntnisse zu gewinnen, die einem einzelnen Programm kaum ansehbar wären.
COMEFROM
Wer auch bei modernen Programmiersprachen nicht auf GOTOs verzichten möchte, weil er sich von der Sprache seinen Programmierstil nicht vorschreiben lassen will, findet den Befehl erstaunlich häufig im Befehlsrepertoire: Einige Versionen von JAVA und C verfügen über GOTO-Statements. Python kennt ihn von Haus aus zwar nicht, man kann ihn jedoch über ein Modul importieren, das sich unter https://entrian.com/goto/ herunterladen lässt. Das Modul enthält übrigens auch, quasi als Persiflage auf die GOTO-Kontroverse, den COMEFROM-Befehl, der 1973 von Lawrence Clark ersonnen wurde. COMEFROM gibt eine Zeile vor, die, sobald sie erreicht wird, einen Rücksprung zur Zeile nach dem COMEFROM ausführt:
10 COMEFROM 30
20 PRINT “YOU GOTO WHERE I COMEFROM!“,
30 REM HIER ERFOLGT DER SPRUNG NACH ZEILE 20