2015-03-06 22 views
9

Próbuję wdrożyć Clean Architecture opisany przez Roberta Martina. Dokładniej używam wersji VIPER, która jest wersją Clean Architecture dla systemu iOS.Czysta architektura - Robert Martin - Jak podłączyć przypadki użycia

Mam problem jest następujący:

Użytkownik uruchamia patrząc na mapę z miejscami (PIN) na nim. Jeśli kliknie przycisk, pinezka zostanie upuszczona i zostanie przeniesiony do innego widoku, aby utworzyć (lub edytować, jeśli było to kliknięcie w istniejącą szpilkę) miejsce (lub anulować). W tym innym widoku użytkownik może edytować informacje o miejscu, a następnie kliknąć "Wstecz" lub "Gotowe" (lub "Edytuj"). Po kliknięciu "done", PlaceDetailsViewController wysyła wiadomość do PlaceDetailsPresenter z informacjami o miejscu, a PlaceDetailsPresenter używa CreatePlaceInteractor do utworzenia miejsca. Ten interactor zwraca identyfikator GUID, który służy do identyfikacji miejsca.

Jeśli użytkownik kliknie z powrotem przed utworzeniem miejsca, wraca do mapy, a upuszczona szpilka podnosi się i odchodzi (ponieważ nie ma identyfikatora GUID, jest to nowe miejsce i znika). Jeśli kliknie z powrotem po utworzeniu, pin pozostanie tam (ponieważ powinien mieć identyfikator GUID).

W jaki sposób należy połączyć to wszystko i gdzie należy przechowywać informacje o miejscu (w tym identyfikator GUID)? Aby wyjaśnić nieco więcej:

  1. Kto powinien poinformować MapPresenter, że pin pozostanie tam lub znika? Czy to jest PlaceDetailsPresenter, czy powinienem przekazać te informacje do PlaceDetailsWireframe -> MapWireframe -> MapPresenter -> MapView?
  2. Przed powrotem, gdzie powinien być przechowywany ten identyfikator GUID, w PlaceDetailsPresenter lub PlaceDetailsViewController?

Teraz to co mam: enter image description here

EDIT:

Zasadniczo Myślę, że problemem jest to, że VIPER pochodzi Roberta Martina Clean Architektury i on pochodzi z internetowego (Rails) tle, więc nie myśli dużo o stanie (lub nie precyzuje go w swoich rozmowach).

Co jest głównie moim pytaniem, gdzie powinien być przechowywany stan, w jaki sposób powinny komunikować się różne moduły, czy powinien to być obiekt Wireframe, czy poprzez bazę danych, lub przez interakcje, lub poprzez Presenterów komunikujących się ze sobą jak tutaj https://github.com/objcio/issue-13-viper-swift.

+0

Właśnie rozpoczynam pracę z VIPER, ale nie mogę mieć prezenterów, którzy wiedzą o sobie nawzajem. Preferuję moduły komunikujące się ze sobą za pośrednictwem Wireframe/Routera. Cieszę się, że poprawiono mnie tutaj, ponieważ wciąż uczę się tej architektury. – bennythemink

+0

Mam tendencję do myślenia tak samo jak ty, chociaż nadal nie znalazłem decydującej odpowiedzi na to, jak przekazywać informacje między nimi, czy lepiej przekazywać struktury danych za pomocą modelu szkieletowego (2 opcje tutaj, używaj zawsze tego samego, dużego, struktury danych lub ciągle się zmieniaj, aby przekazać tylko minimalną ilość potrzebnych informacji (co kończy się tworzeniem większej liczby klas, które nie mogą być ponownie wykorzystane)) lub zapisać stan w Interaktorach i użyć ich do pobrania informacji w drugim prezenterze. Wysłałem kolejne pytanie dotyczące stackoverflow, które wyjaśnia, co rozumiem przez dużą strukturę danych, ale po prostu nie mogłem go jeszcze znaleźć. –

+0

http://stackoverflow.com/questions/29054526/viper- mógłby-interactor-return-nie-potrzebna-informacja –

Odpowiedz

15

Nie wiem zbyt wiele na temat Vipera, więc nie mogę tego komentować. Jednak stan brutto systemu powinien być przechowywany w obiektach podmiotu i manipulowany przez interaktorów. Szczegółowy stan GUI (prostokąty wyboru itp.) Powinien być zarządzany przez specjalne połączenie między kontrolerem a prezenterem.

W twoim przypadku są dwa ekrany. Mapa i edytor miejsc. Kliknięcie na mapę powoduje wywołanie metody placePinController. Zbiera lokalizację kliknięcia i wszelkie inne dane kontekstowe, konstruuje strukturę danych placePinRequest i przekazuje ją do PlacePinInteractor, który sprawdza położenie pinezki, sprawdza ją, jeśli to konieczne, tworzy obiekt Place, aby zapisać pinezkę, konstruuje EditPlaceReponse obiekt i przekazuje go do EditPlacePresenter, który wyświetla ekran edytora miejsca.

Po kliknięciu przycisku Gotowe na ekranie edytora miejsc, wywołuje EditPlaceController, który gromadzi edytowane dane w strukturze danych EditPlaceRequest i przekazuje je do EditPlaceInteractor. itd.

Pytanie o identyfikator GUID pinezki. Zostałoby to utworzone przez encję Miejsce i przekazane z powrotem do edytora EditPlacePresenter PlacePinInteractor.

+0

Może nie było bardzo jasne, ale co to było: kliknięcie dzieje się w MapPresenter, ale miejsce tylko zostanie utworzone później, jeśli użycie naciśnie przycisk "done" w obiekcie PlaceDetailsViewController (który jest podobny do widoku). Kiedy użytkownik kliknie "gotowe", miejsce zostanie utworzone. Jeśli użytkownik kliknie "wstecz", powinien wrócić do MapPresenter, a nie odrzucić pinezkę (lub odrzucić ją, jeśli nie została utworzona). –

+0

Przez stan mam na myśli rzeczy takie jak szpilka, która została tymczasowo utworzona na mapie. Tak więc, kiedy wracamy z PlaceDetailsViewController/Presenter, wiemy, który pinezkę należy odrzucić lub utrzymać (i podać identyfikator GUID, z którym chcemy się skojarzyć). –

+0

Pomyśl o "zrobione" i "z powrotem" jako różne przypadki użycia (różne interakcje). –

0

W czystym VIPER Router powinien przechowywać dane wejściowe modułów w postaci protokołu. I moduły Presenter powinny być z nim zgodne. Tak więc, gdy Ruter używa innych modułów Routera do złożenia nowego modułu, przekazuje mu swoje wejście.

Drugi router następnie przypisuje wejście do swoich prezentacji Presenterów. Więc zasadniczo prezenter pierwszego modułu staje się delegatem na drugi moduł Presenter.

W przypadku, gdy użytkownik wybierze miejsce, MapPresenter poprosi MapInteractor o identyfikator GUID i poleci MapRouterowi, aby przejść do szczegółów tego identyfikatora GUID.

MapRouter prosi o PlaceDetailsRouter o złożenie PlaceDetailsModule dla tego identyfikatora GUID i przekazuje do niego MapModuleInput. PlaceDetailsRouter przypisuje MapModuleInput do PlaceDetailsPresenter. PlaceDetailsRouter umieszcza GUID w PlaceDetailsInteractor