2008-10-16 13 views
5

Odziedziczyłem tę gigantyczną starszą aplikację internetową Java, używając Struts 1.2.4. Mam konkretne pytanie dotyczące działań. Większość stron ma dokładnie jedną Akcja, a metody processExecute() są potworami ohydnymi (bardzo długie i ton zagnieżdżonych instrukcji if na podstawie parametrów żądania).Jak radzić sobie z monstrualnymi działaniami Struts?

Biorąc pod uwagę, że Akcje są implementacją wzorca poleceń, myślę, że podzielę te Akcje na jeden Akcja na gest użytkownika. To będzie duży refaktoryzacji i zastanawiam się:

  1. Czy to właściwy kierunek?
  2. Czy jest jakiś krok pośredni, który mógłbym wykonać, wzór, który zajmuje się bałaganem wewnątrz monolitycznych działań? Może inny wzór poleceń w akcji?

Odpowiedz

9

Mój sposób radzenia sobie z tym byłoby:

  • nie robić „wszystko na raz”
  • ilekroć coś zmienić, zostaw to lepiej niż znalazłeś je
    • zastępujące warunkowe z oddzielnymi implementacjami Action jest jednym krokiem.
    • Jeszcze lepiej: Make Your implementacje oddzielić od klas akcji, dzięki czemu można go używać podczas zmiany ram
    • Trzymaj nową realizację polecenia absolutnie bez odniesienia do rozpórki, wykorzystać swoje nowe działania, jak Wrapper wokół tych wdrożeń.
    • Może być konieczne dostarczenie interfejsów do ActionScripts Struts, aby można je było przekazać bez kopiowania wszystkich danych. Z drugiej strony - może chcesz przekazać wokół innych obiektów niż ActionForms które są zazwyczaj grono Strings (zobacz inne pytanie o Struts 1.2 ActionForms)
  • rozpocząć migrację do nowszych części & lepszej technologii. Struts 1.2 był świetny, gdy wyszedł, ale zdecydowanie nie jest to, co chcesz wspierać w wieczności. Teraz istnieją generacje lepszych frameworków.

Jest zdecydowanie więcej - Niestety, mam coraz mniej czasu tutaj ...

1

trudny problem, ale typowe dla wczesnego rozwoju aplikacji internetowych.

Po pierwsze trzeba zacząć myśleć o tym, która logika stanowi zachowanie biznesowe, która to logika stanowi "przepływ" (tj. To, co widzi użytkownik), a która logika pobiera treść do tego, co widzi.

Nie musisz iść wzdłuż fabryk i interfejsów i tak dalej; Implementacja retroaktywna jest o wiele mniej przydatna ... ale konsolidacja logiki biznesowej i logiki pobierania danych w rodzaju delegatów ... i opuszczenie działań podpórek w celu określenia przepływu stron w oparciu o sukces/porażkę tej logiki.

Stamtąd po prostu trzeba wziąć kilka tygodni i szlifować go

1

Jeden długi sposób nigdy nie jest dobry, chyba że dzieje się pojedynczy switch przypadki są bardzo krótkie (tokenu parsowania lub coś podobnego że).

Można przynajmniej przekształcić długą metodę na mniejsze metody z opisowymi nazwami.

Jeśli to możliwe, możesz uruchomić swoją metodę, rozpoznając, co należy zrobić, sprawdzając formularz, a następnie, jeśli/w inny sposób, do różnych opcji. Nie zagnieżdżone, ale te powodują, że kod jest nieczytelny. Po prostu

enum Operation { 
    ADD, DELETE; 
} 

... 

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

Jeśli możesz posunąć się tak daleko, masz logikę ładną i czystą i możesz zrobić dowolne refaktoryzacje.

Najtrudniej jest uzyskać przejrzystość logiki i robić to krok po kroku. Nie wybieraj wzoru, dopóki nie zrozumiesz dokładnie, jaki jest twój problem.

1

Jeśli zamierzasz zmienić kod, powinieneś najpierw napisać testy dla istniejącego kodu, aby mieć pewność, że nie zmieniłeś jego funkcjonalności po rozpoczęciu refaktoryzacji.

+0

Zamierzam powiedzieć pshah. Autor stwierdza, że ​​metody są monstrualnie długie i mają wysoką złożoność cykliczną. Ten rodzaj kodu jest często koszmarem do testu jednostkowego. – JonMR

2

Zajmowałem się już tego typu rzeczami. Pierwszym dobrym krokiem jest wstawienie kolejnej klasy bazowej do łańcucha dziedziczenia między Akcja i jedną z oryginalnych monstrualnych klas działania (możesz nazwać ją ClassA). Zwłaszcza, jeśli nie masz czasu, aby zrobić wszystko na raz. Wtedy możesz zacząć wyciągać elementy funkcjonalności na mniejsze równoległe klasy działania (ClassB, ClassC). Wszystko, co jest wspólne pomiędzy oryginalną klasą A i nowymi klasami refaktoryzowanymi, można przenieść do nowej klasy bazowej. Tak więc hierarchia wygląda teraz tak:

Original Hierarchy:  New Hierarchy: 

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

Przeczytaj moją odpowiedź powyżej, aby przemyślenia na temat hierarchii działań. Myślę, że w wielu miejscach, które to robią, prawdopodobnie mają za dużo logiki biznesowej w swojej warstwie internetowej. – bpapa

5

Akcje, według mnie, nie powinny zawierać w sobie bardzo dużo kodu. Powinni po prostu wejść w interakcję bezpośrednio z żądaniem i odpowiedzią - pobrać dane z formularza lub parametru żądania, przekazać te informacje do warstwy serwisowej, a następnie umieścić niektóre rzeczy w obiekcie odpowiedzi lub zapisać niektóre dane w sesji użytkownika.

Polecam trzymanie się z daleka od dziedziczenia z klasami działań. Na pierwszy rzut oka wygląda to na dobry pomysł, ale myślę, że prędzej czy później zdasz sobie sprawę, że robisz rzeczy związane z butami bardziej niż czynisz podstawę kodu solidną. Struts ma wystarczającą ilość akcji podstawowych, ponieważ jeśli tworzysz nowe, prawdopodobnie masz kod w warstwie internetowej, którego tam nie powinno być.

To tylko moje osobiste doświadczenie.

2
  1. Go jednej metody naraz
  2. nagrać kilka przypadków testowych można odtworzyć później. Example here (upewnij się, że wykonałeś tyle ścieżek kodu, ile możesz, tj. Wszystkie gesty użytkownika na stronie wywołującej to działanie)
  3. refaktoryzuj metodę, aby zmniejszyć jej złożoność, tworząc mniejsze metody, które robią mniejsze rzeczy.
  4. ponownie uruchomić testy jak to zrobić

W tym momencie masz refactored wersja wielkiego ogromnego metodą irytujące. Teraz można faktycznie rozpocząć tworzenie określonych działań.

Możesz użyć swojej nowo refaktoryzowanej klasy jako klasy bazowej i zaimplementować każdą określoną akcję jako podklasę przy użyciu tych małych, refakturowanych metod.

Gdy to zrobisz, powinieneś mieć dobry obraz logiki dzielonej pomiędzy klasami i możesz podciągnąć lub przesunąć te metody w razie potrzeby.

To nie jest zabawne, ale jeśli będziesz pracował przez chwilę w bazie kodu, zaoszczędzi ci to czasu i bólów głowy.