Gdzie mam umieścić żądanie API w MVC?

25

Buduję aplikację internetową przy użyciu wzorca MVC. Zgodnie z tego rodzaju architekturą możemy zobaczyć, że wszystkie metody używane do interakcji z bazą danych są zaimplementowane w modelu .

Ale co się stanie, jeśli będę musiał zadzwonić do usługi udostępnianej przez innych w sieci? Na przykład chciałbym uzyskać dostęp do interfejsu API Facebooka, aby uzyskać dostęp do wszystkich obserwujących moją stronę, więc gdzie umieszczam te metody?

Oczywiście widok nie jest dobrym pomysłem, ponieważ ten moduł jest poświęcony prezentacji, kontroler nie powinien być wykorzystywany do pobierania danych, ale model jest zwykle przeznaczony tylko do interakcji z bazą danych.

Czy możesz mi coś o tym powiedzieć? I proszę, czy możesz mi powiedzieć, jeśli popełniam błędy w architekturze MVC?

Ema.jar
źródło
2
Myślę, że ludzie byliby w stanie udzielić lepszych odpowiedzi, gdybyś wymienił niektóre biblioteki i frameworki, których używasz do obsługi aplikacji MVC. Chociaż wzorzec MVC jest niezależny od technologii, nie wszystkie frameworki wyraźnie go przestrzegają. Co więcej, większość dojrzałych frameworków ma już znakomitą dokumentację, a wiedza o tym, którego używasz, ułatwiłaby ci skierowanie do wcześniejszego wyjaśnienia, które podąża za tobą.
CLW,
2
Baza danych? Źródło danych? To tylko dane.
2
Jest tak wiele opinii na temat tego, czym powinno być „MVC”, że na to pytanie jest zbyt abstrakcyjne, aby można było na nie odpowiedzieć.
RemcoGerlich,
2
Rozważ także wywołanie interfejsu API z kodu JavaScript interfejsu użytkownika i nie dotykanie go w ogóle jako „MVC”.
RemcoGerlich,
@Remcogerlich dlatego zaproponowałem dodanie rzeczywistej implementacji, na którą patrzy. Mógł mieć do czynienia z backendem i frontendową implementacją mvc. Moglibyśmy również wprowadzić inny wzór, który lepiej wyjaśnia te różnice.
CLW,

Odpowiedzi:

37

Model nie ogranicza się do interakcji z bazą danych, model jest odpowiedzialny za pobieranie i manipulowanie danymi.

Tak więc, twoim zdaniem i kontrolerowi, nie powinno to mieć znaczenia, jeśli dane pochodzą z bazy danych lub z usługi internetowej, a nawet są całkowicie losowe, dlatego powinieneś to zrobić w modelu.

MVC to wzorzec prezentacji, który oddziela tylko różne warstwy reprezentacji.

Nie oznacza to, że ten model musi być jednolitym bałaganem kodu spaghetti. Sam model może być warstwowy, ale administrator nie powinien wiedzieć, skąd pochodzą dane.

Metoda publiczna w twoim modelu może mieć następującą strukturę (pseudo-kod), którą może wywołać kontroler:

public MyDataClass getData(int id) {
    WebServiceData wsData = WebService->getData(id);
    DatabaseData dbData = ORM->getData(id);
    return new MyDataClass(wsData, dbData);
}

WebServicei ORMmoże być konieczne wystąpienie interfejsów, które można zastąpić próbnymi metodami za pomocą wstrzykiwania zależności, ale kontrolery i widoki nie muszą się zmieniać w celach testowych.

