poniedziałek, 4 lipca 2011

Domain Driven Design - Sposób na projektowanie złożonych modeli biznesowych (plus niespodzianka)

W ostatnim numerze Software Developer's Journal ukazał się artykuł mojego autorstwa: "Domain Driven Design - Sposób na projektowanie złożonych modeli biznesowych".

Tekst przeznaczony jest zarówno dla początkujących jaki i średnio zaawansowanych praktyków DDD.
Początkujący znajdą w nim:
- ogólną ideę oraz zakres stosowalności podejścia
- przykłady kodu
a średnio zaawansowani mogą zapoznać się między innymi z:
- technikami komunikacji zdarzeniowej pomiędzy Bounded Context
- nową koncepcją Sagi biznesowej

Zachęcam oczywiście do pobrania i przeczytania całego numeru SDJ, ale dla wygodnych link bezpośredni do tekstu: pobierz.

Dla wzrokowców przydatna może być prezentacja ilustrująca architekturę systemu wykorzystującego DDD: Domain Driven Design - A place for everything and everything in its place. tekst artykułu jest niejako narracją do tej prezentacji.


//====================================

Przy okazji zdradzę informację związaną z tematem posta. W firmie Bottega pracujemy dla Was nad upublicznieniem projektu-sampla (wraz z dokumentacją) ilustrującego w realny i niestrywializowany sposób wszystkie techniki DDD oraz kilka możliwych podejść do implementacji CqRS.

Aktualnie dla środowiska Javy istnieją tylko 2 projekty oscylujące wokół tej tematyki (za: http://cqrsinfo.com/examples) a nasz będzie charakteryzował się:
- prezentacją szerokiego wachlarzu technik DDD w różnych kontekstach
- praktycznym rozwiązaniem typowych wyzwań i problemów projektowych
- gotowym do użycia szkieletem: Spring, Maven, JPA, klienty webowe i zdalne (Android, Ajax)
- kompletna wiki opisująca ideę oraz wyjaśniająca wszystkie szczegóły techniczne, podjęte decyzje projektowe i architektoniczne oraz omawiająca możliwości zmiany podejścia i jego rozbudowy
- wsparciem dla testów integracyjnych oraz metodyki Behavior Driven Developemnt
- wsparciem dla skalowania w środowisku cloud
- racjonalnym podejściem do CqRS bez niepotrzebnego onanizmu technicznego
- i co najważniejsze: nie tworzymy kolejnego frameworka! Formą dystrybucji będzie "zaczyn" (zaczyn to coś z czego wyrasta chleb - ten prawdziwy:)
To Ty jesteś architektem i decydujesz jak wygląda Twój kod!
- sample będzie oczywiście całkowicie darmowy i otwarty

16 komentarzy:

Mirek pisze...

Pomysł z przykładem bardzo fajny. Rzeczywiście w necie niewiele jest przykładów DDD w Java... Dla mnie było by idealnie zobaczyć siłę DDD w sytuacji zmiany wymagań(dochodzeniu nowych)(nowe branche). Czy misternie zaprojektowana struktura klas i technik obiektowych musi zostać całkowicie przeprojektowana czy da się za pomocą niewielkiego nakładu sił spełnić wymagania. Również ciekawym doświadczeniem byłoby zobaczenie fragmentu systemu z pomocą użycie TransactionScript i tego samego w DDD.(branch DDD,TS)

Pozdrawiam

ToJaJarek pisze...

@"Czy misternie zaprojektowana struktura klas i technik obiektowych musi zostać całkowicie przeprojektowana czy da się za pomocą niewielkiego nakładu sił spełnić wymagania."

W dobrym projekcie własnie nie ma takiej potrzeby, DDD zakąłda "odwzorowanie rzeczywistości", model nie jest uproszczony (normalizowany) więc dodawanie nowych rzeczy jest "dodawaniem" a nie "zmianą".

Michał Huniewicz pisze...

Dzieki za artykul. Czy sa inne roznice miedzy DAO a Repository oprocz jednej wymienionej?

jnb pisze...

Bardzo ładny artykuł. Świetne dopełnienie mini książeczki o DDD z InfoQ. Szkoda że nie wrzuciłeś diagramu (jeden obraz, tysiąc słów) pokazujących komunikację/wykorzystanie bloków.

Zastanawiam się tylko, czy artykuł jest zrozumiały dla osób bez wiedzy o DDD. Myślę, że będzie się go lepiej czytało z przykładem (zaczynem projektu). Moglibyście w nim umieścić kilka alternatywnych rozwiązań z wyjaśnieniem trade-off'ów, bo to dla początkujących (przynajmniej z mojego doświadczenia) nie zawsze jest jasne.

Sławek Sobótka pisze...

@Mirek
Oczywiście to zależy od zakresu zmian...
Tak jak w realu - w pewnym momencie albo się rozsypie albo sami przerobimy.

Ale techniki modelowania DDD są dosyć "defensywne". Przykładowo po to hermetyzujemy agregat aby zmiany miały miejsce w jego obrębie i nie miały impaktu to "otoczenie". Po to też czasem z agregatu zwracamy VO, które są jedynie projekcją jego wnętrza. Po to też walczymy o decoupling przy pomocy zdarzeń.

Co do zmiany na zasadzie branchowania, to rozumiem, że w jakiejś wersji (ew. u jakiegoś klienta) system zachowuje się w pewien sposób a w innej w inny.
Jeżeli o to chodzi to służy do tego cała bateria technik: strategie (różne impl, dekorowanie strategii), specyfikacje (różne struktury), zdarzenia (w sensie w różnych wersjach różne listenery).

Ale techniki są prosta - o ile zna się te wzorce. Prawdziwy problem polega na tym aby zauważyć i przewidzieć gdzie w modelu je zastosować:P


@Jarek
Modelujemy "tylko" to co uda nam się dowiedzieć od eksperta domenowego... a jeżeli ekspert nagle przejrzy na oczy i uzna, że ziemia nie jest płaska lecz okrągła to mamy problem:)

