Temporọre Variable durch Abfrage ersetzen

Một phần của tài liệu AW refactoring improving the design of existing code (Trang 141 - 145)

Sie verwenden eine temporọre Variable, um das Ergebnis eines Ausdrucks zu spei- chern.

Extrahieren Sie den Ausdruck in eine Methode. Ersetzen Sie alle Referenzen der Variablen durch den Aufruf der Methode. Die neue Methode kann dann in anderen Methoden be- nutzt werden.

6.4.1 Motivation

Das Problem mit temporọren Variablen ist, dass sie temporọr und lokal sind. Da sie nur im Kontext der Methode zu sehen sind, in der sie benutzt werden, fửrdern sie das Schreiben langer Methoden, weil das der einzige Weg ist, sie zu verwen- den. Ersetzt man die temporọre Variable durch eine Abfrage, so kann jede Me- thode der Klasse an diese Information herankommen. Das fửrdert sehr die Entste- hung klareren Codes in der Klasse.

Temporọre Variable durch Abfrage ersetzen (117) ist oft ein absolut notwendiger Schritt vor Methode extrahieren (106). Lokale Variablen machen das Extrahieren schwierig, versuchen Sie also, so viele Variablen durch Abfragen zu ersetzen, wie Sie kửnnen.

double basePrice = _quantity * _itemPrice;

if (basePrice > 1000) return basePrice * 0.95;

else

return basePrice * 0.98;

if (basePrice() > 1000) return basePrice() * 0.95;

else

return basePrice() * 0.98;

...

double basePrice() {

return _quantity * _itemPrice;

}

In den einfachen Fọllen dieser Refaktorisierung werden die temporọren Variablen nur einmal zugewiesen, oder der Ausdruck, der zugewiesen wird, ist frei von Sei- teneffekten. Andere Fọlle sind schwieriger, aber auch mửglich. Es kann sein, dass Sie zunọchst Temporọre Variable zerlegen (125) oder Abfrage von Verọnderung trennen (285) einsetzen mỹssen, um die Verhọltnisse zu vereinfachen. Wird die temporọre Variable verwendet, um ein Ergebnis zu sammeln (wie eine Summe in einer Schleife), so müssen Sie einige Logik in die Abfragemethode kopieren.

6.4.2 Vorgehen

Hier ist der einfachste Fall:

• Suchen Sie eine temporọre Variable, der einmal etwas zugewiesen wird.

Wird eine temporọre Variable mehr als einmal gesetzt, so sollten Sie erwọgen, Temporọre Variable zerlegen (125) einzusetzen.

• Deklarieren Sie die Variable als final.

• Wandeln Sie den Code um.

Das stellt sicher, dass die Variable wirklich nur einmal gesetzt wird.

• Extrahieren Sie die rechte Seite der Zuweisung in eine Methode.

Deklarieren Sie die Methode zunọchst als privat. Sie kửnnen spọter weitere Ver- wendungsmửglichkeiten finden, aber es ist ein Leichtes, den Schutz zu reduzieren.

Stellen Sie sicher, dass die extrahierte Methode frei von Seiteneffekten ist, d.h. dass sie kein anderes Objekt verọndert. Ist sie nicht frei von Seiteneffekten, verwenden Sie Abfrage von Verọnderung trennen (285).

• Wandeln Sie um und testen Sie.

• Wenden Sie Temporọre Variable durch Abfrage ersetzen (117) auf die temporọre Variable an.

Temporọre Variablen werden họufig verwendet, um zusammenfassend Informati- onen in Schleifen zu speichern. Die ganze Schleife kann in eine Methode extra- hiert werden; das entfernt einige Zeilen stửrenden Codes. Manchmal dient eine Schleife dazu, mehrere Werte aufzusummieren. In diesem Fall duplizieren Sie die Schleife fỹr jede temporọre Variable, so dass Sie jede temporọre Variable durch eine Abfrage ersetzen kửnnen. Die Schleife sollte sehr einfach sein, so dass mit der Duplikation des Codes wenig Gefahren verbunden sind.

Sie mửgen sich in diesem Fall Sorgen ỹber die Performance machen. Lassen Sie dies wie auch andere Performance-Fragen fỹr den Augenblick auòer Betracht. In neun von zehn Fọllen wird es keine Rolle spielen. Und wenn es eine Rolle spielt, beheben Sie das Problem wọhrend der Optimierung. Mit Ihrem besser refaktori- sierten Code werden Sie oft leistungsfọhigere Optimierungen finden, die Sie ohne Refaktorisieren ỹbersehen họtten. Wenn alles schief geht, kửnnen Sie immer noch leicht die temporọre Variable wieder einfỹhren.

6.4.3 Beispiel

Ich beginne mit einer einfachen Methode:

double getPrice() {

int basePrice = _quantity * _itemPrice;

double discountFactor;

if (basePrice > 1000) discountFactor = 0.95;

else discountFactor = 0.98;

return basePrice * discountFactor;

}

Ich neige dazu, beide temporọren Variablen auf einmal zu ersetzen.

Obwohl es in diesem Fall ziemlich klar ist, kann ich testen, ob beiden temporọren Variablen nur einmal zugewiesen wird, indem ich sie als final deklariere.

double getPrice() {

final int basePrice = _quantity * _itemPrice;

final double discountFactor;

if (basePrice > 1000) discountFactor = 0.95;

else discountFactor = 0.98;

return basePrice * discountFactor;

}

Das Umwandeln wird mich auf etwaige Probleme hinweisen. Ich mache dies als erstes, denn wenn es ein Problem gibt, so sollte ich diese Refaktorisierung nicht durchfỹhren. Ich extrahiere deshalb nur jeweils eine temporọre Variable. Zuerst extrahiere ich die rechte Seite der Zuweisung:

double getPrice() {

final int basePrice = basePrice();

final double discountFactor;

if (basePrice > 1000) discountFactor = 0.95;

else discountFactor = 0.98;

return basePrice * discountFactor;

}

private int basePrice() {

return _quantity * _itemPrice;

}

Ich wandle um und teste, dann beginne ich mit Temporọre Variable durch Abfrage (117) ersetzen. Als erstes ersetze ich die erste Referenz auf die temporọre Variable:

double getPrice() {

final int basePrice = basePrice();

final double discountFactor;

if (basePrice() > 1000) discountFactor = 0.95;

else discountFactor = 0.98;

return basePrice * discountFactor;

}

Umwandeln, testen und die nọchste (das hửrt sich an wie der Anfỹhrer bei einer Polonaise). Da dies die letzte Referenz ist, entferne ich auch gleich die Deklaration der temporọren Variablen:

double getPrice() {

final double discountFactor;

if (basePrice() > 1000) discountFactor = 0.95;

else discountFactor = 0.98;

return basePrice() * discountFactor;

}

Nachdem diese Deklaration verschwunden ist, kann ich mit discountFactor ọhn- lich verfahren:

double getPrice() {

final double discountFactor = discountFactor();

return basePrice() * discountFactor;

}

private double discountFactor() { if (basePrice() > 1000) return 0.95;

else return 0.98;

}

Beachten Sie, wie schwierig es gewesen wọre, discountFactor zu extrahieren, wenn ich basePrice nicht durch eine Abfrage ersetzt họtte.

Die getPrice-Methode sieht nun so aus:

double getPrice() {

return basePrice() * discountFactor();

}

Một phần của tài liệu AW refactoring improving the design of existing code (Trang 141 - 145)

Tải bản đầy đủ (PDF)

(468 trang)