Pozostałość
źródło
8
Model nie powinien mieć żadnej logiki, a zatem nie powinien bezpośrednio oddziaływać na nic. Wzorzec MVC wyraźnie wymaga umieszczenia całej logiki w kontrolerach. Kontrolery te powinny kontaktować się z DB, API itp. Jak i aktualizować model w razie potrzeby. Dzięki temu technologia modelu pozostaje agnostyczna i zapewnia, że ​​służy jedynie jako mechanizm pamięci, który można przekazać do różnych widoków w celu prezentacji i kontrolerów w celu dodatkowej manipulacji.
CLW,
3
@CLW: Model! = Model danych. Więcej szczegółów można znaleźć gdzieś indziej, np stackoverflow.com/a/14045514/124983
pozostałość
2
@CLW: logika biznesowa nie powinna znajdować się w M, V ani C. Modele są abstrakcją magazynu danych, widoki i kontrolery są interfejsem użytkownika. Są to peryferia tworzonej przez ciebie aplikacji, która powinna być „tylko kodem”, który nie musi wiedzieć o takich rzeczach, jak bazy danych i Internet.
RemcoGerlich,
2
Część „modelowa” jest interpretowana na setki różnych sposobów. Zawsze uczono mnie, że model jest reprezentacją. Model pociągu jest reprezentacją prawdziwego pociągu, z małymi ruchomymi częściami, które poruszają się tak jak prawdziwy. Podobnie, model w twojej aplikacji jest reprezentacją systemów i procesów, które budujesz oprogramowanie, aby je zastąpić. Jako takie modele zachowują się . Takie zachowanie obejmuje „logikę biznesową”. Tak więc, jeśli zignorujesz dostęp do danych CRUD, interfejs użytkownika i interop, pozostanie prawdopodobnie Twój „model” - klasy domen, reguły biznesowe itp.
Anaximander
1
@RemcoGerlich Nie mówiłem nic o logice biznesowej. Po prostu stwierdziłem, że ponieważ większość interpretacji MVC wymaga, aby model był niczym innym jak prostą strukturą reprezentującą stan twojej aplikacji, że odpowiedzialność za kontakt z DB, API itp. Nie powinna być umieszczona w modelu, ponieważ powinien być bez logiki. Obowiązek komunikacji z bazą danych powinien spoczywać na kontrolerze lub innym obiekcie zarządzanym przez kontroler.
CLW,
12

Istnieje powszechne (umyślne?) Nieporozumienie dotyczące tego, czym są M, V i C. Nie o rolach, które przyjmują, ale jakie .

W oryginalnej definicji graficznego interfejsu użytkownika MVC były to moduły . Zazwyczaj aplikacja zawierała kilka z nich, czasami pracując w trojaczkach, czasami mając różnorodne widoki i modele, które kilka kontrolerów mogło łączyć i dopasowywać.

We frameworkach sieciowych, OTOH, są one zwykle postrzegane jako warstwy , gdzie są tylko jedną z nich i zajmują się głównie pokryciem pewnego poziomu pobocznego abstrakcji: „warstwa modelu abstrakcji bazy danych”, „warstwa widoku implementuje prezentację”, „kontroler warstwa przetwarza dane wprowadzone przez użytkownika ".

Więc powiedziałbym, że masz już to model, dedykowany do interakcji z bazą danych, a teraz po prostu trzeba utworzyć inny model do czynienia z source API. Jeśli uczynisz je możliwie jak najbardziej podobnymi, większość kontrolera i kodu widoku może bezproblemowo współpracować z dowolnym modelem.

Javier
źródło
1
Uzgodnione: Model (y) zawsze miały stanowić całą domenę problemową. W skomplikowanych aplikacjach zawsze miała stanowić większość kodu. Składały się one z całego kodu, który nie zmieniłby się, jeśli zmienisz interfejs użytkownika (np. Ze strony internetowej na GUI lub nawet aplikację wiersza poleceń). Pomyśl o kompilatorze. Tylko niewielka część kodu zmieniłaby się, gdybyś przeszedł z interfejsu wiersza poleceń do GUI, a nawet interfejsu WWW. Wszystkie cechy takiego zastosowania to modele.
Kevin Cathcart,
1
W pierwotnym użyciu tego terminu każda kontrolka interfejsu użytkownika w interfejsie miała swój własny model, widok i kontroler.
RemcoGerlich,
5

Częściową trudnością przy jakiejkolwiek dyskusji na temat MVC jest to, że różne grupy kooptowały go, aby oznaczać różne rzeczy. Implementacja MVC zastosowana, powiedzmy, w aplikacji Rails, byłaby prawie nie do poznania dla kogoś, kto pisze aplikację Swing. W zakresie, w jakim MVC jest nadal dobrze zdefiniowaną rzeczą, jest to raczej zbiór zasad przewodnich (oddzielenie podstawowej aplikacji od jej wizualnej reprezentacji, zapewnienie elastycznych mechanizmów umożliwiających połączenie tych dwóch elementów), które można wdrożyć w różnych sposoby

