Dienstag, 1. März 2011

DRY Coding

DRY (Don’t repeat yourself) ist ein Grundprinzip von Clean Code. DRY ist in allen Entwicklungsphasen anwendbar. Im Design bei der Komposition von Komponenten, bei der Datenmodellierung stellvertretend durch die Normalisierung und bei der Implementierung durch die Wiederverwendung von Quellcode.

Nichts ist einfacher als mit „Copy & Paste“ gegen DRY zu verstoßen. Der Sumpf der dabei entsteht wird immer größer und führt häufig zu schlechter Evolvierbarkeit und Inkonsistenzen einhergehend mit höherer Fehleranfälligkeit. Ein Verstoß gegen DRY hat eine höhere Abhängigkeit im Quellcode zur Folge, eine geringere Isolation von Komponenten und schlechtere Testbarkeit. Zusätzliche Arbeit durch höhere  Komplexität sind die Folgen von DRY. Änderungen in einem System sollen deshalb nur einmal durchgeführt werden. Die Gefahr ein Quellcode-Duplikat zu vergessen und damit verbunden eine Änderung während der Weiterentwicklung zu übersehen ist stets gegeben.

DRY einzuhalten ist ein fester Bestandteil des TDD Mantras und wird regelmäßig als integrierter Schritt beim Schreiben von Testfällen ausgeführt. Patterns wie Template Method helfen Duplikate beim Refactoring zu eliminieren. Abstraktionen und generische Strukturen sind mächtige Mittel, um das DRY Prinzip einhalten zu können.

Die Wiederverwendung von Quellcode durch Refactoring ist nicht auf Makrokomponenten beschränkt. Grundsätzlich findet ein Refactoring zunächst auf der Mikroebene statt, mit dem Ziel die innere Struktur eines Softwarebausteins zu verbessern. Selbst einzelne Quellcodezeilen und die Bündelung kleiner Methoden können durch das DRY Prinzip die Komplexität im Quellcode verringern und dadurch die Wartbarkeit verbessern. Es ist deshalb eine gute Praxis die gängigen Java Idiome und APIs zu nutzen.

Java Syntax verhindert DRY auf dem Abstraktionslevel einer Methode:

public double calculateProduct(double factor) {
        
    product = product * factor;
       
    return product; 
}

public double calculateProduct(double factor) {
       
    product *= factor;
       
    return product;
}

Java Idiom (Static Factory Method) verhindert DRY bei der Definition einer Datenstruktur:

private Map<Double, List<Double>> products = new HashMap<Double, List<Double>>();

private Map<Double, List<Double>> products = Products.newInstance();

In Java 7 sind "Static Factory Methods" als Problemlösung für das DRY Prinzip überflüssig. Die neue Java Diamant Syntax (Diamond) ist für diesen Fall die beste Lösung.

private Map<Double, List<Double>> products = new HashMap<>();

Interessant ist, dass in der Methode "getProduct" das Attribut "product" verwendet wird. In diesem Fall wird gegen das Single Level of Abstraction (SLA) Prinzip verstoßen. Die weitläufige Verwendung von Attributen in den Methoden einer Klasse, führt wie DRY zu geringerer Isolation und darüber hinaus zu schlechterer Lesbarkeit des Quellcodes.

Im Java-Umfeld birgt der Verstoß gegen SLA die Gefahr in sich Memory Leaks zu erzeugen. Dieses Phänomen tritt durch Objektreferenzen auf, die über einen langen Zeitraum hinweg als Attribute in der Instanz einer Klasse gehalten werden. Der Garbage Collector gibt den Speicher, der durch Instanzen belegt wird, nicht frei sofern noch Referenzen auf die Instanzen verweisen. Zirkulare Referenzen können dabei eine Referenzinsel bilden, die es dem Garbage Collector besonders schwer machen Speicher freizugeben. Die Zuweisung von "null" nach der Benutzung von Referenzen hilft zwar dem Garbage Collector bei der Freigabe des Speichers, verschlechtert auf der anderen Seite aber die Lesbarkeit des Quellcodes.

Es ist deshalb eine gute Praxis SLA anzuwenden und dabei den natürlichen Mechanismus der Speicherfreigabe zu nutzen. Dieser Mechanismus tritt in Kraft, sobald eine lokale Variable, die eine Referenz auf eine Instanz hält, "Out of Scope" ist (Methode wurde beendet). SLA und damit verbunden eine Referenzvariable im kleinstmöglichen "Scope" zu verwenden fördert im Java-Umfeld deshalb nicht nur die Lesbarkeit sondern schont Resourcen.


Der Rechtshinweis des Java Blog für Clean Code Developer ist bei der Verwendung und Weiterentwicklung des Quellcodes des Blogeintrages zu beachten.