Warstwa aplikacji a warstwa domeny?

47

Czytam projektowanie oparte na domenie autorstwa Evansa i jestem w części, omawiając architekturę warstwową. Właśnie zdałem sobie sprawę, że warstwy aplikacji i domeny są różne i powinny być oddzielne. W projekcie, nad którym pracuję, są one mieszane i nie mogę powiedzieć różnicy, dopóki nie przeczytam książki (i nie mogę powiedzieć, że jest to dla mnie teraz bardzo jasne), naprawdę.

Moje pytania, ponieważ oba dotyczą logiki aplikacji i powinny być czyste z aspektów technicznych i prezentacji, jakie są zalety wyznaczenia granicy między tymi dwoma?

Louis Rhys
źródło

Odpowiedzi:

36

Niedawno sam przeczytałem DDD. Gdy doszedłem do tego działu, byłem mile zaskoczony, gdy odkryłem, że odkryłem tę samą 4-warstwową architekturę, co Evans. Jak wskazał @lonelybug, warstwa domeny powinna być całkowicie odizolowana od reszty systemu. Jednak coś musi tłumaczyć wartości specyficzne dla interfejsu użytkownika (ciągi zapytań, dane POST, sesja itp.) Na obiekty domeny. Tutaj zaczyna się warstwa aplikacji. Jego zadaniem jest tłumaczenie w tę iz powrotem między interfejsem użytkownika, warstwą danych i domeną, skutecznie ukrywając domenę przed resztą systemu.

Widzę teraz wiele aplikacji ASP.NET MVC, w których prawie cała logika znajduje się w kontrolerach. To nieudana próba wdrożenia klasycznej architektury 3-warstwowej. Kontrolery są trudne do testowania jednostkowego, ponieważ mają wiele problemów związanych z interfejsem użytkownika. W rzeczywistości napisanie kontrolera tak, aby nie dotyczył bezpośrednio wartości „kontekstu HTTP”, jest poważnym wyzwaniem samym w sobie. Najlepiej byłoby, gdyby kontroler wykonał tłumaczenie, koordynował pracę i odrzucił odpowiedź.

Może nawet mieć sens przeprowadzanie podstawowej weryfikacji w warstwie aplikacji. Domena może założyć, że wchodzące w nią wartości mają sens (czy jest to prawidłowy identyfikator dla tego klienta i czy ten ciąg reprezentuje datę / godzinę). Jednak walidacja z wykorzystaniem logiki biznesowej (czy mogę zarezerwować bilet lotniczy w przeszłości?) Powinna być zarezerwowana dla warstwy domeny.

Martin Fowler komentuje, jak płaskie są obecnie większość warstw domen . Chociaż większość ludzi nawet nie wie, co to jest warstwa aplikacji, odkrywa, że ​​wiele osób tworzy raczej głupie obiekty domenowe i złożone warstwy aplikacji, które koordynują pracę różnych obiektów domenowych. Jestem tego winny. Ważną rzeczą nie jest budowanie warstwy, ponieważ kazała ci to jakaś książka. Chodzi o to, aby zidentyfikować obowiązki i oddzielić nasz kod na podstawie tych obowiązków. W moim przypadku „warstwa aplikacji” ewoluowała naturalnie, gdy zwiększyłem testy jednostkowe.

Travis Parks
źródło
9
Nie sądzę, aby to, co tu podałeś, było poprawne: „Jednak coś musi tłumaczyć wartości specyficzne dla interfejsu użytkownika (ciągi zapytań, dane POST, sesja itp.) Na obiekty domeny. W tym miejscu wchodzi warstwa aplikacji”. To, o czym mówisz, to w terminologii DDD warstwa „prezentacji”. Warstwa aplikacji ma rozwiązywać problemy z hydrauliką, współbieżnością i przekrojami, będąc jedynie niewielkim opakowaniem w warstwę domeny. To, co opisujesz, odpowiadałoby (pod) warstwie w warstwie prezentacji.
pożarł elysium
23

W oparciu o wzorce projektowania korporacyjnego Martina Fowlera najczęstsze warstwy to:

  • Prezentacja - są to widoki, szablony prezentacji, które generują interfejs interakcji dla Twojej aplikacji (korzystam z interakcji w przypadku, gdy dostęp do Twojej aplikacji mają inne systemy za pośrednictwem usług internetowych lub RMI, więc może nie być interfejsem użytkownika). Dotyczy to również kontrolerów, które decydują o sposobie wykonywania akcji i sposobie ich wykonywania.

  • Domena - tutaj znajdują się reguły biznesowe i logika, zdefiniowane są modele domen itp

  • Źródło danych - jest to warstwa mapowania danych (ORM) i źródło danych (baza danych, system plików itp.)

