2012-02-28 18 views
5

Buduję projekt, który obecnie ma 3 zespoły:Architektura MVC dla projektu WWW/użytkowania różnych typów modelu

  • UI
  • główne (Usługi & modelek, Narzędzia)
  • (repozytoriów linq2sql)

Zależności są

  • UI -> Rdzeń
  • Rdzeń -> Repozytoria.

Chciałbym usług i modeli, aby być w swoich zespołach i skończyć z czymś, co jest zbudowany wokół modeli tj:

  • UI -> Modele, Usługi
  • Usługi -> Modele repozytoria
  • Repozytoria -> modele
  • modele

Th System, który buduję, to po prostu witryna CMS, więc będę miał model strony internetowej (PageModel), która ma kolekcję dziecięcych stron internetowych. PageModel może wywoływać metody w usłudze (PageService), aby zapełnić swoje strony podrzędne, ale w nowym projekcie, który nie może się zdarzyć, ponieważ zespół Modele niekoniecznie nie wie nic o zespole usług.

Rozważyłem niektóre z pomysłów w architekturze cebuli (czyli zastrzyk zależności), aby rozwiązać ten problem, ale wydaje się, że bardziej eleganckie/oczywiste rozwiązanie może być dostępne.

Czy muszę wprowadzić kolejną warstwę modelu? Wyświetl modele? Myślę, że to, co nazywam modelami, to modele domenowe ... mogę się mylić! Usługi byłyby wówczas usługami domenowymi?

Więc moje rozwiązaniem byłoby:

  • UI -> Usługi, ViewModels, modele
  • ViewModels -> Usługi, modele
  • Usługi -> Repozytoria, modele
  • Repozytoria -> Modele
  • Modele

W tym przykładzie wyobrażam sobie m y PageViewModel rozszerzy PageModel i użyje usługi PageService do pobrania stron podrzędnych.

Wszelkie sugestie doceniane. Jakiekolwiek wskazówki na temat tego, co te warstwy modeli są zwykle nazywane? Czy mówię tu o modelach DTO, a nie Domenach? A raczej modele domen niż modele widoków? Wygląda na to, że to, co proponuję użyć modeli widoku, nie jest naprawdę zadaniem modelu widoku.

Dzięki

EDIT:

Coś mi nie wspomniał, że pierwotnie to moja domena modele nie są podstawowe tłumaczenia pojedynczych podmiotów bazodanowych jak masz tendencję, aby zobaczyć w większości ćwiczeń. Model domeny może zawierać pola danych pochodzące z kilku powiązanych tabel bazy danych.

Czy warto byłoby mieć zestaw modeli wyłącznie do enkapsulacji danych w domenie - bez żadnych metod/właściwości, które pobierałyby powiązane obiekty lub zapisywały obiekt z powrotem do bazy danych itp? - Obiekty przenoszenia danych.

Spoglądając na kilka nagrywanych diagramów, oznaczałoby to posiadanie zestawu maperów w warstwie domeny (co wydaje się błędne ..) do przetłumaczenia modeli DTO na Modele Domeny iz powrotem. Projekt zostanie zbudowany wokół modeli DTO, a nie modeli domenowych, ale biorąc pod uwagę to, co jest zawarte w DTO, nie uważam tego za problem.

Dla każdego, kto jest zainteresowany, proponowana struktura zależności byłoby tak:

  • UI -> Usługi, model domeny
  • Services -> Repozytoria, model domeny, DTO modele
  • Domena modele - > Repozytoria, DTO modele
  • odwzorowujących -> model domeny, DTO modele
  • Repozytoria -> DTO modele
  • DT O Modele (bez zależności)

To trochę bałaganu! I wszystko tylko dlatego, że chcę, aby mój PageModel był w stanie pobrać swoje własne modele PageModels. Wygląda na to, że posiadanie zastrzyku na uzależnienie może nie być tak złym planem.

Dziękuję tym, którzy odpowiedzieli. Dałeś mi mnóstwo do myślenia.

Odpowiedz

2

Można to osiągnąć dzięki architekturze cebuli. będę mieć na przykład: UI, Domena Dostęp do danych, usług

UI Usługi Data Access Domain (zawiera zobacz modele również)

UI można uzyskać dostęp do nikogo. Usługi, tylko dostęp do danych i domeny. Dostęp do danych - tylko domena.

Moje interfejsy repozytoriów znajdują się w projekcie domeny i są zaimplementowane w projekcie dostępu do danych. Zachowuję również inne interfejsy w projekcie domeny (IContext, IUnitOfWork, etc), więc mam jedno centralne miejsce i nie rozpowszechniając zbyt wielu interfejsów między projektami.

