Zrozumienie DDD oraz Onion Architecture

Odpowiedz Nowy wątek
2019-09-16 09:27
0

Cześć. Miałbym do was pytania które mnie nurtują :)
Chcę stworzyć aplikację ASP.NET MVC zgodną z DDD. Stworzyłem 3 warstwy aplikacji:

  • Warstwa Domain która zawiera modele domenowe, jest to niejaki rdzeń aplikacji, oraz w folderze repositories zawiera interfejsy użyteczne dla warstw wyższych.
  • Warstwa Persistence która zawiera klasę w której tworzonę są obiekty odpowiadające fizycznej bazie danych, oraz które będą odpowiadać za komunikację z serwerem SQL. Zawiera także folder z migacjami oraz folder z konfiguracjami encji.

  • Wartswa Infrastructure - która zawiera Folder DTO w tym folderze znajdują się klasy służace do wykonywania operacji na danych. Folder AutoMapper. Zawierające konfigurację mappera. A także folder Services gdzie znajdują się serwisy aby wartstwa WebUI nie zawierała logiki biznesowej.

Korzystałem mniej wiecej z tego diagramu:

https://ibb.co/T0Gn7BB

Kod do tego projketu:

https://github.com/Michal-Warmuz/Online-Shop-v.2.0

A to moje pytanie ?
Czy dobrze wszystko rozumiem czy to co napisałem jest poprawne ? Oraz co dokładnie powinna zawierać warstwa Application, Bo z tego co wiem powinna zawierać implementacje wysyłania emaila itd.
Oraz czy mogę mappować view modele ?

edytowany 1x, ostatnio: Michał Warmuz, 2019-09-16 09:33

Pozostało 580 znaków

2019-09-16 09:43

Projekt Application powinien zawierać klasy realizujące logikę aplikacji, tj. np. jakąś ProductService operującą na IProductRepository. Ogólnie chodzi o to, że nie można całej logiki upchnąć w warstwie domeny (np. autoryzacji, mapowań), dlatego potrzebujemy tej warstwy. Implementację klasy wysyłającej emaili powinieneś mieć w Infrastructure, a odpowiedni interfejs IEmailSender np. w Application lub Core (którego nie masz, Core to zazwyczaj Domain + jakieś interfejsy infrastrukturalne czy klasy używane powszechnie w całej aplikacji - np. Result/Option/Either). DTO powinny znajdować się w Application, bo to przy ich użyciu warstwa aplikacji będzie komunikować się z warstwą prezentacji (tzn. Twoja ProductService będzie przyjmować np. AddProductDto).
Co do DDD, zastanów się, czy na pewno chcesz w to iść, bo to nie jest proste. Jak na razie Twoje encje z Domain nie mają nic wspólnego z DDD. Jeśli chcesz jakiś projekt do referencji, to zobacz sobie repozytoria Kamila Grzybka na GitHubie: https://github.com/kgrzybek/sample-dotnet-core-cqrs-api Ma on też swój blog: http://www.kamilgrzybek.com/

edytowany 3x, ostatnio: nobody01, 2019-09-16 10:28

Pozostało 580 znaków

2019-09-16 09:50
3

Nie zabieraj się za DDD i onion-architecture jednocześnie. Oba mogą się jak najbardziej uzupełniać ale DDD to obszerne zagadnienie i lepiej do tego podejść oddzielnie. Nie mam obecnie czasu przeglądnąć Twojego kodu niestety ale już samo to zdanie

Wartswa Infrastructure (...) older Services gdzie znajdują się serwisy aby wartstwa WebUI nie zawierała logiki biznesowej.

świadczy że źle do tego podszedłeś- w świetle DDD przynajmniej.Cały sens w tym żeby mieć bogaty model domeny, ale do tego dochodzi sporo innych zagadnień które też należy uwzględnić: aggregates, aggregate roots, bounded contexts. ubiquitous language


Na każdy złożony problem istnieje rozwiązanie które jest proste, szybkie i błędne.

Pozostało 580 znaków

2019-09-16 11:22
2019-09-16 13:56
0

@nobody01: Kurde jest strasznie trudne :) Tutaj już zrobiłem pierwsze poprawki https://github.com/Michal-Warmuz/Online-Shop-v.2.0. Tylko mnie ciekawi jak stworzę ProductDTO to w kontrolerze mogę miec coś takiego ?

        [HttpGet]
        public ViewResult ViewProduct(Guid id)
        {
            ProductDTO product = productService.Get(id);
            return View(product);
        }