@Michał
Repo jest związane z agregatem. Ma za zadanie go zwrócić w gotowości do pracy - czyli jeżeli jest taka potrzeba to dokonuje na nim wstrzyknięć zależności (chyba, że używamy @Configurable ze Springa). Aby poskładać agregat może zachodzić potrzeba sięgnięcia do różnych źródeł danych. Sam nie miałem takiej potrzeby, ale widziałem systemy, gdzie Repo używało kilku DAO (sięgających do bazy, WS itd).

DAO kiedyś gdy powstawało zwracało obiekty danego typu. Wraz z pojawieniem się ORMów DAO zwraca w jakimś sensie Agregaty (lazy loadowane albo eager pobierane grafy). Są one zwykle anemiczne. Ale dao zwykle zawiera też kilkanaście/kilkadziesiąt metod wyszukujących pisanych na potrzeby GUI.

@Jakub
Jakiś rodzaj wizualizacji znajduje się w podlinkowanej prezentacji na Prezi - są tam rozysowane warstwy, BB i strzałki pokazujące komunikację. Całość można zoomować kółkiem myszki.

Co do przykładu to planujemy właśnie aby odróżniał się od tego co jest dostępne właśnie prezentacją różnych podejść. A w wiki będą opisane trade-off'y.

Michał Huniewicz pisze...

Dzieki za odopwiedz. :)
A co jesli moje GUI dalej potrzebuje tych wielu roznych metod? Jak DDD to rozwiazuje przy pomocy repozytoriow?

Sławek Sobótka pisze...

Repo używane jest tylko w kodzie nieimplementującym use casy/user stories, które wykonują jakieś operacje biznesowe. Technicznie są wołane prze serwisy aplikacyjne, ale również inne building blcoks.

Natomiast wyszukiwanie danych dla widoków to specjalność osobnych serwisów. Jest to uzasadnione o tyle, że gdy wyświetlamy dany to zwykle potrzeba jakiś przekrojowych danych a agregaty ze swoimi grafami obiektów są nieodpowiednie.

Bardzo wyraźnie widać to rozdzielenie w architekturze Command-query responsobility Segregation. Zobacz tu prezentację: http://art-of-software.blogspot.com/p/artykuy-i-prezentacje.html

ToJaJarek pisze...

"Modelujemy "tylko" to co uda nam się dowiedzieć od eksperta domenowego... a jeżeli ekspert nagle przejrzy na oczy i uzna, że ziemia nie jest płaska lecz okrągła to mamy problem:)"

Święte słowa, dlatego eliminuję eksperta dziedzinowego jako źródło wiedzy, służy mi tylko do testowania projektu, wiedzę czerpię z dokumentów i własnych obserwacji (jako lekarz robię zdjęcie roentgena a nie mega wywiad, ten raczej uzupełnia braki zdjęcia), badań focusowych jeśli potrzebne... mimo tego, że to brzmi irracjonalnnie, sprawdza się doskonale, wymaga jednak bardzo rygorystycznego sformalizowanego modelowania procesów. Ludzie (przyszły user) mają tendencje do ubijania własnych interesów podczas wdrożeń (kumulowanie uprawnień, zawłaszczanie udziału w procesie, "nieusuwalność z procesu"....) to powoduje, ze połączone user story i przypadki użycia uzyskane w wywiadach stanowią nie raz bełkot nie do przejścia...

Michał Huniewicz pisze...

Czyli DAO z 150 metodami do czytania danych zastepuje Finder, bedacy niejako poza reszta aplikacji?

Sławek Sobótka pisze...

