W przeszłości korzystałem z MVP i MVC i wolę MVP, ponieważ moim zdaniem znacznie lepiej kontroluje przebieg wykonywania.
Stworzyłem swoją infrastrukturę (klasy magazynu danych / repozytorium) i używam ich bez problemu podczas twardego kodowania przykładowych danych, więc teraz przechodzę do GUI i przygotowuję MVP.
Sekcja A
Widziałem MVP używającego widoku jako punktu wejścia, to znaczy w metodzie konstruktora widoków tworzy on prezentera, który z kolei tworzy model, łącząc zdarzenia w razie potrzeby.
Widziałem również prezentera jako punkt wejściowy, w którym tworzony jest widok, model i prezenter. Następnie ten prezenter otrzymuje widok i model obiektu w swoim konstruktorze w celu połączenia zdarzeń.
Jak w 2, ale model nie jest przekazywany do prezentera. Zamiast tego model jest statyczną klasą, w której wywoływane są metody, a odpowiedzi zwracane bezpośrednio.
Sekcja B
Widziałem, jeśli chodzi o synchronizację widoku i modelu.
Ilekroć zmienia się wartość w widoku, tj.
TextChanged
Zdarzenie w .Net / C #. To uruchamia model,DataChangedEvent
który jest przekazywany do modelu, aby cały czas był zsynchronizowany. A gdy model się zmienia, tj. Zdarzenie w tle, którego słucha, widok jest aktualizowany za pomocą tego samego pomysłu wywołania aDataChangedEvent
. Gdy użytkownik chce zatwierdzić zmianySaveEvent
, uruchamia się, przechodząc do modelu, aby zapisać. W takim przypadku model naśladuje dane widoku i przetwarza działania.Podobne do # b1, jednak widok nie jest zsynchronizowany z modelem przez cały czas. Zamiast tego, gdy użytkownik chce zatwierdzić zmiany,
SaveEvent
zostaje zwolniony, a prezenter pobiera najnowsze szczegóły i przekazuje je do modelu. w tym przypadku model nie wie o danych widoków, dopóki nie będzie musiał na nim działać, w którym to przypadku zostaną przekazane wszystkie potrzebne szczegóły.
Sekcja C
Wyświetlanie obiektów biznesowych w widoku, tj. Obiektu (MyClass), a nie pierwotnych danych (int, double)
Widok ma pola właściwości dla wszystkich swoich danych, które będą wyświetlane jako obiekty domeny / biznesu. Na przykład
view.Animals
ujawniaIEnumerable<IAnimal>
właściwość, nawet jeśli widok przetwarza je na węzły w TreeView. Następnie dla wybranego zwierzęcia odsłoniłby sięSelectedAnimal
jakoIAnimal
własność.Widok nie ma wiedzy o obiektach domeny, udostępnia właściwości tylko dla typów obiektów zawartych w elementach pierwotnych / ramowych (.Net / Java). W tym przypadku prezenter przekazuje obiekt adaptera obiekt domeny, adapter następnie przetłumaczy dany obiekt biznesowy na formanty widoczne w widoku. W tym przypadku adapter musi mieć dostęp do rzeczywistych elementów sterujących w widoku, a nie tylko do dowolnego widoku, dlatego zostaje ściślej sprzężony.
Sekcja D
Wiele widoków użytych do utworzenia jednego elementu sterującego. tzn. masz złożony widok z prostym modelem, takim jak zapisywanie obiektów różnych typów. Możesz mieć system menu z boku przy każdym kliknięciu elementu, wyświetlane są odpowiednie elementy sterujące.
Tworzysz jeden ogromny widok, który zawiera wszystkie poszczególne elementy sterujące, które są widoczne przez interfejs widoków.
Masz kilka widoków. Masz jeden widok na menu i pusty panel. Ten widok tworzy inne wymagane widoki, ale ich nie wyświetla (widoczny = fałsz), ten widok implementuje również interfejs dla każdego widoku, który zawiera (tj. Widoki potomne), dzięki czemu może być udostępniany jednemu prezenterowi. Pusty panel jest wypełniony innymi widokami (
Controls.Add(myview)
) i ((myview.visible = true
). Zdarzenia wywołane w tych „podrzędnych” widokach są obsługiwane przez widok nadrzędny, który z kolei przekazuje zdarzenie prezenterowi i odwrotnie w celu dostarczenia zdarzeń z powrotem do elementów potomnych.Każdy widok, niezależnie od tego, czy jest to główny widok rodzica, czy mniejszy widok dziecka, jest połączony z własnym prezenterem i modelem. Możesz dosłownie po prostu upuścić kontrolkę widoku do istniejącej postaci, a ona będzie mieć gotową funkcjonalność, wystarczy podłączyć do prezentera za kulisami.
Sekcja E
Jeśli wszystko ma interfejs, teraz oparte na sposobie wykonania MVP w powyższych przykładach wpłynie na tę odpowiedź, ponieważ mogą one nie być kompatybilne krzyżowo.
Wszystko ma interfejs, widok, prezentera i model. Każdy z nich ma oczywiście konkretne wdrożenie. Nawet jeśli masz tylko jeden konkretny widok, model i prezentera.
Widok i model mają interfejs. Dzięki temu widoki i modele mogą się różnić. Prezenter tworzy / otrzymuje widok i modeluje obiekty i służy tylko do przekazywania komunikatów między nimi.
Tylko widok ma interfejs. Model ma metody statyczne i nie jest tworzony, dlatego nie ma potrzeby używania interfejsu. Jeśli chcesz mieć inny model, prezenter wywołuje inny zestaw metod klasy statycznej. Będąc statycznym Model nie ma linku do prezentera.
Osobiste myśli
Ze wszystkich przedstawionych przeze mnie wariantów (większość, których prawdopodobnie użyłem w jakiejś formie), których jestem pewien, że jest ich więcej. Wolę A3 jako logikę biznesową wielokrotnego użytku poza MVP, B2 dla mniejszego powielania danych i mniejszej liczby zdarzeń. C1 za brak dodawania w innej klasie, na pewno umieszcza w widoku niewielką ilość logiki, która nie może być testowana jednostkowo (sposób wizualizacji obiektu domeny), ale można to sprawdzić w kodzie lub po prostu wyświetlić w aplikacji. Gdyby logika była złożona, zgodziłbym się na klasę adaptera, ale nie we wszystkich przypadkach. W przypadku sekcji D wydaje mi się, że D1 tworzy widok, który jest zbyt duży przynajmniej na przykład w menu. Używałem wcześniej D2 i D3. Problem z D2 polega na tym, że w końcu musisz napisać dużo kodu, aby przekierować zdarzenia do i z prezentera do właściwego widoku potomnego i nie jest on zgodny z funkcją przeciągnij / upuść, każdy nowy element sterujący wymaga dodatkowego okablowania, aby obsługiwać jednego prezentera. D3 jest moim preferowanym wyborem, ale dodaje jeszcze więcej klas jako prezenterów i modeli do obsługi widoku, nawet jeśli widok jest bardzo prosty lub nie trzeba go ponownie wykorzystywać. myślę, że mieszanka D2 i D3 najlepiej opiera się na okolicznościach. Jeśli chodzi o sekcję E, myślę, że wszystko, co ma interfejs, może być przesadzone. Już to robię dla obiektów domenowych / biznesowych i często nie widzę w tym „przewagi”, ale pomaga to w wyśmiewaniu obiektów w testach. Osobiście widziałbym E2 jako klasyczne rozwiązanie, chociaż widziałem E3 zastosowane w 2 projektach, nad którymi wcześniej pracowałem. myślę, że mieszanka D2 i D3 najlepiej opiera się na okolicznościach. Jeśli chodzi o sekcję E, myślę, że wszystko, co ma interfejs, może być przesadą. Już to robię dla obiektów domenowych / biznesowych i często nie widzę w tym „przewagi”, ale pomaga to w wyśmiewaniu obiektów w testach. Osobiście widziałbym E2 jako klasyczne rozwiązanie, chociaż widziałem E3 zastosowane w 2 projektach, nad którymi wcześniej pracowałem. myślę, że mieszanka D2 i D3 najlepiej opiera się na okolicznościach. Jeśli chodzi o sekcję E, myślę, że wszystko, co ma interfejs, może być przesadzone. Już to robię dla obiektów domenowych / biznesowych i często nie widzę żadnej korzyści w „projektowaniu”, ale pomaga to w wyśmiewaniu obiektów w testach. Osobiście widziałbym E2 jako klasyczne rozwiązanie, chociaż widziałem E3 zastosowane w 2 projektach, nad którymi wcześniej pracowałem.
Pytanie
Czy poprawnie wdrażam MVP? Czy istnieje odpowiedni sposób, aby to zrobić?
Przeczytałem pracę Martina Fowlera, która ma różne wersje, i pamiętam, kiedy po raz pierwszy zacząłem tworzyć MVC, zrozumiałem koncepcję, ale początkowo nie mogłem ustalić, gdzie jest punkt wejścia, wszystko ma swoją funkcję, ale to, co kontroluje i tworzy oryginał zestaw obiektów MVC.