Jak narysować granice między trzema warstwami:

  • Nie umieszczaj logiki specyficznej dla prezentacji w modelach lub obiektach domeny

  • Nie umieszczaj logiki na swoich stronach i kontrolerach, tj. Logiki do zapisywania obiektów w bazie danych, tworzenia połączeń z bazami danych itp., Które spowodują, że warstwa prezentacji będzie krucha i trudna do przetestowania

  • Użyj ORM, który umożliwia oddzielenie dostępu do źródła danych i działań od modelu

  • Postępuj zgodnie z cienkim kontrolerem - paradygmat modelu tłuszczu, kontrolery służą do kontrolowania procesu wykonywania, który go nie realizuje, więcej na http://www.littlehart.net/atthekeyboard/2007/04/27/fat-models-skinny-controllers/ oraz http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model model, widok i kontroler,

Stephen Senkomago Musoke
źródło
17

Warstwa domeny modeluje działalność Twojej aplikacji. To powinna być twoja jasna interpretacja jego zasad, dynamiki komponentów i zawiera swój stan w danym momencie.

Warstwa aplikacji „martwi się” o zdefiniowanie zadań, które należy wykonać, aby wykonać określone zadanie aplikacji. Głównie odpowiada za mandat za niezbędne prace w domenie i współdziała z innymi (zewnętrznymi lub nie) usługami.

Na przykład moja aplikacja finansowa ma operację użytkownika służącą do zmiany stanu encji modelowej (encji zdefiniowanej w DDD [89]):

  • „Szef operacji może zatwierdzić propozycję finansową”.

Ale jako proces aplikacji, oprócz wszystkich konsekwencji modelowych tej operacji, muszę wysłać komunikację wewnętrzną do innych użytkowników aplikacji. Ten rodzaj pracy jest „koordynowany” w warstwie aplikacji. Nie chciałbym, aby moja warstwa domeny myślała o kierowaniu usługą przesyłania wiadomości. (i na pewno nie jest to odpowiedzialność warstwy prezentacji). Niezależnie od sposobu, jedno jest pewne: potrzebuję nowej warstwy, ponieważ moja warstwa domeny dotyczy podstawowej działalności, a moja warstwa prezentacji dotyczy interpretacji poleceń użytkownika i prezentacji wyników.

Uwagi:

  • Biznes to jedno z tych słów, które często prowadzą do wielu interpretacji jego znaczenia, ale na pewno można znaleźć wiele przykładów i dyskusji w DDD;
  • DDD oznacza książkę opartą na domenie autorstwa Erica Evansa i numer w nawiasach kwadratowych dla numeru strony.
José Andias
źródło
6

Warstwę domeny należy zaprojektować jako warstwę izolacyjną, co oznacza, że ​​żadna zmiana kodu (w warstwie aplikacji, warstwie prezentacji i warstwie infrastruktury) nie powinna mieć wpływu na logikę biznesową i reguły.

Warstwa aplikacji ma być zaprojektowana tak, aby zapewniała pewne funkcje dotyczące interfejsu systemu (aplikacji) (tak jak API lub RESTful). Na przykład użytkownicy mogą zalogować się do systemu, aw tym działaniu aplikacji (logowanie) kody warstwy aplikacji będą kodami klienta dla warstwy domeny (lub warstwy infrastruktury), w której pobiera obiekt domeny użytkownika i stosuje metody tego obiektu w celu zaimplementowania funkcja „logowania”.

Warstwa aplikacji powinna również zostać zaprojektowana jako warstwa izolacyjna, co oznacza, że ​​na zachowanie aplikacji nie powinny mieć wpływu żadne zmiany (w warstwie prezentacji, warstwie domeny i warstwie infrastruktury).

stevesun21
źródło
2
Przynajmniej w literaturze, takiej jak Domain-Driven Design (Evans), wiadomo, że warstwy mają zależność jednokierunkową ... faktem jest, że w pewnym momencie twój kod zależy od czegoś . Interfejs użytkownika zależy od aplikacji, ale nie odwrotnie. Aplikacja zależy od domeny, ale nie odwrotnie. Domena w infrastrukturze, a nie odwrotnie.
1
Zależność polega na tym, jak programujesz, a warstwa izolacyjna polega na tym, jak projektujesz warstwy systemowe. Zależność w jednym kierunku nie złamała tutaj koncepcji izolacji, ponieważ podczas programowania kod górnej warstwy powinien zależeć od interfejsu niższej warstwy niż klas implementacyjnych.
stevesun21
To świetnie, wszystko na papierze, ale w praktyce wymagania biznesowe powodują zmiany, które mogą wpływać na interfejs warstwy aplikacji w taki sposób, że zmiany przechodzą przez warstwę prezentacji, a czasem nawet do warstwy pamięci. To wszystko, co dostawałem ...
Projekt warstwy izolacyjnej nie oznacza, że ​​żadne zmiany nie będą dozwolone w przyszłości. Przeciwnie, sprawia, że ​​zmiany są znacznie łatwiejsze - łatwiejsze do przetestowania i łatwiejsze do oszacowania prac. Tak, nowy wymóg biznesowy oznacza, że ​​możesz potrzebować zmiany z góry na dół, czy nie jest to sposób, w jaki wcześniej zaimplementowałeś istniejącą funkcję? Jeśli możesz zaprojektować każdą warstwę w oparciu o zasady SOLID, może się okazać, że możesz po prostu ponownie wykorzystać istniejące funkcje z dolnej warstwy.
stevesun21
3

