Samstag, 27. September 2014

Don't Repeat Yourself

Vermeidung von Redundanz gehört in vielen Bereichen der Informatik zu den Grundprinzipien eines guten Entwurfs. In Bezug auf Software haben sich eine Reihe weitgehend synonymer Bezeichnungen für dieses Prinzip eingebürgert: "Don't Repeat Yourself", "Single Point of Truth" und "Once and Only Once" zielen allesamt darauf ab, ein bestimmtes Wissen innerhalb des Systems nur ein einziges Mal zu repräsentieren. 

Ein fundamentales Prinzip

Wie fundamental das Prinzip ist, zeigt sich nicht nur an den diversen Benennungen, sondern auch an zahlreichen prominenten Technologien und Paradigmen, die wesentlich auf das Argument der Redundanzfreiheit zurückgeführt werden:
  • Das für das Paradigma der prozeduralen Programmierung elementare Konzept der Subroutine beruht wesentlich auf dem Gedanken, dass eine spezifische Funktionalität durch nur genau eine Subroutine umzusetzen ist, die von allen Nutzern aufgerufen werden soll.
  • Das Paradigma der aspektorientierten Programmierung beruft sich u. a. auf die Vermeidung des sogenannten Code Scattering, eine Verteilung immer gleicher oder sehr ähnlicher Codefragmente auf verschiedene Module. Aspekte bieten eine redundanzfreie Lösung dieses Problems an.
  • Das Verfahren der generischen Programmierung löst das Problem sich wiederholender Algorithmen, die sich lediglich hinsichtlich des Datentyps einzelner beteiligter Elemente unterscheiden.
  • Grundsätzlich kann von sinnvoller Wiederverwendung nur dann gesprochen werden, wenn diese ohne eine Duplizierung der wiederverwendeten Elemente auskommt. Dies ist der Kern des Reuse-Release Equivalence Prinzips
  • Das weite Feld modellgetriebener Entwicklungsansätze wird zentral durch das Bestreben motiviert, Wiederholungen durch den Einsatz spezieller Technologien wie Modellierungswerkzeuge, Generatoren, Interpreter usw. zu vermeiden.
Viele bekannte Autoren haben die besondere Bedeutung des Prinzips hervorgehoben. Es folgen einige beispielhafte Zitate:
"Duplikation ist womöglich die Quelle allen Unheils im Bereich der Software. Viele Prinzipien und Praktiken wurden entworfen, um sie zu kontrollieren oder zu beseitigen." Robert C. Martin, [Martin2008]
"Die mächtigste Design-Heuristik, die ich kenne, ist Once and Only Once." Kent Beck, [Beck2004]
"Ich denke, eine der wertvollsten Regeln ist die Vermeidung von Duplikation." Martin Fowler, [Fowler2002]

Welche Probleme entstehen durch Redundanz?

Durch Redundanz entstehende Probleme hängen hauptsächlich mit dem Problem der Synchronisierung zusammen. Hinzu kommt der erhöhte kognitive Aufwand, der durch die pure Anwesenheit von Duplikaten regelmäßig entsteht.
  • Synchronität: Existieren im Software-System mehrere Repräsentationen einer Information, so müssen alle Repräsentationen jederzeit synchron gehalten werden, wenn sich die Information ändert. Dies geht konkret mit folgenden Problemen einher:
    • Aufwand: Das Ändern mehrerer Repräsentationen wegen eines einzigen Änderungsgrunds geht mit unnötig hohem Aufwand einher.
    • Logische Widersprüche: Wird eine der Repräsentationen beim Synchronisieren übersehen, so können logische Widersprüche mit weitreichenden Folgen entstehen.
    • Fehlerpotential: Eine weitere mögliche Folge unvollständiger Synchronisation liegt in der Verursachung von Programmfehlern.
  • Verständlichkeit: Insbesondere wenn Redundanzen häufig vorkommen, wird die Verständlichkeit der Software beeinträchtigt. Grundsätzlich erhöhen Redundanzen den Umfang der zu pflegenden Artefakte, ohne dass der Informationsgehalt steigt. Zudem müssen Redundanzen auch als solche erkannt werden, um angemessen mit ihnen umgehen zu können. Durch diese Eigenschaften erhöhen Redundanzen den kognitiven Aufwand, der für den Umgang mit dem System erforderlich ist.

Umgang mit Ausnahmen

