Aus gegebenem Anlass möchte ich mal auf einen kritischen Blick auf eins der Prinzipien werfen, das bei Ruby so gerne zitiert, aber gerne auch missverstanden wird: DRY.

DRY ist das wohl am häufigsten genannte Prinzip, wenn es um Ruby-Programmierung geht. Allerdings würde ich auch behaupten, dass es auch häufig missverstanden wird. Es geht bei DRY nämlich nicht darum, möglichst wenig zu schreiben, sondern darum, Redundanz zu vermeiden. Konkret soll jedes Stück Wissen des Systems nur an einer Stelle im Code erwähnt werden. Deswegen nannt man die Idee hinter DRY auch Single Point of Truth.
Ein Beispiel:
1 2 3 4 5 6 7 |
class Address < ActiveRecord::Base validates_presence_of :name validates_presence_of :street validates_presence_of :number validates_presence_of :city validates_presence_of :postalcode end |
Wiederholt sich häufig, ist aber trotzdem DRY. Sicher, folgende Version ist kürzer und natürlich genauso korrekt:
1 2 3 |
class Address < ActiveRecord::Base validates_presence_of :name, :street, :number, :city, :postalcode end |
Aber sie hat Nachteile bei zweifelhaftem Gewinn: ich kann zum Beispiel keine Validierungen mal schnell auskommentieren, sondern müsste den Namen gleich löschen. Genauso muss ich die Statements gleich wieder aufsplitten, wenn ich unterschiedliche Meldungen für unterschiedliche Felder haben will. Lösung 2 ist shorthand und damit auch gerne mal erlaubt, aber nicht stärker dem DRY-Prinzip folgend als 1.
Um also auf die häufig gestellte Frage zurück zukommen: wie löse ich das DRY? Garnicht! Denn
Und last but not least:
6. ist einfach beantwortet:
1 2 |
name = self.name
name.nil? || name.empty? |
Was unseren Code jetzt DRY macht, ist der Umstand, dass wir diesen Codeschnipsel nicht immer und überall wieder verwenden, sondern einmal in eine Methode fassen, die diesen Validierungsschritt hübsch gekapselt in eine Validierungsliste legt (
Die Information, dass die 5 Attribute dieser speziellen Klasse validiert werden müssen, befindet sich bereits in beiden Statements oben - und ist DRY.
Ich gehe manchmal sogar soweit und wende das auf requires und verlange zum Beispiel beim laden einer Klasse alle Abhängigkeiten explizit:
1 2 3 4 5 6 7 8 |
require 'my_module' require 'my_referenced_class' class MyClass include MyModule #hier wird noch irgendwo MyReferencedClass verwendet end |
Das hat den Vorteil, dass ich jede Klasse einzeln laden kann, ohne gleich die komplette Bibliothek zu laden. Das mag auf den ersten Blick etwas nach den hässlichen Java-Imports aussehen und dient mir auch zu einen ähnlichen Zweck: es ist sofort ersichtlich, von welchen Systemelementen diese Klasse essentiell abhängt. Insofern wiederhole ich mich nicht einfach nur, sondern füge dem System eine (schwache) Information hinzu.
Die Essenz ist: Kurz ist nicht zwingend trockener als verbos, wichtig ist der Informationsgehalt.
Kommentar schreiben
Kommentare
Sehr schön auf den Punkt gebracht.
Man kann das ganze natürlich auch wie folgt schreiben: validates_presence_of :name :street, :number, :city, :postalcode Da bleibt dann immer noch die Möglichkeit, einzelne Zeilen auszukommentieren.
Leider hat die Blog-Software meine Umbrüche in meinem vorherigen Kommentar entfernt. Eingegeben hatte ich im Code-Schnipsel Umbrüche nach jedem Komma.
Selbstverständlich ;). Aber ich hatte das auch mehr als plakative Illustrierung gedacht. Eventuell wäre ein etwas durchdachteres Beispiel angebrachter gewesen.
Noch ein aktueller Beitrag dazu von Jim Weirich: "Nitpicking perhaps, but I feel DRY is often used for justifying stuff that it was never meant to cover. (Consider this a DRY best practice :)."