Refactoring: Eine Methode mit einem Methodenobjekt ersetzen

Howto Refactoring: Eine Methoden mit mehreren Methodenvariablen in kleinere Einheiten zerlegen.

Heute möchte ich meine neue Artikelserie einläuten: Refactoring. Dabei werde ich in unregelmäßigen Abständen Tipps und Tricks dazu veröffentlichen. Der erste geht im speziellen an meinen Freund Eggi, der viel mit von Kollegen geerbten Legacy Code zu kämpfen hat:

Wer kennt sie nicht, viel zu lange Methoden. Mit Variablen die am anfang deklariert, in der Mitte 5x verändert und am Ende zurückgegeben werden sollen. Und dann auch noch 2 oder mehr von den Dingern!

Ok es müssen nicht 5 davon sein, und die Methode noch nichtmal lange. Ein schnelles, bewusst sehr simples Beispiel: Einfach mal versuchen die beiden Zuweisungen mittels Eclipse -> Extract Method als neue private Method rausziehen.

package test;

public class ToMuchVarMethod {
	
	public void shortExample(){
		
		int i = 1;
		int j = 1;
		
		i = 2;
	    j = 2;
	    
	    System.out.println(i +" "+ j);
	}

}

Die neue Methode wird einem mit der Meldung „Ambiguous return value: Selected block modifies more than one local variable used in subsequent code.“ versagt.

Was also tun? Nun es mag in dem hier gewählten Beispiel nicht besonders schlau wirken, aber eine saubere Lösung wäre es, die Methode in ein eigenes Objekt umzuwandeln. Man muss dazu den Scope der lokalen Methodenvariablen ändern und sie zu Instanzvariablen dieses Objektes werden lassen. Als nächsten Schritt gilt es, die lange Methode in einzelne Methoden innerhalb des neuen Objekts aufzusplitten. Die neue Klasse bietet dann eine Startmethode an wie z.B. compute() oder run() und bildet darin durch die einzelnen Methodenaufrufe die alte Methode nach.

So entsehen gut testbare Units und klare logische Abgrenzungen was in den einzelnen Methoden passiert.

Auch wenn es in dem hier angeführten Beispiel zu mehr Zeilen Code führt und somit etwas aufgebläht wirkt, bedient man dabei doch folgende zwei Prinzipien, die zu einem besser lesbaren, verständlicheren und damit besser wartbaren Code führen:

Hier noch das Beispiel von oben aufgesplittet in

das Aufrufende Objekt:

package test;

public class ToMuchVarMethod {
	
	public void shortExample(){
		
		ShortExample e = new ShortExample(1, 1);
		e.compute();
	}

}

und Methodenobjekt:

package test;

public class ShortExample {
	
	private int i;
	private int j;
	
	ShortExample(int i, int j){
		this.i = i;
		this.j = j;
	}
	
	private void setToTwo(){
		this.i = 2;
		this.j = 2;
	}
	
	private void print(){
		System.out.println(this.i + " "+ this.j);
	}
	
	public void compute(){
		setToTwo();
		print();
	}

}

Ähnliche Artikel:

Kleine Java Tips: Einfach über eine Map iterieren

Ist man von früher gewohnt über das KeySet zu iterieren um alle Elemente einer Map aufzurufen, wird hier ein neuer Weg über das EntrySet und foreach gezeigt.

Hat man eine Map und muss nicht nur mit einem Element sondern mit allen Elementen die die Map beinhaltet weiterarbeiten, ist ein gebräuchlicher Weg über den KeySet der Map zu iterieren

for (Iterator it = map.keySet().iterator(); it.hasNext(); ){
    Object key = it.next();
    Object vlaue = map.get(key);
}

Seit Java 1.5, und damit eigentlich schon recht lange, gibt es jedoch einen bequemeren Weg. Die foreach Schleife in Java funktioniert mit allen Objekten die Iterable implementieren, und somit auch mit dem EntrySet einer Map.

for (Entry e : map.entrySet()){
    e.getKey();
    e.getValue();
}

So bekommt man zu einem viel übersichlicherem Code, der obendrein noch äußerst geschmeidig wirkt :D

Ganz hilfreich ist dabei der im TryCatchFinally Blog veröffentlcihte Artikel, der Zeigt wie man dafür ein schnell zu verwendendes Template in Eclipse anlegt:

http://blubberbart.blogspot.com/2011/04/eclipse-code-template-uber-eine-map.html

Happy Coding!

Ähnliche Artikel: