Mit einem Klienten habe ich neulich eine Servlet mit mehreren 1000 Zeilen Code refactored.
Der Code war alle paar 100 Zeilen mit return Statements durchzogen. Ein einfaches extract method war nicht möglich. Nach ein wenig experimentieren haben wir das Either Pattern ausprobiert und der Code wurde schlanker und lesbarer. Ab hier war es Fleißarbeit. Im folgenden ist das Prinzip kurz erläutert:
Code vorher
String monsterMethod() {
{ /* block A severall 100 lines */ }
if(isBlockA) return „A“;
{ /* block B severall 100 lines */ }
if(isBlockB) return „B“;
{ /* block C severall 100 lines */ }
if(isBlockC) return „C“;
return „nothing“;
}
Code nachher
final var service = new MonsterMethodExtractedService(dependencies…);
String monsterMethod() {
final var eitherA = service.invokeBlockA(parameter…);
if(eitherA.isRight()) return eitherA.getRight();
// result is used in subsequent calls
final var leftA = eitherA.getLeft();
final var eitherB = service.invokeBlockA(leftA, parameter…);
if(eitherB.isRight()) return eitherB.getRight();
final var eitherC = service.invokeBlockA(leftA, parameter…);
if(eitherC.isRight()) return eitherC.getRight();
return „nothing“;
}
Wo ist beim Codebeispiel der Unterschied?
- Die Kommentarblöcke im „Code vorher“ verstecken mehrere 100 Zeilen Logik, die im Code nachher Block nicht mehr vorkommen. Die ursprüngliche Klasse schrumpft.
- Am Ende ist das, was gemacht wurde „nur“ ein extract Method (in eine eigene Klasse) und damit relativ harmlos.
- Das IOSP Prinzip wird angewendet. Dadurch erhöht sich die Testbarkeit der Klasse.
Was für Schwierigkeiten kennt ihr bei eigentlich einfachen Refactoringarbeiten? Wo seht ihr Möglichkeiten oder Schwierigkeiten bei der oberen Methode?