Basics – Trockenes Einzelstück

Hallo Spaß-Coder,

im Artikel Basics? Kenn’ ich doch schon! haben wir begründet, warum grundlegende Programmierpraktiken sinnvoll und hilfreich sind.

Eine wichtiger Punkt in der objektorientierten Programmierung ist die Wiederverwendbarkeit unseres Codes. Darüber möchten wir im Folgenden ein wenig sprechen.

Don’t Repeat Yourself

Anders als beim Lernen, wo ständige Wiederholung das zu Lernende festigt, ist es bei der Programmierung so, dass jede Art der Wiederholung schädlich für unseren Code ist. Genauso wie beim Lernen manifestiert sich bei Wiederholungen der Code in den tiefsten Winkeln unserer Projekte. Allerdings nicht mit dem charmanten Vorteil, dass dieses Wissen schnell hervorgeholt werden kann, sondern vielmehr vergessen und explosiv vergraben im Untergrund.

Dieser Code ist gefährlich. Ist es euch nicht auch schonmal passiert, dass ihr ein Programm umstrukturieren musstet um dabei den gleichen Code wieder und wieder anzupassen? Wie viele Stellen habt ihr dabei übersehen, die dann später zur Laufzeit zu Problemen führten (na komm, seid ehrlich zu euch selbst 😉 )?

Das Prinzip Don’t Repeat Yourself setzt genau an dieser Stelle an. Es besagt, dass eine Umsetzung im Code nur genau einmal („Once and only once“) erfolgen soll.

Duplizierter Code == böser Code

Das heißt, dass wir duplizierten Code vermeiden sollen. Wenn wir also Stellen in unserem Code haben, die wir an unterschiedlichen Stellen aber im Grunde genau gleich implementiert haben, sollten wir uns einen Moment Zeit nehmen, und diesen Code refakturisieren, damit wie Änderungen an diesem Code ebenfalls nur genau einmal durchführen müssen.

Ich habe mal ein Beispiel aus einem seeeehr alten Projekt von uns ausgegraben. Es handelt sich um die Initialisierungsroutine unseres allerersten Spiels, BreakXPress (allerdings die dritte Implementierung, diesmal in .Net und mit neuer Engine).

Nehmt euch mal eine oder zwei Minuten um den Code zu lesen und zu verstehen? Was fällt euch auf, wenn ihr euch diesen Code anschaut? Richtig, hier ist sehr viel doppelt.

Es wird ein Spieler initialisiert, dann ein Score-Text für diesen Spieler. Und wenn es einen weiteren Spieler gibt, wird der gesamte Code nochmal wiederholt. Lediglich einzelne Positionsangaben sind anders.

Fällt euch auch der versteckte Fehler auf? In diesem Code wurde eine Änderung durchgeführt, aber nicht an allen Stellen richtig und sauber. Wer genau hinschaut stellt fest, dass der Scale und das Spacing des Score-Objekts beim zweiten Spieler mit .55 festgelegt wird. Beim ersten Spieler aber mit .65. Ob das Absicht war? Sicherlich nicht, warum sollten die Punkte des einen Spielers kleiner angezeigt werden als die des anderen?

Ich habe den Code mal refaktorisiert. So sollte er deutlich besser lesbar und vor allen einfacher – und fehlerfreier – zu ändern sein:

Der Code der Methode CreatePlayer(…) lässt sich sicherlich noch optimieren (hier sind vor allem zu viele new-Aufrufe enthalten), aber dem Prinzip DRY sind wir mit diesem Code schon einen sehr großen Schritt näher gekommen.
Implizit habe ich auch noch eine andere Wiederholung eliminiert. Im alten Code gab es mehrfach den Aufruf PlayerManager.GetPlayerByIndex(0), etwa um die Farbe oder die Punktzahl des Spielers abzurufen. Diesen Aufruf habe ich nun einmal durchgeführt und am Anfang der Methode in einer Variable player gespeichert.

Unterm Strich ist der Code in der Methode Initialize() nun deutlich leichter lesbar und der Code der Methode CreatePlayer(…)  muss – im Falle des Falles – nur einmal geändert werden.

Duplizierte Algorithmen vermeiden

Das gleiche, was generell für unseren Code gilt, gilt auf einer etwas höheren Abstraktionsebene auch für Algorithmen. Wenn wir einmal eine State-Machine gebaut haben und brauchen dann – ggf. sogar in einem anderen Projekt – ebenfalls eine State-Machine mit den gleichen Anforderungen, wäre es ein guter Zeitpunkt darüber nachzudenken, ob die Implementierung der State-Machine nicht in einer Bibliothek verallgemeinert werden kann um dann von beiden Projekten genutzt zu werden.

Wenigstens, wenn man eine solche Situation in einem Projekt vorfindet, sollte man diese gemeinsamen Konzepte nur einmal implementieren. Es gelten die gleichen Gründe wie auch beim doppelten Code:

  • Änderungen müssen nur einmal durchgeführt werden
  • Fehler müssen nur einmal gefunden und behoben werden
  • der Algorithmus muss nur einmal getestet werden
  • Brauche ich oder ein anderer Entwickler eine solche Funktion an anderer Stelle, muss sie nicht nochmal implementiert werden

Zusammenfassung
Wiederholt euch nicht, sagt was ihr zu sagen habt, aber sagt es nur genau einmal – dann aber richtig und geprüft. Dadurch wird das Leben für euch und alle Programmierer die mit eurem Code arbeiten einfacher.

Viel Spaß beim Anwenden
Eure Spaß-Coder

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert