2008-10-16 7 views
5

Ich habe diese gigantische veraltete Java Web App mit Struts 1.2.4 geerbt. Ich habe eine spezifische Frage zu Aktionen. Die meisten Seiten haben genau eine Aktion, und die processExecute() -Methoden sind scheußliche Monster (sehr lange und viele verschachtelte if-Anweisungen basierend auf Anfrageparametern).Wie mit monströsen Struts-Aktionen umgehen?

Da Aktionen eine Implementierung des Befehlsmusters sind, denke ich, diese Aktionen in eine Aktion pro Benutzergeste zu unterteilen. Das wird aber ein großes Refactoring sein und ich frage mich:

  1. Ist das die richtige Richtung?
  2. Gibt es einen Zwischenschritt, den ich annehmen könnte, ein Muster, das sich mit dem Chaos innerhalb der monolithischen Aktionen beschäftigt? Vielleicht ein anderes Befehlsmuster in der Action?

Antwort

9

Mein Weg des Umgangs mit dieser wäre:

  • dont do 'alles auf einmal'
  • , wenn Sie etwas ändern, lassen Sie es besser als Sie es gefunden
    • ersetzt conditionals mit separaten Action-Implementierungen ist ein Schritt.
    • Noch besser wäre es: Machen Sie Ihre Implementierungen von den Action-Klassen trennen, so dass Sie es verwenden können, wenn Sie Frameworks ändern
    • Halten Sie Ihre neue Implementierung Befehl absolut ohne Verweise auf Struts, verwenden Sie Ihre neue Aktionen als Wrapper um diese Implementierungen.
    • Sie müssen möglicherweise Schnittstellen zu Ihren Struts ActionForms bereitstellen, um sie zu übertragen, ohne alle Daten zu kopieren. Auf der anderen Seite - Sie könnten um andere Objekte als Actionübergeben wollen, die in der Regel eine Reihe von Strings sind
  • Start Teile auf neuere & bessere Technologie (Ihre andere Frage über Struts 1.2 ActionForms sehen) migrieren. Struts 1.2 war großartig, als es herauskam, aber ist definitiv nicht das, was du in der Ewigkeit unterstützen willst. Es gibt jetzt einige Generationen von besseren Frameworks.

Es gibt definitiv mehr - Sorry, ich bin hier nicht mehr viel Zeit ...

1

Tough Problem, aber typisch für die frühen Web-App-Entwicklung.

Zuerst müssen Sie anfangen darüber nachzudenken, welche Logik das Geschäftsverhalten ausmacht, welche Logik den "Fluss" darstellt (d. H. Was der Benutzer sieht) und welche Logik den Inhalt für das erhält, was er sieht.

Sie müssen nicht die Route von Fabriken und Schnittstellen und all das gehen; eine rückwirkende Implementierung ist viel weniger nützlich ... aber die Konsolidierung von Geschäftslogik und Datenabruflogik in Delegaten irgendeiner Art ... und das Verlassen der Struts-Aktionen, um den Seitenfluss basierend auf Erfolg/Fehlschlag dieser Logik zu bestimmen.

Von dort Sie nur ein paar Wochen in Anspruch nehmen müssen, und es mahlt

1

Eine lange Methode ist nie gut, wenn es eine einzige Switch-Anweisung sein geschieht, wo die Fälle sehr kurz sind (Token-Parsing oder so ähnlich Das).

Sie könnten die lange Methode zumindest in kleinere Methoden mit beschreibenden Namen umgestalten.

Wenn möglich, könnten Sie Ihre Methode mit der Erkennung beginnen, was es tun soll, indem Sie das Formular untersuchen, und dann, wenn Sie zu den verschiedenen Optionen gelangen. Keine verschachtelten ifs, diese neigen dazu, Code unlesbar zu machen. Nur

enum Operation { 
    ADD, DELETE; 
} 

... 

Operation operation = determineOperation(form); 
if (operation == Operation.DELETE) { 
    doDelete(form); 
} else if (operation == Operation.ADD) { 
    doAdd(form); 
} 

