Może trochę dziwić w kontekście "standardowej" struktury projektu. Pewnie przyzwyczajeni jesteście do struktury:
- controller - odpowiedzialny za rejestrownie endpointów, mapowanie jsonów do obiektów oraz wywołanie operacji na serwisie, odebranie
- service - cała logika aplikacji mieści się tutaj. Ładujemy model z bazy danych, często translacja na obiekty, na których operujemy w serwisie. Następnie wykonanie operacji bizneswej, ewentualna translacja na model do zapisu, i persystencja obiektu.
- model - w zasadzie anemiczna encja, nie posiada żadnych biznesowych metod
- repository - ładowanie i zapisywanie w bazie danych
W zasadzie składa się z 3 głównych "warstw":
- application - instrumentacja domeny - załadowanie obiektów, wykonanie operacji biznesowych oraz zapisanie zmienionych obiektów
- domain - zawiera cała logika znajduje się tutaj, encje, agregaty i value objecty
- infrastructure - adaptery do portów wystawionych w domenie, persystencja obiektów domenowych, implementacja usług, używanych przez domenę
Domena zarządzania użytkownikami. Dodawanie użytkownika, walidowanie czy danych użytkownik już istnieje, walidowanie hasła. Aktywowanie użytkownika, obsługa wygasania hasła.
- application - controller + instrumentacja domeny
- user, idgenerator interface, implementacja w infrastrukturze
Encja to jeden z podstawowych budulców domenowych w DDD. To obiekt, który można jednoznczanie zidentyfikować po id. Obiekt ten może zmieniać swój stan w trakcie życia systemu. Dba też o swoje niezmienniki (invariants), zapewnia, że jest zawsze w poprawnym, spójnym stanie.
Przykładem encji jest User. Wspomnijmy o aggreagacie.
Możliwe strategie generowania idków (przez application service albo przez repository).
Persistence:
- zapewniona unikalność
- korzystamy często z gotowych mechanizmów
- czas generowania
Application:
- szybkość
- czasami przez wymagania nie jest możliwy do zaimplementowania (idki numeryczne unikalne)
plusy:
- dostępność od raz - struktury hashujące
Służy do persystencji stworzony encji. Jest to element domeny, domena nie zależy od niczego, jedynie infrastruktura implementuje domenę. Implementacja na razie w pamięci ale będziemy to rozwijać.
Ukrywa bardziej zaawansowane kreowanie obiektów.
Drugi building blok. W przeciwieństwie do encji nie są to obiekty, które musimy móc jednoznacznie zidentyfikować. Posiadają swoje atrybuty. Jest niemutowalny, składnik encji. Wrapper na typy proste, często posiadający specjalne zachowania (nie tylko value holder). Przykładowe VO:
- Date (nie po prostu string)
- Money (a nie bigdecimal + zachowania)
- Password
Czemu nie prosty type:
- większa ekspresja wyrazu - bardziej domenowo odbieramy kod
- mogą posiadać od razu własną walidację
- dodatkowe zachowania
Przykładowe operacje biznesowe które możemy zaimplementować to:
- resetowanie hasła
- blokowanie użytkownika - przestaje mieć możliwość logowania
- odblokowanie użytkownika - + dodatkowe wymaganie - nie może się zalogować starym hasłem;
Interfejs do domeny - PORT przez który wchodzi się ze znanym API. Instruuje domenę i możę wykonywać dodatkowe akcje. Przykładowe użycia:
- uwierzytelnianie - w springu np. @PreAuthorize
- emailing
- wysyłanie eventów
- sprawdzenie czy obiekt istnieje
W zasadzie w naszym przypadku całkiem dobry application service może być nasz endpoint.
Wrapuje obiekty domenowe żeby wyrazić coś czego nie może pojedyncza encja. Jakby rozwinięcie tego czego nie widać w zamodelowanych obiektach domenowych. Mogą to być też obiekty uzyskujące potrzebne informacje z zewnątrz.
Przejscie na repozytorium w mongo
Rozdzielenie sposobu obsługi modyfikacji obiektów od ich querowania. Plusy:
- różne modele (nie interferują ze sobą), nie tworzymy niepotrzebnych metod dostępowych
- w różny sposób obsługiwane mogą być pod spodem (nawet inna baza danych!)