Zwischen Hybris und Demut

>>I regularly have to google the basic syntax of a language l've used every day for 10 years. #coderconfessions«

@HackerNewsOnion I Twitter, 10. Juli 2013

In den letzten Jahren wurde in Geek-Kreisen gern der »Dunning-Kruger-Effekt«1 zitiert, demzufolge ausgerechnet inkompetente Personen besonders stark dazu neigen, das eigene Können zu überschätzen. Nachfolgestudien deuten darauf hin, dass es sich in Wirklichkeit anders und einfacher verhält: Menschen sind ganz allgemein nur schlecht in der Lage, ihre eigene Kompetenz auch nur halbwegs zutreffend einzuschätzen.

Ungeübte Programmierer schwanken zwischen Selbstüberschätzung und dem Glauben, zu dumm für das Metier zu sein. In der Begeisterung, zu der die Planung eines neuen Projekts führt, werden die eigenen Fähigkeiten oft überschätzt, insbesondere macht man sich keine Vorstellung davon, wie langsam die Entwicklung von funktionierendem Code tatsächlich voranschreitet. Die Konfrontation mir der unangenehmen Wahrheit führt dann entweder zu Verzweiflung (bei Projekten mit Deadline) oder Lustlosigkeit (bei Hobbyprojekten).

Selbstüberschätzung hat mehrere Ursachen. Zum einen lernt man als Anfänger ständig hinzu, das schmeichelt dem Ego. Die Lernkurve ist in den ersten zwölf Monaten, in denen man etwas Neues lernt, so steil, dass man nicht anders kann, als sich für einen ausgemachten Topchecker zu halten. Was schwer zu erkennen ist: Trotz des vielen und schnellen Dazulernens ist man gerade erst bis zu den Knöcheln ins Nichtschwimmerbecken gewatet. Die Welt der Programmierung ist für den Anfänger, um es mit Donald Rumsfeld zu sagen, voller »unknown unknowns«, also voller Wissenslücken, die man gar nicht als Lücken erkennt.

Eine weitere Ursache für Selbstüberschätzung liegt darin, dass unerfahrene Programmierer dazu neigen, nur die ersten 80 Prozent eines Projekts überhaupt zu erledigen, weil sie aufhören, sobald die Aufgabenstellung weniger interessant wird. Der 80-20-Regel2 zufolge verursachen die dann noch folgenden 20 Prozent allerdings 80 Prozent der Arbeit. Man baut also mit einem Bruchteil der Programmierkenntnisse eines Profis eine Applikation zusammen, die »praktisch dasselbe« ist wie ihr Vorbild. Die dabei durch Unkenntnis und Fehlentscheidungen verursachten Probleme fallen nicht weiter auf, weil sie erst innerhalb der letzten 20 Prozent der Aufgabe ihre hässliche Fratze zeigen.

Überschätzung der eigenen Fähigkeiten oder Unterschätzung einer Aufgabe kann auch Vorteile haben. Wenn jeder von Anfang an über das Ausmaß seines Unwissens Bescheid wüsste, lebte die Menschheit vermutlich immer noch in Erdhöhlen (»Hochbau? Was man da alles wissen müsste!«). Auch bei einzelnen Projekten kann es hilfreich sein, sich zu verschätzen. Als Donald Knuth 1977 - frustriert über den hässlichen Textsatz des zweiten Bandes seines Hauptwerks >>The Art of Computer Programming« - beschloss, selbst ein besseres Satzprogramm zu schreiben, rechnete er mit etwa sechs Monaten Entwicklungszeit. Das Ergebnis hieß TeX und war schon knapp zwölfJahre später fertig. Der Doktorand George Bernard Dantzig erschien 1939 zu spät zu seinem Statistikkurs an der University of California und fand zwei Probleme an der Tafel vor, die er für Hausaufgaben hielt. Einige Tage später entschuldigte er sich bei seinem Professor, dass er so lange gebraucht habe, um die Aufgaben zu lösen; sie seien etwas schwieriger gewesen als sonst. Allerdings handelte es sich gar nicht um Hausaufgaben, sondern um bis dahin unbewiesene Statistiktheoreme, die Dantzig damit versehentlich bewiesen hatte. In manchen Fällen sind Fehleinschätzungen der Lage also durchaus hilfreich, weil sie einen davor bewahren, sich vom Umfang oder der Komplexität einer Aufgabe abschrecken zu lassen.

Auf der anderen Seite des Wetterhäuschens wohnt der Selbstzweifel. Der eigene Code ist ein hässliches, unwartbares Dickicht. Sicher müssen andere, bessere Programmierer nicht jeden Befehl vor jeder Verwendung in der Dokumentation nachschlagen. Niemand sonst vergisst über Nacht, was er sich beim Schreiben des Codes gedacht hat. Man ist einfach unbegabt und faul und wird zeitlebens ein schlechter Programmierer bleiben.

