Cieszę to pytanie zostało zadane, ponieważ GWT desperatley potrzebuje Rails jak sposób strukturyzacji aplikacji. Proste podejście oparte na najlepszych praktykach, które będą działać dla 90% wszystkich przypadków użycia i umożliwia bardzo łatwą testowalność.
W ostatnich latach korzystałem z własnej implementacji MVP z bardzo pasywnym poglądem, który zniewalałby się tym, co prezenter każe mu zrobić.
Moje rozwiązanie składało się z następujących elementów:
- interfejs za widget zdefiniowanie metod kontrolowania wizualnego wyglądu
- klasę wykonawczą, która może być złożona lub użyć zewnętrznego biblioteki widget
- Central Presenter dla ekranu zawierającego widoki N składające się z widgetów M
- centralny model na ekranie, który przechowuje dane powiązane z bieżącym wyglądem wizualnym
- Ogólne klasy nasłuchujące, takie jak "SourcesAddEvents [CustomerDTO]" (edytor nie lubi prawdziwych symboli generycznych java tutaj, więc użyłem nawiasów thoe), ponieważ w przeciwnym razie będziesz miał wiele takich samych interfejsów, które różnią się tylko typem
Widoki otrzymują odniesienie do prezentera jako jego parametru konstruktora, dzięki czemu mogą zainicjować swoje zdarzenia z prezenterem. Prezenter zajmie się tymi zdarzeniami i powiadomi inne widżety/widoki i lub zadzwoni do gwt-rpc, że na sukces umieści swój wynik w modelu. Model ma typowy mechanizm "List [String [String]] names = ....", który jest zarejestrowany w prezencie, dzięki czemu aktualizacja modelu przez żądanie gwt-rpc przechodzi do wszystkich widoków/widżetów, które są zainteresowani.
Dzięki tej aplikacji uzyskałem bardzo łatwą testowalność z EasyMock dla moich AsynInterfaces. Miałem również możliwość łatwej wymiany implementacji widoku/widżetu, ponieważ wszystko, co musiałem przerobić, to kod, który powiadomił prezentera o jakimś wydarzeniu - niezależnie od ukrytego widgetu (Button, Links, itp.).
Problemy z mojego podejścia:
- Moja obecna realizacja sprawia, że trudno, aby zsynchronizować dane wartości współczynnika pomiędzy centralnymi modeli różnych ekranach. Załóżmy, że masz ekran wyświetlający zestaw kategorii i kolejny ekran, na którym możesz dodawać/edytować te elementy. Obecnie bardzo trudno jest propagować te zdarzenia zmianowe poza granice ekranów, ponieważ wartości są buforowane w tych modelach i ciężko jest nam znaleźć, czy niektóre rzeczy są brudne (byłoby to łatwe w tradycyjnym web1.0-html -drogowy typ scenariusza z pamięcią podręczną deklarowaną przez serwer).
- Parametry konstruktora widoków umożliwiają super łatwe testowanie, ale bez solidnej struktury Dependency-Injection, jeden będzie zawierał trochę kodu fabrycznego/instalacji UGLY wewnątrz "onModuleLoad()". W momencie, kiedy to zaczynałem, nie wiedziałem o Google GIN, więc kiedy zmienię swoją aplikację, wykorzystam to, aby pozbyć się tej tablicy. Ciekawym przykładem jest gra "HigherLower" w GIN-Trunk.
- Po raz pierwszy historia nie była prawidłowa, więc trudno jest nawigować z jednej części aplikacji do drugiej. Moje podejście nie jest świadome historii, która jest poważnym kryzysem.
Moi Rozwiązania tych problemów:
- Zastosowanie GIN usunąć boilerplate instalacyjny, który jest trudny do utrzymania
- Podczas przechodzenia z GWT-EXT do GXT, wykorzystać swoje ramy MVC jako EventBus do dołączaj/odłączaj modularne ekrany, aby uniknąć problemów z buforowaniem/synchronizacją.
- Pomyśl o jakimś "Miejscu" - tak jak Ray Ryan opisał w swoim przemówieniu na I/O 09, które łączy lukę między GXT-MVC a Podejście GWTs-Hitory
- Zastosowanie MVP dla widżety wyizolować dostęp do danych
Podsumowanie:
nie sądzę, można użyć jednego podejścia „MVP” dla całej aplikacji. Zdecydowanie potrzebna jest historia dla aplikacji nawigacyjnej, eventbus taki jak GXT-MVC do podłączania/odłączania ekranów i MVP, aby umożliwić łatwe testowanie dostępu do danych dla widżetów.
Proponuję zatem podejście wielowarstwowe, które łączy w sobie te trzy elementy, ponieważ uważam, że "system jedno-event-mvp-system" nie będzie działał. Nawigacja/Załączanie ekranów/Dostęp do danych to trzy oddzielne kwestie, a w następnych miesiącach zmienię swoją aplikację (przejdę na GXT), aby wykorzystać wszystkie trzy ramy zdarzeń dla każdej sprawy osobno (najlepsze narzędzie do pracy). Wszystkie trzy elementy nie muszą być świadome siebie nawzajem. Wiem, że moje rozwiązanie dotyczy tylko projektów GXT.
Pisząc duże aplikacje GWT, czuję, że muszę wymyślić coś w rodzaju Spring-MVC na kliencie, co naprawdę jest do bani, ponieważ potrzeba dużo czasu i energii, by wypluć coś eleganckiego jak Spring MVC. GWT potrzebuje ramy aplikacji o wiele bardziej niż te małe, małe optymalizacje JS, na które tak ciężko pracują kompilatorzy.
Ale te niewielkie małe optymalizacje JS są tym, co sprawia, że GWT jest tak szybkie - i jest podstawową platformą dla bardziej wyrafinowanych frameworków, które, jeśli są wykonane prawidłowo, mogą zapewnić wszystkie korzyści abstrakcji bez ponoszenia kosztów wielu głębokich funkcji alls/depesz (GWT zoptymalizuje/rozwinie je). – Chii
Szczególnie w przypadku dzielenia kodu w 2.0, GWT jest wystarczająco szybki dla twórcy IMO. Nie zrozumcie mnie źle, nie chcę zlekceważyć znaczenia tych optymalizacji. Ale deweloperzy napotykają problemy w świecie rzeczywistym i przydałyby się o wiele więcej dzięki tradycyjnemu sposobowi działania - w ramach aplikacji - teraz. – Sakuraba
Sakuraba - Zgadzam się z Tobą, że GWT potrzebuje jakiegoś mechanizmu konwergencji konwencji do zorganizowania kodu. Nie obchodzi mnie, czy to się nazywa MVC czy MVP, po prostu chcę czegoś prostego i łatwego w użyciu. Użyłem GXT MVC [1] i, biały działa, może być mylące używać podczas wdrażania historii. Dla mnie historia jest jednym z najważniejszych aspektów aplikacji GWT i odkryłem, że najłatwiej jest ją wdrożyć wcześnie, niż później. Pochylam się do MVP b/c Google poleca (patrz odpowiedź JP poniżej). [1] http://raibledesigns.com/rd/entry/gxt_s_mvc_framework –