DTO będą używane po prostu do przenoszenia między warstwami, jeśli uznasz to za stosowne. Nie ma dla mnie powodu, dla którego nie możesz przekazać modelu domeny z poziomu warstwy danych, niektórzy decydują się na używanie DTO tylko tutaj.Zrobię mapowanie w warstwie UI (z kontrolera MVC) do ViewModel, ponieważ mogę zrobić to za pomocą AoP (atrybut [AutoMap()])

Pamiętaj tylko, że twoje modele nie powinny zawierać jakakolwiek logika wytrwałości w ogóle.

+0

Dzięki Adam. Umieszczenie interfejsów repozytorium w domenie wydaje się być dobrym sposobem na zachowanie wszystkiego wokół domeny. Na punkcie trwałości, moje modele domen mają wygodniejsze metody Save(), które wywołują metodę Save() w odpowiednim repozytorium. Czy uważasz, że jest to logika wytrwałości, a zatem i zła praktyka? – Giles

+0

ya, nie powinni nic o tym wiedzieć. Przekaż element do swojego repozytorium i niech to będzie jedyne miejsce do obsługi wszystkiego. to następnie ładnie dopasowuje się do wzorca pracy jednostki, ponieważ repozytoria mogą być refaktoryzowane, aby teraz faktycznie zapisać je do kolekcji, a jednostka pracy implementacji zapisuje to zbieranie do bazy danych w jednej transakcji. Twoje usługi, zamiast wywoływać Save() na modelach, zamiast tego po prostu wiesz, aby wywołać implementację repozytorium, które powinno zostać wstrzyknięte do kontrolera lub repozytorium. To ładnie nadaje się do testowania/szyderstwa/etc. –

2

Myślę, że to dość typowe dla każdej aplikacji "rzeczywistego świata" do przechowywania danych inaczej niż na ekranie. Myślę, że jesteś na dobrej drodze, mając 2 oddzielne "modele". Zwykle kończę je nazywanie:

  • ViewModels - mapowanie do tego, co jest wyświetlane na ekranie, jakie widoki chcą.
  • DataModels - mapować do bazy danych, czego potrzebuje warstwa trwałości (ORM).

Czasami DataModels nazywane są Entities zwłaszcza gdy mówimy o Entity Framework jako warstwa dostępu do danych lub Data Transfer Objects (DTOs).

Zazwyczaj jest jakiś zestaw "tłumaczy" do mapowania z widoku do modeli danych, albo czasami można użyć AutoMappera.

Oczywiście, jeśli wyświetlane dane są wystarczająco zbliżone do struktury danych, nie ma nic złego w przekazywaniu wszystkich modeli trwałości/danych do widoków, ale ja też lubię je rozdzielać.

+0

Dzięki. Zaczynam się zastanawiać nad modelami DTO. Moje modele niekoniecznie są prostymi mapowaniami z pojedynczych tabel bazy danych. Być może będę musiał odpowiedzieć na mój post, aby wyjaśnić to poprawnie, chociaż .. – Giles

2

ja uważane za jedne z pomysłów w cebuli Architecture (czyli Dependency Injection), aby rozwiązać ten problem, ale wydaje się, że bardziej eleganckie rozwiązanie oczywiste/mogą być niedostępne.

Po prawidłowym użyciu Dependency Injection jest to bardzo eleganckie/oczywiste rozwiązanie.

Sugeruję strukturę zależności takiego:

  • UI
    • Kontrolery -> Usługi, modele, ViewModels
    • widoki -> ViewModels
    • ViewModels (brak zależności)
  • Usługi -> Repozytoria, modele
  • Repozytoria -> Modele
  • Modele

Jest to dość blisko do tego, co przedtem, ale twoi ViewModels są częścią projektu interfejsu użytkownika i nie ma zależności w ogóle. Powinny to być proste klasy, które reprezentują to, co chcesz pokazać użytkownikowi.

To praca kontrolera do:

  • wywołać usługi, aby uzyskać modele,
  • Przekłada modeli do ViewModels i
  • Wywołanie kodu Zobacz

Widoki nie powinny wymagają wszelkich informacji, które nie są dostarczane przez ViewModels.

+0

Dzięki. Myślę, że Dependency Injection zaczyna wyglądać jak droga. Projekt jest już dość skomplikowany (według moich standardów ..) i implementacja DI może być sporym wyzwaniem. – Giles

+0

@Giles: DI ma tendencję, by podążać za dobrymi wzorami projektowymi. Ponieważ nie używasz go od samego początku, może pojawić się pewien ból, który sprawi, że twój kod będzie podążał za wzorami, które powinny być używane przez cały czas. Ale jeśli zrobisz to dobrze, DI powinien naprawdę pomóc ci uprościć wszystko. Powodzenia. – StriplingWarrior

Powiązane problemy