Die gute Nachricht: Den anderen geht es genauso. Auch erfahrene Programmierer sind vergesslich, unkonzentriert, arbeitsscheu und halten den eigenen Code für den schlechtesten der Welt. Es gibt nur wenige Probleme, die ausschließlich unerfahrene, halbherzige oder eilige Programmierer betreffen:

Unwartbarer Code

Code wird ohne Rücksicht auf spätere Wartbarkeit (durch einen selbst oder andere) geschrieben. Das liegt in erster Linie an mangelnder Erfahrung. Erst wenn man oft genug vor einem selbst erzeugten, undurchdringlichen Codedschungel gestanden hat, fällt es etwas leichter, beim Schreiben an den künftigen Leser zu denken. Nur ungewöhnlich

phantasiebegabte oder zukunftsorientierte Programmierer erfassen diesen Sachverhalt gleich von Anfang an. Alle anderen müssen erst das Tal der Schmerzen durchschreiten.

Wahl ungünstiger Mittel

Wer nur eine halbe Programmiersprache oder Technik beherrscht, der wird sie zur Lösung sämtlicher Aufgaben heranziehen, die ihm einfallen. Oft ist das Problem dabei nicht totale Unkenntnis, sondern nur mangelnde Vertrautheit mit der nächstliegenden Herangehensweise.

Selbstüberschätzung

Auch gute Programmiererinnen überschätzen häufig ihre Produktivität. Das liegt zum einen daran, dass ihnen wie allen anderen Menschen die Fähigkeit zur realistischen Einschätzung fehlt, wie lange ein Projekt dauern wird. Zum anderen kristallisiert sich die eigentliche Problemstellung oft erst im Laufe der Arbeit heraus. Das ist bei schlechten Programmiererinnen nicht anders - nur um etwa drei Größenordnungen schlimmer.

Fehlendes Vorwissen

Jedes Konzept, dem der unerfahrene Programmierer begegnet, ist für ihn neu. Auch in der Softwareentwicklung gibt es jedoch relativ viele Ideen, die wieder und wieder in neuem Gewand Anwendung finden. Erfahrene Programmierer erkennen diese Muster, können sie benennen und tun sich dann leichter damit, sie in anderen Kontexten anzuwenden.

Schwächen als Stärken

Der Perl-Erfinder Larry Wall nennt im Standardwerk »Programmieren mit Perl« Faulheit, Ungeduld und Selbstüberschätzung als wichtige Programmiertugenden. Faulheit ist gut, weil sie die Programmiererin dazu motiviert, so viel Energie wie möglich einzusparen. Sie wird arbeitssparende Software schreiben, das Geschriebene gründlich dokumentieren und eine FAQ verfassen, um nicht so viele Fragen dazu beantworten zu müssen. Ungeduld bringt die Programmiererin dazu, Software zu schreiben, die ihre Bedürfnisse nicht nur erfüllt, sondern vorausahnt. Und Selbstüberschätzung lässt sie auch das Unmögliche anpacken. Aber auch andere Untugenden können Programmierern, richtig eingesetzt, zum Vorteil gereichen:

Dummheit

>>Mir kommt es oft so vor, als käme der schlimmste Spaghetticode von den Leuten, die am meisten gleichzeitig im Kopf behalten können. Anders bringt man solchen Code ja gar nicht zustande«, vermutet der Softwareentwickler Peter Seibel.3 Ein weniger intelli-3 »Coders at Work<<, S. 311.