Rzeczywiście istnieje tendencja do nadawania innym projektom pochodzącym z MVC różnych nazw (patrz artykuł Martina Fowlera, aby o tym dyskutować), a nawet rezygnacji z precyzyjnego nazewnictwa - na przykład AngularJS opisuje się jako Model-Widok-Cokolwiek struktura.

Trudno więc odpowiedzieć, nie wiedząc, z którą wersją „MVC” pracujesz. Jednak żądanie API zwykle stanowiłoby część podstawowej aplikacji (część, która nie powinna ulec zmianie, jeśli zdecydujesz się użyć innej reprezentacji wizualnej), która w wielu implementacjach byłaby zawarta całkowicie w modelu.

James_pic
źródło
2

Tutaj model jest opisany w następujący sposób:

Model przechowuje dane, które są pobierane do kontrolera i wyświetlane w widoku. Ilekroć następuje zmiana danych, jest ona aktualizowana przez kontrolera.

Powiedziałbym, że kontroler zawiera logikę wywoływania usługi lub wywołuje oddzielny Serviceobiekt. Jeśli usługa jest osobna, możesz łatwiej tworzyć testy, powiedzmy, jeśli nie jest możliwe połączenie z usługą za pośrednictwem sieci, niektóre TestServicemogą udzielać odpowiedzi Servicelokalnie.

Sprawdź również tę odpowiedź, która sugeruje, że kontroler wywołuje usługę.

zero
źródło
2

Twój model nigdy nie powinien zawierać żadnego faktycznego kodu i powinien być postrzegany jako komunikat lub struktura używana do zarządzania treściami manipulowanymi przez kontroler i wyświetlanymi przez widok.

Twój kontroler powinien być odpowiedzialny za kontaktowanie się z wszelkimi interfejsami API, bazami danych, usługami itp. ... żądaniem zmiany i zarządzaniem niezbędnymi aktualizacjami modelu.

Cała siła wzoru MVC polega na tym, że oddziela on logikę (kontroler) od widoku i stanu (model). W ten sposób masz teraz gwarancję, że tylko kod w kontrolerze może wywoływać skutki uboczne, ponieważ widok i model po prostu nie mogą wprowadzać zmian.

Pozwala także na lepsze ponowne wykorzystanie kodu, ponieważ model może być współużytkowany przez różne kontrolery i widoki.

CLW
źródło
4
Myślę, że kiedy mówisz tutaj „model”, masz na myśli „viewmodel”, który IMO stanowi odrębną rzecz. Viewmodel pobiera dane z kontrolera do widoku, i jako taki jest albo szczegół implementacji widoku, albo aspekt komunikacji między widokiem a kontrolerem, który tak naprawdę nie pasuje do żadnego (zależy od tego, jak to widzisz). „Model” w MVC odnosi się do modelu systemu - reprezentacji systemu, która uwzględnia jego dane, strukturę i zachowanie. Model jest stanem i logiką; Kontroler powoduje, że logika działa, a stan zmienia się podczas manipulacji widokiem.
anaximander,
@anaximander Nie Odnoszę się do modelu w dość ścisłej interpretacji MVC (patrz Wikipedia, Microsoft MVC, wzorce Head First Design itp.). W takich przypadkach Model jest niczym innym jak prostą strukturą do przekazywania danych wokół i nie ma czegoś takiego jak viewmodel. Chociaż implementacja Microsoft MVC dodaje różne atrybuty do modelu, jest to bardziej wygodne niż cokolwiek innego. Ostatecznie celem wzoru MVC było ułatwienie dobrej praktyki separacji kodów i ograniczenie skutków ubocznych.
CLW,
1

Może być daleko, ale tak myślę o WebApps i pracy ze [złożonymi] zdalnymi API w wielu przypadkach:

Zrobiłbym to klasę (tj. Bibliotekę metod ograniczania danych) zamiast modelu (tj. Stos funkcji ograniczania danych). Wygląda na to, że działałby bardziej przejrzysto, bardziej agnostycznie względem logiki / schematu, i można go używać wszędzie, bez ładowania-> wywoływania samego modelu / kontrolera za każdym razem, gdy chcesz go użyć. Logika jest nadal oddzielona, ​​punkt danych jest nadal elastyczny, i wydaje się bardziej otwarty na interoperacyjność w dziwnych przypadkach, takich jak układanie klientaAJAX-> appJSON-> appLIB-> remoteAPI-> remoteJSON itp., Aby pośrednio sondować punkt końcowy.

dhaupin
źródło