Wie schreibe ich unleserlichen Code?

Quidquid latine dictum sit, altum viditur.
"My Code is My Castle" - Warum sollte jemand anderes als der Autor es wagen, seinen Code auch nur ansatzweise zu verstehen? Es war schon schwer genug, den Code zu schreiben, also sollte es genauso schwer sein, ihn zu lesen. Hierzu einige Tipps, wie Sie ihren Code vor unerwünschten Mitlesern schützen können (s.a. How To Write Unmaintainable Code):
  1. Sorge dafür, dass die Kommentare mit den Code auseinanderlaufen und vergiss ihn up-to-date zu halten. Oder lüge ein wenig.
     
  2. Würze Deinen Code mit Kommentaren wie /* add 1 to i */, schreibe aber niemals Dinge hinein, die das Lesen erleichtern könnten.
     
  3. Sorge dafür, dass jede Methode etwas mehr (oder weniger) macht, als es der Name vermuten läßt. Z.B. eine Methode isValid(x) sollte als Nebeneffekt x binär codieren und als Ergebnis in einer Datenbank ablegen.
     
  4. Verwende Akronyme, um den Code knapp zu halten. Große Programmierer definieren niemals Akronyme - sie verstehen sie blind.
     
  5. Wenn Du z.B. eine Flug-Reservierungs-System entwickelst, sorge dafür, dass an mindestens 25 Stellen der Code modifiziert werden muss, wenn eine neue Fluggesellschaft eingebunden werden muss. Dokumentiere auf gar keinen Fall diese Stellen. Programmierer, die nach Dir kommen, sollen erst jede Zeile Code verstehen müssen, ehe sie sich an diese Aufgabe wagen können.
     
  6. Verwende aus Effizienz-Gründen "cut/paste/clone/modify". Dies ist wesentlich effizienter, als dafür kleine, wiederverwendbare Methoden zu schreiben. Außerdem erhöht es die LOCs (Lines of Code), und damit Deine Produktivität.
     
  7. n dr Krz lgt d Wrz. Variablen oder Methoden, die sprechende Namen enthalten, sind langweilig. Verwende verschiedeneAbkürzungen für dieselben Wörter, um den Code interessanter zu halten und das Aufnahmevermögen des Wartungs-Techniker zu testen.
     
  8. Alternative: verwende sehr lange, nichtssagende Variablen- oder Methoden-Namen, die sich von anderen nur in einem Buchstaben oder durch Groß/Kleinschreibung unterscheiden. Ideal sind auch Zeichen, die sich optisch ähnlich sehen, z.B. swimmer und swimner, parselnt und parseInt, DOCalc und D0Calc.
     
  9. Variablen-Recycling: Wann immer möglich, verwende Variablen mehrfach, am besten mit unterschiedlicher Bedeutung. Falls Dich jemand fragt, begründe es mit Effizienz-Überlegungen.
     
  10. Verwende niemals i für die innerste Schleife. Verwende i für irgendetwas anderes, auf keinen Fall für für eine int-Variable.
     
  11. Dokumentiere keine Unsauberkeiten im Code. Wenn Du den Verdacht hast, dass da ein möglicher Bug in Deinem Code schlummert, behalte es für Dich. Auch irgendwelche Ideen über eine mögliche Umstrukturierung gehören nicht hinein. "If you can't say anything nice, don't say anything at all" (Thumper). Was, wenn dieser Kommentar Dein Vorgesetzter oder Boss zu sehen bekommt? Ein "Must be fixed"-Kommentar ist völlig ausreichend, vor allem dann, wenn nicht daraus hervorgeht, auf welche Teile sich dieser Kommentar bezieht.
     
  12. Exceptions sind etwas für Weichlinge und Angsthasen. Sorgfältig geschriebener Code schlägt niemals fehl, wozu sich also um Exeption-Behandlung oder ein Excepition-Klassen-Konzept den Kopf zerbrechen?
     
  13. Schachtelung: Schachtele so tief wie möglich. Gute Programmierer schaffen bis zu 10 Klammern-Ebenen innerhalb einer Zeile und bis zu 20 {}-Ebenen in einer Methode. Extra-Punkte gibt es für öffnende und schließende Klammer auf verschiedene Seiten im ausgedruckten Listing.
     
  14. Lerne aus Büchern. Suche Dir Autoren aus, die so mit Bücher Schreiben beschäftigt sind, dass sie keine Zeit haben, um selber Code zu schreiben. Suche Dir Bücher aus, die lauter netten Wolken- und anderen Diagramme, aber keinen Code enthalten. Lerne aus diesen Büchern einige obskure, pedantische Begriffe, um damit irgendwelche Möchtegern-Entwicklern, die nach Dir kommen, einschüchtern zu können. Dein Code soll beeindrucken. Wenn andere Leute Dein Vokabular nicht verstehen können, müssen sie annehmen, dass Du sehr intelligent und Dein Algorithmus sehr unergründlich ist. Vermeide alle Arten von verständlichen Analogien in Deiner Algorithums-Beschreibung.
     
  15. Interface: Ignoriere das Interface-Konzept in Java. Wenn Dein Chef darauf besteht, erkläre ihm, das dadurch cut&paste-Code zwischen verschiedenen Klassen entsteht, der nur sehr schwer zu warten ist. Mach es stattdessen lieber wie die Java AWT-Designer - verfrachte alle mögliche Funktionalität in Klassen, die nur von Unterklassen verwendet werden können. Verwende jede Menge von "instanceof()"-Überprüfungen in Deinen Methoden.
    Wenn sich Interfaces nicht vermeiden lassen, benenne es "ImlementableIface" oder so. Ein anderes Juwel aus der akademischen Ecke ist das Anhängen von ?Impl? an die Klasse, die ein Interface implementiert. Dies kann z.B. gewinnbringend bei Klassen angewandt werden, die das Runnable-Interface implementierten.
     
  16. Wirf nichts weg - lasse alle nicht mehr verwendeteten Methoden und Variablen im Code. Wer sagt Dir denn, dass Du eine Variable, die Du seit 1996 nicht mehr gebraucht hast, nicht schon morgen wieder benötigst? "Warum das Rad neu erfinden" (Lieblingsspruch für Deinen Vorgesetzten), auch wenn sich der Code grundlegend geändert hat? Und wenn Du den Kommentar für diese Methode oder Variable nichtssagend gewählt hast, wird keiner es wagen, sie anzufassen und rauszuschmeißen.
     
  17. Kommentiere eine Methode makeSnafucated lediglich mit /* make snafucated */. Verrate auf keinen Fall, was snafucated bedeutet. Nur Idioten können sich darunter nichts vorstellen.
     
  18. KamaSutra-Technik: Kreiere Dutzende verschiedener Varianten einer Methode, die sich lediglich in einem winzigen Detail unterscheiden. Die Benutzer Deiner Methode werden dadurch erzogen, die Dokumentation (die höchstwahrscheinlich veraltet ist) genauestens zu lesen.
    (Stellung 47 und 115 im Kama Sutra unterscheiden sich lediglich darin, dass in 115 die Frau die Finger gekreuzt hat).
     
  19. Java ist schizophren bezüglich Array-Deklaration. Man kann es wie in C machen (String x[]), oder man kann den Java-Weg einschlagen (String[] x). Um den Leser total zu verwirren, sollte man beide Notationen mischen, z.B.:
      byte[] rowvector, colvector, matrix[];
  20. was gleichbedeutend ist mit:
      byte[] rowvector;
      byte[] colvector;
      byte[][] matrix;
       
  21. Wenn Dein Boss der Meinung ist, dass seine 20jährige FORTRAN-Erfahrung ein exzellenter Leitfaden zur objektorientieren Programmierung darstellt, folge stur seinen Empfehlungen. Du wirst sehen, dass Dein Boss sein Vertrauen in Dich setzt. Und das kann Deiner Kariere nützen. Und Du wirst jede Menge neuer Techniken der Code-Verschleierung kennenlernen.
     
  22. Verwende oktale Konstanten. Schmuggle sie in eine Liste von dezimalen Nummern, z.B.:
      array = new int [] { 111, 120, 013, 121 };
       
  23. Ungarische Notation ist die taktische Nuklear-Waffe im Kampf gegen lesbaren Code: benutze sie! Während bereits eine unvollstellbare Menge an Source-Code damit kontaminiert ist, kann nichts anderes einen Wartungs-Ingenieur schneller außer Gefecht setzen als ein wohlüberlegter Angriff mittels Ungarischer Notation. Die folgenden Tipps helfen, die ursprüngliche Absicht der Ungarischen Notation zu unterlaufen:
  24. Umlaute und andere nationale Sonderzeichen wie ß, ä oder é eignen sich hervorragend als Variablennamen, vor allem dann, wenn sie nicht ohne Copy&Paste erzeugt werden können.
     
  25. Wenn Dir kein passender englischer Name für eine Variable einfällt, verwende eine andere Sprache. Schwäbisch oder Bayrisch ist zum Beispiel hervorragend geeignet, um die Sprachkenntnis eines (womöglich indischen) Wartungs-Ingenieurs zu testen. z.B. statt "boolean running;" schreibe lieber "boolean ämmrnonetferdig;"
     
  26. Wann immer Code verwendet werden muss, der nicht selbst geschrieben wurde, isoliere diesen "dirty" Code durch mindestens einen Wrapper-Layer. Es könnte ja sein, dass der andere Autor möglicherweise jeder seiner Methode in ferner Zukunft umbenennen wird. Um sich vor unnötigen, globalen Umbennungen (womöglich noch automatisch mit VAJ) zu schützen, muss ein Wrapper her.

    Eine der größten Verdienste von Java sind viele Dummy-Wrapper-Methoden, ohne die viele einfache Probleme nicht lösbar wären, und die nichts anderes tun, als weitere Wrapper aufzurufen. D.h. es ist ohne weiteres möglich, Wrapper zu schreiben, die nichts tun, ohne dass es irgendjemand bemerkt. Um die Verwirrung perfekt zu machen, nimm für jeden Wrapper einen anderen Namen (z.B. aus einem Thesaurus).
     
  27. Cargills Quandary (Zwickmühle): "jedes Design-Problem kann durch einen zusätzliche Indirektion gelöst werden, außer das der zu großen Indirektion." Zerlege jedes OO-Programm, bis es nahezu unmöglich wird, eine Methode zu finden, die den Programmstatus verändert. Besser noch, lagere diese Methoden als Callback-Methoden aus.
     
  28. Verwende Variablennamen, die überhaupt nichts mit der aktuellen Programmfunktion zu tun hat, dafür aber eine eigene Bedeutung als Wort hat. Z.B. lassen sich damit Anweisungen wie
    marypoppins = (julieAndrews + starship) / mailbox;
    schreiben.
     
  29. Kapsle, kapsle, kapsle, z.B.
    myPanel.add (getMyButton());
    private Jbutton getMyButton() {
        return myButton;
    }
  30. Vertreibe nie ein "Bug-Fix-Only"-Release. Stelle sicher, dass Bug-Fixe nur zusammen mit Datenbank-Änderungen, einem komplett neuen Oberflächen-Konzept oder/und anderen Administrations-Schnittstelle ausgeliefert werden. Auf diese Weise werden die Benutzer erzogen, sich an Bugs zu gewöhnen und sie als Feature zu betrachten.
     
  31. Ändere Datei-Formate mit jedem Release-Wechsel. Deine Kunden wollen Aufwärts-Kompatibilität? Gib sie ihnen, aber vermeide unter allen Umständen Abwärtskompatibilität, damit die Anwender nicht auf die Idee kommen könnten, wieder zum alten Release zurückzukehren. Zusammen mit der Bug-Fix-Strategie (s.o.) werden die Kunde jeweils beim neuesten Release bleiben.
     
  32. Extra Bonus-Punkte: stelle sicher, dass die alte Programm-Version nicht die Dateien erkennt, die von der neuen Version erzeugt werden. Nicht nur, dass sie diese Dateien nicht lesen können, sie werden auch leugnen, dass sie von derselben Anwendung erzeugt wurden. Tipp: PC-Textverarbeitungsprogramme sind ein gutes Beispiel für dieses Verhalten.
     
  33. Ein beliebter Trick bei der Ungarischen Notation ist folgender: "Ändere den Typ einer Variablen, aber ändere nicht den Variablennamen." Dies findet sich z.B. durchgehend bei Windows-Anwendungen, die von Win16 auf Win32 portiert wurden: WndProc (HWND hW, WORD wMsg, WPARAM wParam, LPARAM lParam) wird in Win32 zu WndProc (HWND hW, UINT wMsg, WPRAM wParam, LPARAM lParam), wobei die w-Variablen eine Variable vom Typ word nahelegen, in Wirklichkeit aber vom Typ long sind. Den wahre Wert dieses Ansatzes werden wir wahrscheinlich erst begreifen, wenn die alten "w" und "l" Präfixe auch die Win64-Migration überlebt haben.
     
  34. Verlagere große Teile des Codes in Makefiles. Deine Nachfolger werden sehr beeindruckt sein, wie man Makefile schreiben kann, die Batch-Dateien generieren, die Header-Dateien generieren, um daraus die Anwendung bauen zu können, ohne dass man Aussagen darüber treffen kann, was Änderungen oder eine Migration auf eine moderne IDE bedeuten würde.
     
  35. Schreibe ein leeres Interface, z.B. "WrittenByMe". Lass alle Deine Klassen dieses Interface implementieren. Schreibe um alle verwendeten Java-Builtin-Klassen einen Wrapper. Grundidee: Jede verwendete Klasse soll dieses Interface implementieren. Schreibe alle Methoden so, dass die Rückgabewerte und Argumente vom Typ "WrittenByMe" sind. Dies macht es nahezu unmöglich herauszufinden, was eine Methode macht, und führt zu all den bekannten Cast-Anforderungen. Als weitere Erweiterungen kann jedes Team-Mitglied sein eigenes, persönliches Interface (z.B. "WrittenByJoe") besitzen. Man kann dann aus einer großen Anzahl bedeutungsloser Interfaces auf beliebige Objekte referrieren!

Letzte Änderung: 4. August 2002 von Oliver Böhm