a potem w widoku umieścić model ProductDTO
czy lepiej stworzyć ViewModel odzielny ?

edytowany 3x, ostatnio: cerrato, 2019-09-16 14:50

Pozostało 580 znaków

2019-09-16 14:28
1

Sam kiedyś o to tu pytałem. Masz kilka opcji:
1) Wyrzucić ViewModele do jakiegoś projektu Contracts będącego pomostem pomiędzy Application a Web (obydwa projekty będą mieć do niego referencje). Zaletą jest mała ilość kodu. Zazwyczaj granice między warstwami będą wystarczająco zarysowane.
2) Stworzyć osobne DTO i umieścić je w warstwie aplikacji. Będzie więcej kodu, ale ViewModele pozostaną tam, gdzie powinny być: w Web (będziesz mógł zrobić sobie ładne feature folders). Będziesz mógł również użyć sobie w warstwie aplikacji biblioteki MediatR, tu post @Aventus pokazujący, jak to może wyglądać: https://4programmers.net/Forum/1567409
3) Wrzucić logikę aplikacji do Web, tak jak u Kamila.

W skrócie: potrzebujesz MediatR? Opcja 2. Nie potrzebujesz? Opcja 1.

edytowany 1x, ostatnio: nobody01, 2019-09-16 14:34

Pozostało 580 znaków

2019-09-17 09:48
2

Artykuł który zalinkował @Markuz jest ogólnie dobry ale trochę mylny. Autor już w samym tytule wymienia DDD natomiast już w samym artykule pisze że logikę biznesową/domenową obejmująca więcej niż jedną encję umieścił w serwisach domenowych co świadczy że w kontekście DDD ma coś źle zamodelowane. Popełnia dosyć częsty błąd- nazywa coś w swojej aplikacji modelem domeny i zakłada że ma DDD. Oczywiście dalej wymienia bounded contexts ale pomija inne bardzo ważne elementy, takie jak agregaty (aggregates) którymi rozwiązał by problem wymieniony wcześniej. Moim zdaniem zastosował tutaj coś co ja nazywam "lekkim DDD" i nie ma w tym nic złego, tylko bardzo uważał bym z mówieniem że jest to DDD (pełnoprawne). Stwierdzić że ma się DDD to pojęcie dosyć absolutne, i siłą rzeczy zakłada użycie wszelkich innych aspektów DDD a nie tylko jednego czy dwóch wybranych. Co za tym idzie nie, autor nie ma aplikacji opartej o DDD. Proszę nie dać się zwieść tytułem.


Na każdy złożony problem istnieje rozwiązanie które jest proste, szybkie i błędne.
edytowany 1x, ostatnio: Aventus, 2019-09-17 09:50
Pokaż pozostałe 17 komentarzy
Bo uznaliby, że niepotrzebnie komplikuje projekt :p - szydlak 2019-09-17 15:20
Wstępnie przyglądałem się temu, i jakbym miał dołożyć kolejny moduł to trochę by to trwało. I jeszcze ten Event sourcing - szydlak 2019-09-17 15:21
No jeśli taki zmiana nie przyniosła by korzyści projektowi to wiadomo że nie ma sensu komplikować ;) Natomiast nie wiem czemu zakładasz konieczność używania Event Sourcingu stosując modularny monolit. Nie ma takiej potrzeby. - Aventus 2019-09-17 15:40
@Aventus: Dyskusja trochę przeszła na inny tor, a ja dalej jestem ciekaw Twojej opinii na temat projektu, który zalinkowałem: https://github.com/kgrzybek/modular-monolith-with-ddd Jest też prostszy projekt: https://github.com/kgrzybek/sample-dotnet-core-cqrs-api Chciałbym się upewnić, że pamiętasz. Oczywiście nie spieszy mi się i nie naciskam na nic :) - nobody01 2019-09-19 12:16
@nobody01 przeglądałem to sobie i wygląda dosyć ciekawie. Z braku czasu nie zagłębiałem się za bardzo, jest parę rzeczy które rzuciły mi się w oczy i bym poprawił- ale zawsze będzie się miało uwagi do czyjegoś kodu, to normalne. Facet zrobił kawał dobrej roboty, szczególnie z dosyć obszerną dokumentacją. Mi by się nie chciało :D - Aventus 2019-09-19 12:21

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0