@Jarek - tak, sam spotkałem się z przykładami tego typu "strategii" np etaty istniejące tylko po to aby wykonywać pracę rozwiązującą sztucznie wykreowane problemy - co było widać jak na dłoni na diagramach procesów.

Ale czy analityk systemowy, architekt, projektant czy programista jest od tego aby weryfikować sposób pracy organizacji? Organizacja powinna mieć od tego analityka biznesowego, ew zaangażowany emocjonalnie, kompetentny i uczciwy management;P

Programista, który dostaje UC/US do implementacji nie rozstrzyga ich sensowności na poziomie biznesowym.


@Michał
Tak, można tak powiedzieć.
Taki Finder to początek historii. Bo są jeszcze klasy, które on zwraca ze swych metod. Zwykle klasy domenowe są nieodpowiednie. Przykładowo wyświetlając listę dokumentów interesuje mnie tytuł, autor, status, ilość pozycji.
Czyli dane przekrojowe z wielu tabel, ale tylko niewielka ilość kolumn. Zatem lista Agregatów jest nieodpowiednią strukturą danych - lepiej stworzyć sobie szyte na miarę Data Transfer Objects.

W Hibernate możesz sobie napisać na szybko:
SELECT NEW DocumentDto(d.id, d.title, d.author.firstname) FROM Document d.

czyli niejako w zapytaniu "odpalić" konstruktor naszego DTO.

Do tego możesz dodać osobne źródło danych dla Finderów - skonfigurowane na poziomie dostępu do bazy do działania w trybie tylko od odczytu - będzie działać szybciej.

Nie wiem jakiej klasy soft tworzysz, ale w aplikacji, która działa pod dużym obciążeniem idziesz dalej:
Odczyty DTO możesz puszczać na osobnym modelu bazodanowym: materializowane widoki, osobne tabele (wręcz bazy na innych maszynach), które są uaktualniane zdarzeniami biznesowymi. Ale to już osobna historia... architektura CqRS

Michał Huniewicz pisze...

Dzieki za odpowiedz. :)

Jak sie ma immutability do DDD? Encje pewnie nie, Value Objects pewnie tak, a DTO? Tez na miare?

Sławek Sobótka pisze...

Encje zwykle są zagregowane w Agregatach a Agregaty to podstawowe jednostki pracy i w systemie. Agregat jest "granicą" gdzie zachodzą zmiany. Tak więc zmienność encji jest naturalna. Technicznie Encje DDD to encja w JPA.

Natomiast VO powinny być immutable - jest ku temu ważny powód. VO są używane do przekazywania danych pomiędzy Agregatami, Serivisami i innymy Building Blockami. Tak więc jeżeli będą immutable to unikniemy efektów ubocznych, czyli życie staje się prostsze.

Co do DTO to jeżeli używamy go jedynie to prezentacji, to sprawa jest prosta - nie ma potrzeby aby były zmienne.

Pytanie jednak co wówczas gdy DTOsa wyświetlam z jednoczesną możliwością edycji na jakimś formularzu.

Od razu powiem, że jeżeli jest to zwykła operacja CRUD to zaprzęganie do niej DDD jest po prostu "nakładaniem gaci przez głowę". Dla zwykłego Cruda oczywiście najbardziej produktywne będzie operowania na encjach JPA w formularzach.

I tutaj dochodzimy do kolejnej techniki DDD: destylacji domen. DDD używasz w Core Domain, tam gdzie masz złożoną logikę oraz model. Natomiast proste Crudy to zwykle domena Supporting, gdzie nie stosujemy technik DDD.

Tak więc DDD jasno "mówi", kiedy nie należy go stosować:)

ToJaJarek pisze...

"Ale czy analityk systemowy, architekt, projektant czy programista jest od tego aby weryfikować sposób pracy organizacji? Organizacja powinna mieć od tego analityka biznesowego"

Powinna mieć, i po to on jest by dał jako efekt swojej pracy model dziedziny (DDD :)) a nie proze, user sotry itp. zaś architekt, czy programista powinien to z pokorą uznać, skoro jak sam zauważasz, userzy robią programistów w bambuko bo ci nie mają kompetencji by to wychwycić...

Sławek Sobótka pisze...

Kompetencji nie mają, bo w sumie mieć nie powinni - to nie jest ich branża.

Co najwyżej czasem mogą mieć jakiś rodzaj intuicji wynikający ze zdolności do logicznego rozumowania (zwykle większej niż średnia w populacji).

Ale nie chodzi o kompetencje czy logikę, lecz o zakres "uprawnień" i wpływów.

ToJaJarek pisze...

osobiście nie wdawał bym się w dyskusje o zdolnościach, bo relacja kto komu płaci może być zaskakująca ;), ale podział kompetencji ok, zaś "zakres wpływów i uprawnień" pachnie polityką...a tego w projektach nie lubię ;)

Michał Huniewicz pisze...

Dzieki za odpowiedzi!