genter Programmierer wird versuchen, eine möglichst einfache Lösung zu finden und dadurch mit höherer Wahrscheinlichkeit ( ode schreiben, den auch andere Menschen verstehen, warten und erweitern können.

Unwissenheit

Wissen um die Details einer Programmiersprache oder um abstraktere Konzepte ist eine feine Sache. Sobald es aber zu einem Paradigmenwechsel kommt - die Einführung der objektorientierten Programmierung war ein solcher -, werden viele bisher kompetente Programmierer durch ihr vorhandenes Wissen ausgebremst. Weitgehend ahnungslose Geschöpfe haben es in so einer Situation leichter, weil sie unvorbelastet an das Neue herangehen können.

Vergesslichkeit

Douglas Crockford, eine wichtige Figur in der Entwicklung von JavaScript, antwortet auf die Interviewfrage, ob Programmieren nur etwas für die Jugend sei: »Ich bin heute vielleicht ein bisschen besser als früher, weil ich gelernt habe, mich weniger auf mein Gedächtnis zu verlassen. Ich dokumentiere jetzt gründlicher, weil ich mir nicht mehr so sicher bin, dass ich nächste Woche noch weiß, warum ich etwas so und nicht anders gelöst habe.«-* Außerdem wird ein Programmierer, der ständig Namen und Syntax der einfachsten Funktionen vergisst, stärker motiviert sein, sich eine Entwicklungsumgebung oder wenigstens einen Editor mit intelligenten Codevervollständigungsoptionen zuzulegen.

Fehlendes Durchhaltevermögen

In manchen Kreisen gilt es als heroisch, die ganze Nacht durchzuprogrammieren. Die Wahrscheinlichkeit, dass man den so entstandenen Code am nächsten Tag wegwirft, ist hoch. Wer es sich leisten kann, weil ihm kein Chef und keine Deadline im Nacken sitzt, tut besser daran, ich nicht zur Arbeit am Code zu zwingen. Oft kann eine gute Idee am Badesee ganze Wochen unsinniger Arbeit ersetzen.

Prokrastination

Gerade für schlechte Programmierer ist es nützlich, Verbesserungen am Code so lange wie möglich aufzuschieben. Falls es eines Tages wirklich unumgänglich ist, etwas zu ändern, wird man bis dahin ein besserer Programmierer geworden sein. Dann ist es gut, dass man nicht früher ans Werk gegangen ist. Außerdem werden Werkzeuge, Programmiersprachen, Codebibliotheken und Frameworks mit der Zeit immer besser. Die Lösung eines Problems wird also einfacher, je länger man wartet, denn andere, erfahrenere Programmierer erledigen dann einen Teil der Arbeit. Oft genug kann eine Aufgabe einfach ausgesessen werden, bis ein entsprechendes Open Source-Projekt das Problem 4

gelöst hat. Durch aktive Beteiligung an so einem Projekt lässt sich dieser Prozess natürlich noch beschleunigen.

Ekel vor dem eigenen Code

Es ist gut und richtig, den eigenen Code zu hassen. An guten Code klammert man sich mit irrationaler Anhänglichkeit. Schlechten Code wird man bereitwillig wegwerten, sobald Nutzer sich Änderungen wünschen oder ein neuer Lösungsweg auftaucht. Wer seinen Code für perfekt hält, lernt zu wenig dazu. Die Zusammenarbeit mit anderen ist produktiver, wenn die Beteiligten nicht in ihren eigenen Code verliebt sind. Und die übermäßige Beschäftigung mit der Codequalität kann Energie dort abziehen, wo sie dringender gebraucht wird: beim Nachdenken über Zweck und Ergebnis der Arbeit. Code ist lediglich ein Lösungsweg und - im Gegensatz zu Literatur - kein Selbstzweck.

Ehrgeizlosigkeit

Mittelmäßiger Code macht eventuell froher - vielleicht nicht unbedingt seine Nutzer, aber wenigstens seinen Urheber. Die Glücksforschung unterscheidet zwischen »Maximi-zers<<, die stets das Beste anstreben, und >>Satisficers<<, die sich auch mit weniger zufriedengeben. Die Maximizer mögen bessere Ergebnisse erzielen, glücklicher aber sind die Satisficer.

Trägheit

Geschickt eingesetzte Trägheit kann zum Werkzeug werden. Ein Beispiel: Globale Variablen sollten nur dort verwendet werden, wo sie wirklich nötig sind - also ziemlich selten.s Weil es aber so bequem ist, Daten, auf die man an mehreren Stellen zugreifen möchte, in eine globale Variable zu stecken, neigen Anfänger dazu, dieses Mittel überzustrapazieren. Es kostet viel Mühe, eine solche global angelegte Variable später wieder loszuwerden. Umgekehrt kann man die Kraft der eigenen Trägheit in den Dienst der guten Sache stellen, indem man grundsätzlich alle Variablen lokal anlegt und erst dann global werden lässt, wenn es gar nicht mehr anders geht. Jetzt macht sich die Trägheit nützlich, indem sie einen daran hindert, den Code zu verschlechtern.

Das Hauptproblem des Glaubens an die eigenen Schwächen ist, dass er sich so gut als Ausrede benutzen lässt: »Ich muss gar nicht erst versuchen, es besser zu machen weil ich es nicht besser machen kann. Ich bin einfach nicht schlau genug.« Diese Annahme ist nicht nur kontraproduktiv, sondern auch falsch. Die meisten persönlichen Schwächen und Unfähigkeiten erweisen sich bei näherer Betrachtung als so weit verbreitet, dass man sie sinnvoller als Normalzustand des menschlichen Geistes betrachten sollte. Irgendwo an der Peripherie des Bekanntenkreises mag es einen Superprogrammierer geben, der Fehler im Code auf den ersten Blick identifiziert, die Umgekehrt Polnische Notation 5 Die Nachteile globaler Variablen sind im Wikipedia-Eintrag en. wikipedia.org/wiki/Globul_variables erläutert. 5

beherrscht und sämtliche Syntaxfinessen seiner zwölf Lieblingssprachen im Kopf hat. Aber die Existenz dieses Superprogrammierers bedeutet nur, dass Ausnahmen von der allgemeinen Unzulänglichkeit möglich sind.

Richtiges muss nicht schwierig sein

Der selbst geschriebene Code sieht womöglich aus wie im Kinderbuch: »Das ist der Hund. Der Hund spielt im Garten. jetzt bellt der Hund.« Aber das ist kein Grund zur Demut. Nicht die Fähigkeit, möglichst komplexen Code zu schreiben, zeichnet gute Programmierer aus. Elegante und gute Ideen lassen sich auch in schlichtem Code ausdrücken, und umgekehrt kann sich hinter kompetentem Code ein schlecht durchdachtes Konzept verbergen.6

Ein aus dem Flugzeugbau stammendes und auch in anderen technischen Bereichen sehr populäres Motto lautet »KISS«, was für »Keep it simple, stupid« steht. Motivation dieses Designprinzips war ursprünglich, zu gewährleisten, dass amerikanische Bomber von einem einzelnen Mechaniker in zwei Minuten mit einem Schweizer Taschenmesser repariert werden können. Auf Softwareentwicklung angewendet, besagt es, dass Formulierungen im Kinderbuchstil nicht nur akzeptabel, sondern sogar vorteilhaft sind, weil sie unmissverständlich und leicht zu warten sind.

Häufig sind die Aufgaben, mit denen man als Programmierer zu tun hat, auch gar nicht so kompliziert wie zunächst gedacht. Bernie Cosell, einer der Programmierer hinter dem Ur-Internet Arpanet, erklärt: »Ich habe ein paar Grundregeln, die ich den Leuten beizubringen versuche. Das sind meistens Leute, die direkt vom College kommen und glauben, sie wüssten alles über Programmierung. Zum einen geht es mir dabei um die Einsicht, dass es nur ganz wenige an sich schwierige Programmierprobleme gibt. Wenn man Code betrachtet, der sehr schwierig aussieht - wenn man überhaupt nicht versteht, was das alles soll -, dann ist das fast immer ein Anzeichen dafür, dass dieser Code schlecht durchdacht ist. Dann krempelt man nicht die Ärmel hoch und versucht, den Code geradezuziehen, sondern man lehnt sich erst mal zurück und denkt nach. Wenn man lange genug nachgedacht hat, stellt sich heraus, dass alles ganz einfach ist. (. . .) Ich bin lange genug im Geschäft; ich weiß, dass es ein paar sehr komplexe Probleme gibt. Aber das sind nicht viele. Es ist immer wieder dasselbe: Wenn man gründlicher darüber nachdenkt, wird es einfacher, und die eigentliche Programmierung ist dann am Ende ganz leicht.«7

Wir brauchen einen vernünftigen Umgang mit unserer eigenen Fehlbarkeit und der anderer Menschen. Alles kann immer falsch sein und ist es meistens auch (eine Regel, die man insbesondere beim Lesen von Codekommentaren im Kopf behalten sollte). Aber es ist unproduktiv, sich deshalb für einen Idioten zu halten. Ein Kleinkind, das sprechen lernt, hat kein Problem damit, wenn es »ich habe getrinkt« sagt. Kind und Eltern verstehen, was gemeint ist, und hinter diesem einfachen Satz stecken erhebliche Leistungen der Evolution und des Individuums. Wer in der Lage ist, sich irgendeiner Programmiersprache zu bedienen, um auch nur »Hallo Welt« zu sagen, der hat es weit gebracht und braucht sich nicht durch die Lektüre von Blogbeiträgen, die von >>real programmers« handeln, entmutigen zu lassen. Alles, wasjetzt noch fehlt, ist der Wille, die Sache halbwegs gut zu machen. Man muss Störendes und Falsches erkennen und bereit sein, es zu ändern - vielleicht nicht sofort, aber doch zumindest irgendwann.

1

   de. wikipedia. org/uiki/Dutmmg-Kntge r-Efekt.

2

de. wikipedw.org/wiki/Paretoprinzip.

3

Schwächen als Stärken | 9

4

»Coders at Work«, S. 114.

5

Schwächen als Stärken I 11

6

   Ein SonderfaU ist schlechter Code, der ein schlechtes Konzept verbirgt: »In other words - and that is a rocksolid principle on which the whole of the Corporation's Galaxywide snccess is fonnded - thcir fundamental design flaws are completely hidden by their superficial design flaws.« Douglas Adams, »So Long, and Thanks For All the Fish«.

7

Richtiges muss nicht schwierig sein |    13