Im Abschnitt "Beispiel(e)" des unten folgenden Katalogeintrags werden auch zahlreiche wichtige Gegenbeispiele genannt. "Don't Repeat Yourself" ist folglich ein Prinzip, das in der Regel nicht ausnahmslos befolgt werden kann. Dann aber stellt sich die Frage, ob die Umstände für akzeptable Ausnahmen näher benannt werden können.

Da die Synchronisierung das Hauptproblem von Redundanzen darstellt, kann gefolgert werden, dass Verstöße gegen "Don't Repeat Yourself" tendentiell leichter akzeptiert werden können, wenn das Problem der Synchronisierung vergleichsweise leicht gelöst werden kann. Beispielsweise kann argumentiert werden, dass ein nicht angepasster Testfall automatisch fehlschlägt und somit auch seine baldige Synchronisierung bewirkt. Je weniger automatisiert und je aufwändiger Synchronisierungen erfolgen müssen, desto schwerwiegender sind Verstöße einzuschätzen.

Katalogeintrag


Name, Kurzform Don't Repeat Yourself
Synonyme
DRY,
Single Point Of Truth (SPOT),
Single Source Of Truth (SSOT),
Once and Only Once Prinzip,
Vermeide Wiederholungen
Beschreibung
Jede Wissenseinheit muss eine einzige, eindeutige, maßgebliche Repräsentation innerhalb eines Systems haben.“ [Hunt1999]
Erläuterung
Der große Vorteil dieser Formulierung von Andrew Hunt und David Thomas ist die allgemeine Anwendbarkeit des Prinzips, da nicht konkret benannt wird, um welche Art von „Wissenseinheit“ (engl. piece of knowledge) es sich handelt. Das Prinzip ist auf diese Weise auf Quellcode, Metadaten, Dokumentation und beliebige andere Artefakte anwendbar, die ein Software-System in seiner Gesamtheit ausmachen.

Oftmals findet man Varianten des Prinzips, die sich auf bestimmte Arten von Wissenseinheiten beziehen. Bspw. findet man die Bezeichnung „Single Source of Truth“ bevorzugt im Umfeld des Datenmanagements, während die Formulierung „Once and Only Once“ oftmals in Bezug auf das funktionale Verhalten eines Software-Systems verwendet wird. Zu den Stärken des Prinzips gehört es jedoch gerade, dass es sich auf die unterschiedlichsten Bestandteile von Software-Systemen anwenden lässt.