Modelowanie oparte na domenach polega na oddzieleniu podstawowego modelu domeny i jego istnieniu bez żadnych zależności od innych warstw i innych problemów związanych z aplikacją.

Pozwala to skupić się na samej domenie bez zakłóceń (takich jak koordynacja interfejsu użytkownika i usług trwałości).

Oded
źródło
Czy źródło danych (ORM) znajduje się w domenie?
Maykonn
@Maykonn - Może być. ORM nie jest jednak źródłem danych. Jest to narzędzie między Twoim kodem a rzeczywistym źródłem danych (relacyjna baza danych). Sposób uzyskiwania dostępu do danych nie powinien być przedmiotem zainteresowania domeny - konstruktorzy i fabryki mogą sobie z tym poradzić (i ORM, jeśli taki masz).
Oded
Zgadzam się. I myliłem się co do źródła danych i ORM. Dzięki!
Maykonn
3
  • Warstwa aplikacji i warstwa domeny wchodzą w zakres wdrożenia.
  • Warstwa aplikacji działa jako interfejs API.
  • Warstwa domeny działa jako implementacja interfejsu API, zawiera logikę biznesową, dlatego jest również nazywana warstwą logiki biznesowej.

wprowadź opis zdjęcia tutaj

Premraj
źródło
nigdy tego nie myślałem w ten sposób ... Czuję się oświecony
Nikos
2

Głównym powodem tych granic jest rozdzielenie obaw . Kod, który uzyskuje dostęp do magazynu danych, powinien tylko martwić się o dostęp do magazynu danych. Nie powinien ponosić odpowiedzialności za egzekwowanie zasad dotyczących danych. Ponadto interfejs powinien być odpowiedzialny za aktualizowanie kontrolek w interfejsie, uzyskiwanie wartości z danych wejściowych użytkownika i tłumaczenie ich na coś, z czego warstwa domeny może korzystać, i nic więcej. Powinien wywoływać operacje zapewniane przez warstwę domeny, aby wykonywać wszelkie niezbędne działania (np. Zapisać ten plik). Wywoływana usługa internetowa powinna być odpowiedzialna za konwersję z medium transmisyjnego na coś, z czego może korzystać warstwa domeny, a następnie wywołać warstwę domeny (większość narzędzi wykonuje za Ciebie wiele pracy).

Ta separacja, jeśli zostanie poprawnie zaimplementowana, może pozwolić ci na zmianę części twojego kodu bez wpływu na inne. Na przykład być może kolejność sortowania zwróconej kolekcji obiektów wymaga zmiany. Ponieważ wiesz, że warstwa odpowiedzialna za manipulowanie danymi (zwykle warstwa logiki biznesowej) obsługuje te rzeczy, możesz łatwo określić, gdzie należy zmienić kod. Oprócz tego, że nie muszę modyfikować sposobu, w jaki jest pobierany ze magazynu danych lub dowolnej aplikacji korzystającej z domeny (interfejs użytkownika i usługa internetowa z mojego przykładu powyżej).

Ostatecznym celem jest uczynienie twojego kodu tak łatwym w utrzymaniu, jak to możliwe.

Na marginesie, niektóre rzeczy nie mogą być zaszufladkowane w określonej warstwie domeny (np. Rejestrowanie, sprawdzanie poprawności i autoryzacja). Te elementy są powszechnie nazywane problemami przekrojowymi, aw niektórych przypadkach można je traktować jako warstwę, która sama w sobie jest widoczna i może być używana przez wszystkie pozostałe warstwy.

Osobiście uważam, że podejście warstwowe jest przestarzałe, a podejście serwisowe jest lepsze. Nadal masz wyraźną linię narysowaną na piasku, kto co robi, ale to nie zmusza cię do bycia tak hierarchicznym. Na przykład usługa zamówienia zakupu, usługa fakturowania i usługa wysyłki, z perspektywy aplikacji wszystkie te usługi reprezentują Twoją domenę, a odroczenie odpowiedzialności, którą opisałem powyżej, jest nadal aktualne w tym kontekście, właśnie zostało zmienione takie że Twoja domena istnieje w wielu miejscach, dodatkowo wykorzystując koncepcję separacji problemów.

Charles Lambert
źródło
Byłem ciekawy umiejscowienia logiki autoryzacji i z tego, co próbuję zrozumieć, pasuje ona do „warstwy aplikacji”. Czy mógłbyś podzielić się spostrzeżeniami na temat tego, dlaczego umieszczenie go w tej warstwie logicznej może nie być najlepsze?
1
To idealny rodzaj pytania dla tej strony. Powinieneś to opublikować, aby każdy miał szansę odpowiedzieć.
Charles Lambert
@tuespetre Czy możesz podać link do tego postu?
drizzie,