Wenn Sie so weit gehen kann, haben Sie Ihre Logik schön und sauber, und Sie können tun, was Refactoring Sie wollen.

Der schwierige Teil ist, Ihre Logik klar zu machen, und Sie können das in Schritten tun. Wähle kein Muster, bis du genau verstanden hast, was dein Problem ist.

1

Wenn Sie den Code umgestalten möchten, sollten Sie zuerst Tests für den vorhandenen Code schreiben, damit Sie sicher sein können, dass Sie die Funktionalität nach dem Refactoring nicht geändert haben.

+0

Ich werde sagen Pshah. Der Autor stellt fest, dass die Methoden monströs lang sind und eine hohe zyklomatische Komplexität haben. Diese Art von Code ist oft ein Albtraum für den Komponententest. – JonMR

2

Ich habe diese Art von Sache schon einmal behandelt. Ein guter erster Schritt ist das Einfügen einer anderen Basisklasse in die Vererbungskette zwischen Aktion und einer der ursprünglichen monströsen Aktionsklassen (nennen wir sie ClassA). Vor allem, wenn Sie keine Zeit haben, alles auf einmal zu machen. Dann können Sie Teile der Funktionalität in kleinere parallele Aktionsklassen (ClassB, ClassC) einfügen. Alles, was zwischen dem ursprünglichen ClassA und den neuen refaktorierten Klassen üblich ist, kann in die neue Basisklasse übernommen werden. Also sieht die Hierarchie jetzt so aus:

Original Hierarchy:  New Hierarchy: 

    Action     Action 
     |      | 
     |      BaseA 
    (old)ClassA     | 
         +--------+----------+ 
         |  |   | 
        ClassB (new)ClassA ClassC 
+0

Lesen Sie meine Antwort oben für Gedanken über eine Aktionshierarchie. Ich denke, an vielen Stellen, die das tun, haben sie wahrscheinlich zu viel Geschäftslogik in ihrer Webschicht. – bpapa

5

Struts-Aktionen, in meinen Gedanken sollte nicht sehr viel Code in ihnen überhaupt haben. Sie sollten nur direkt mit der Anfrage und der Antwort interagieren - einige Daten aus einem Formular oder einem Anfrageparameter übernehmen, diese Informationen an die Serviceebene weitergeben und dann ein paar Dinge in ein Response-Objekt einfügen oder vielleicht Daten in der Benutzersitzung speichern.

Ich würde empfehlen, weg von Vererbung mit Aktionsklassen zu bleiben. Es klingt zunächst nach einer guten Idee, aber ich denke, früher oder später merkt man, dass man Dinge mehr bescheuert, als man die Codebasis wirklich robust macht. Struts hat genug Basisaktionen, wenn Sie neue erstellen, haben Sie wahrscheinlich Code in der Webebene, der nicht dort sein sollte.

Das ist nur meine persönliche Erfahrung.

2
  1. Go eine Methode zu einem Zeitpunkt
  2. Nehmen Sie einige Testfälle Sie später wiedergeben. Example here (achten Sie darauf, so viele Pfade durch den Code zu treffen, d. H. Alle Benutzergesten auf der Seite, die diese Aktion aufrufen.)
  3. refaktorieren Sie die Methode, um ihre Komplexität zu reduzieren, indem Sie kleinere Methoden erstellen, die kleinere Aufgaben erledigen.
  4. Re-run-Tests, wie Sie tun, um diese

An dieser Stelle Sie Version des großen großen lästige Methode Refactoring haben. Jetzt können Sie tatsächlich beginnen, bestimmte Aktionen zu erstellen.

Sie können Ihre neu refaktorierte Klasse als Basisklasse verwenden und jede spezifische Aktion als Unterklasse mithilfe dieser refaktorierten kleinen Methoden implementieren.

Sobald Sie dies getan haben, sollten Sie ein gutes Bild der Logik haben, die zwischen den Klassen geteilt wird, und diese Methoden nach Bedarf ziehen oder drücken.

Es macht keinen Spaß, aber wenn Sie eine Weile an der Codebasis arbeiten, sparen Sie Zeit und Kopfschmerzen.