Die Abkürzung DRY wird im Englischen häufig im Sinne eines Adjektivs verwendet: „Keep your software DRY!“ Bei einem Verstoß hingegen ist die Softare WET (z. B. für „We Edit Twice/Too much“ oder „We Enjoy Typing“).
Beispiel(e
In der obigen Einleitung wurden bereits mit der prozeduralen, aspektorientierten und generischen Programmierung sowie mit dem Wesen der Wiederverwendung und modellgetriebenen Entwicklungsansätzen eine Reihe von Beispielen genannt. Daher folgen hier lediglich noch einige Gegenbeispiele:
  • Testen: Die Umsetzung von Testfällen basiert meist auf gewollten Redundanzen oder Wiederholungen.
  • Typsysteme: Der Verzicht einer Programmiersprache auf ein (statisches) Typsystem wird von den Schöpfern und Anhängern solcher Sprachen oftmals damit begründet, dass die Deklaration von Typen eine überflüssige Redundanz darstellt. Andererseits bieten Typsysteme auch zahlreiche Vorteile.
  • Performance: Die Inkaufnahme von Redundanzen kann ggf. auf Performance-Erwägungen basieren. Typisch sind Verstöße gegen Normalformen im Bereich der Datenbanken oder das Inlining performancekritischer Funktionen in ein lokales Modul.
  • Abhängigkeiten: Bewusste Redundanzen wurden im Kontext der Durchbrechung von Zyklen als ein ausnahmsweises Mittel zur Beseitigung von Abhängigkeiten erwähnt. Auch hier ist das Inlining bestimmter (möglichst trivialer) Code-Elemente in ein lokales Modul die Lösung. In diesem Fall wird der durch die Redundanz eingeführte Verstoß gegen „Don't Repeat Yourself“ durch den Nutzen rechtfertigt, der durch die erreichte Zyklenfreiheit entsteht.
  • Requirements: Bis heute ist es in der Praxis nur sehr selten möglich, die Erfassung von Anforderungen mit der systemseitigen Umsetzung zu so zu synchronisieren, dass nur noch eine maßgebliche Repräsentation entsteht. Auch Ansätze aus dem Bereich der modellgetriebenen Entwicklung, die in diese Richtung streben, leisten dies bestenfalls ansatzweise.
Historie
  • Eine frühe Quelle stammt bereits aus dem Jahr 1983. In seinem Buch über Prinzipien im Bereich der Programmiersprachen schreibt Bruce J. MacLennan: "Vermeide es, dass etwas mehr als einmal ausgedrückt werden muss; extrahiere das wiederkehrende Muster." [MacLennan1983] MacLennan formuliert dies im Kontext von Abstraktionen, die er als Lösung für Wiederholungen ansieht.
  • Einige prominente Autoren erwähnen das Prinzip im Jahr 1999: 
    • Unter der Namen „Don't Repeat Yourself“ wird das Prinzip in dem populär gewordenen Buch „The Pragmatic Programmer" ausführlich behandelt. [Hunt1999]
    • In „The Practice of Programming“ wird (wenn auch eher beiläufig) von „Single Point of Truth“ gesprochen. [Kernighan1999]
    • In "Refactoring: Improving the Design of Existing Code" schreibt Martin Fowler: "Durch die Beseitigung von Duplikaten wird sichergestellt, dass der Quellcode alles nur genau einmal (engl. Original: once and only once) ausdrückt, was die Essenz eines guten Designs ist." [Fowler1999]
  • Die Formulierung von Kernighan und Pine greift Eric S. Raymond in „The Art of Unix Programming“ im Jahr 2003 auf und spricht von „The SPOT Rule“. Er bevorzugt diese Bezeichnung explizit gegenüber „Don't Repeat Yourself“. [Raymond2003]
  • Ebenfalls 2003 bevorzugt Kent Beck die Bezeichnung "Once and Only Once" [Beck2003]. Im Bereich des Extreme Programming ist daher diese Benennung etablierter.
  • In „Clean Code: A Handbook of Agile Craftmanship“ (2008) entscheidet sich Robert C. Martin für die Bezeichnung „Don't Repeat Yourself“. Womöglich ist es – neben dem Wortspiel um die Abkürzung DRY – Martins Ansehen im Bereich der Prinzipien zu verdanken, dass man das Prinzip heute am häufigsten unter dieser Bezeichnung antrifft.
Art des Prinzips
  • Grundlegende Einteilung: Produkt.
  • Technologiebezug: Allgemeingültig.
  • Entwurfsgüte: Strukturprinzip.
  • Handlungsbezug: Erleichterung von Änderung und Wiederverwendung.
  • Kognitionsbezug: Komplexitätsreduktion.
(Siehe Kategorisierung der Prinzipien.)
Grad der formalen Spezifikation Nur für bestimmte Formen der Redundanz hoch. Beispielsweise lassen sich Redundanzen im Quellcode mit diversen Analysewerkzeugen aufspüren. Hingegen lassen sich andere Formen der Redundanz wie z. B. eine Repräsentation im Quellcode, die redundant zu einer UML-Repräsentation ist, praktisch nicht automatisiert erkennen. Auch kann im Einzelfall strittig sein, ob eine Ähnlichkeit als Redundanz zu werten ist.
Vorteile
  • Fundamentale Bedeutung.
  • Globaler Anwendungsbereich.
  • Leicht verständlich und anwendbar.
Nachteile
  • Ausnahmen können nicht ausgeschlossen werden.
Übergeordnete Prinzipien -
Abgleitete Prinzipien Convention over Configuration

Verwandt: Abstraktionsprinzip, Lokalitätsprinzip
Qualitätsmerkmale
(+) Änderbarkeit, (+) Wartbarkeit,
(+) Verständlichkeit, (+) Wiederverwendbarkeit,
(+) Komplexität, (+) Korrektheit
 

Quellen

[Beck2004] - Extreme Programming Explained: Embrace Change, Kent Beck, Cynthia Andres (2004)

[Fowler1999] - Refactoring: Improving the Design of Existing Code, Martin Fowler (1999)


[Fowler2002] - Design Principles and Code Ownership. A Conversion with Martin Fowler by Bill Venners, Part II, siehe http://www.artima.com/intv/principles.html

[Hunt1999] - The Pragmatic Programmer, Andrew Hunt, David Thomas (1999)

[MacLennan1983] - Principles of programming languages: design, evaluation, and implementation, Bruce J. MacLennan (1983)

[Martin2008] - Clean Code: A Handbook of Agile Craftmanship, Robert C. Martin (2008)

[Raymond2003] - The Art of Unix Programming, Eric S. Raymond (2003)