Domain-Driven Design refaktoringi

Do tej pory pisałem o konieczności stworzenie modelu, który odwzierciedla domenę oraz zaprezentowałem elementy architektury modelu według DDD. Oprogramowanie bez poprawnie zdefiniowanego modelu szybko staje się nieprawdziwe w kontekscie  problemów biznesowych, które probuje rozwiązać. Dlatego wszystkie zmiany w modelu wymagają zmian w kodzie. Kod musi byc regularne przegladany i weryfikowany pod katem zgodnosci z modelem domeny.

Refaktoring, czyli zmiana struktury kodu bez zmiany jego funkcjonalnosci, może wynikać z dwoch powodów:

  1. zmiana modelu domeny, doszczegolowienie, wprowadzenie nowych  koncepcji,
  2. zmniejszenie złożoności przypadkowej, optymalizacja, refaktoring do wzorców.

Z czasem znajomość domeny biznesu będzie rosła, model będzie ewoluował. Musi za tym nadarzyć kod, który powinien być implementacja modelu. Wymagać to będzie ciągłych refaktoringów. Każdy nowy koncept bedzie musiał być odzwierciedlony w implementacji. Zdarzy się, że wiele małych zmian nie zmieni w znaczący sposób architektury, ale może zdarzyć się jedna, która odwróci go o 180 stopni. Model nie powstaje w ciągu jednej nocy w głowie analityka, jest to proces iteracyjny, gdzie w każdej iteracji zespół przedefiniowuej go, upraszcza. Zmianie  ulega sposób myślenia o domenie. Poznajemy ukryte pojęcia i czynimy je jawnymi. To bardzo ważne, by odkryc i zamodelować wszystkie istotne z punktu widzenia domeny koncepty.

Rada na koniec. Refaktoring powinien być przeprowadzany w małych krokach i z testami pilnującymi wprowadzania błędów regresyjnych.

Domain-Driven Design Repositories

Jendym z ostatnich „building blocks” dostarczonych przez metodykę DDD jest repozytorium. Repozytoria to obiekty służace do utrwalania stanu encji, aggregatów i obiektów wartości. Są interfejsami, nie konkretnymi implementacjami, gdyz chcemy odseparować elementy infrastrukturalne, takie jak dostep do bazy dancyh od warstwy logiki domenowej. Implementacja interfejsu repozytorium już bardziej związana z konkretną platformą bazodanową bardziej niż z modelem dziedziny. Sposób postępowania z tymi elementami jest stosunkowo prosty. Obiekt zwracany użytkownikowi pochodzi z bazy danych i jest wybierany na podstawie kryteriów przekazanych jako parametry wywołania funkcji. Samo repozytorium ukrywa szczegóły konfiguracyjne potrzebne do uzyskania połączenia z serwerem czy treść zapytań SQL. Z drugiej strony nie musi to być serwer bazy danych. Można użyć innego medium do utrwalania danych:  bazy NoSQL, XML, plik itd. Dzięki posiadaniu osobnych obiektów odpowiedzialnych za utrwalanie i pobieranie, obiekty domeny mogą skupić się całkowicie na rozwiązywaniu problemów biznesowych.

Dla każdego obiektu, który ma być dostępny zewnętrznie potrzebne jest repozytorium, które pozwoli na operacje związane z utrwalaniem – dodawanie i usuwanie obiektów, wyszukiwanie obiektów na podstawie przekazanych kryteriów. Dla agregatów repozytorium powinno zostać stworzone jedynie dla głównego elementu. Do głównych zalet używania tego elementu metodyki Domain-Driven Design należą:

  • umożliwienie klientowi używania prostych mechanizmów uzyskiwania obiektów trwałych i dostarczają sposobu na zarządzanie ich cyklem życia

  • oddzielenie modelu dziedziny od konkretnej technologii utrwalania danych, czy wielu źródeł danych

  • umożliwieniu szybkiej zmiany dostawcy systemu baz danych poprzez enkapsulację całej specyfikacji utrwalania w jednym miejscu

Repozytorium od Fabryki w kontekscie DDD odroznia fakt, ze repozytoria słuzą do utrwalania i pobierania juz utrwalonych obiektów domenowych. Natomiast fabryka słuzy do budowania nowych instancji obiektów domenowych.

Domain-Driven Design Factories

Obiekty modelu domeny mogą być duże i na tyle skomplikowane, że nie da sie ich stworzyc przy pomocy konstruktorów. Być może w domenie za tworzenie obiektów odpowiadają inne obiekty.

Fabryki są właśnie takimi obiektami, odpowiedzialnymi za tworzenie skomplikowanych encji, obiektów wartości lub całych agregatów. Mimo, że nie posiadają żadnej operacji ani stanu, to należy je traktować jako pełnoprawnych członków modelu domeny, na równi z obiektami domenowymi. Używanie fabryk obiektów jest zasadne, ponieważ odpowiedzialność za tworzenie obiektu nie leży w zakresie obowiązków tworzonego obiektu. Poza tym ten artefakt, stwarza możliwość umieszczenia całego kontekstu potrzebnego do inicjalizacji obiektu w jednym miejscu. Jest to szczególnie ważne, gdyż wiele obiektów posiada silne powiązania z innymi zasobami, które muszą być skonfigurowane przed stworzeniem obiektu. Przez to że proces tworzenia obiektu został wydzielony do  oddzielnego obiektu, to można w nim zebrać  i pilnować wszystkie niezmienniki.

Projektując fabryki należy pamiętać o tym, że:

  • Każda operacja musi być atomowa,

  • Fabryka będzie ściśle powiązana z parametrami przekazywanymi do jej metod.

Tworząc fabrykę trzeba być świadomym, że  łamiemy enkapsulację tworzonego obiektu. Natomiast z drugiej strony, zapewniamy, że tworzony obiekt przestrzega zasadę pojedynczej odpowiedzialności („Single Responsibility Principle”).

Są również miejsca w domenie, gdzie wporwadzenie fabryki jest mało zasadne:

  • konstruowanie obiektów domeny nie jest skomplikowane
  • obiekt nie posiada powiązań do inncyh obiektów

Domain-Driven Design Aggregates

Oprócz encji, obiektów wartości i serwisów, Domain-Driven Design dostarcza jeszcze trzy typy wzorców odpowiedzialne za zarządzanie cyklem życia pozostałych obiektów domenowych.

Agregaty są grafami powiązanych ze sobą encji lub obiektów wartości, które traktowane są jak jeden element podczas zarządzania jakimikolwiek zmianami ich stanu. Każdy agregat posiada element główny – zwany również korzeniem w teorii grafów oraz ściśle określone granice. Element główny jest jedynym obiektem spośród wszystkich członków agregatu, do którego referencje mogą posiadać obiekty zewnętrzne. To on kontroluje dostęp do elementów agregatu. Jeżeli wewnątrz istnieją jeszcze jakieś inne encje, to ich identyfikator jest identyfikatorem lokalnym.

Gdy obiektów w domenie przybywa i zaczynają budować skomplikowana sieć powiązań, każde ważne powiązanie musi zostać odwzorowane w kodzie. Jednym ze sposobów ich ograniczenia jest pakietowanie. Kolejnym jest wyróżnienie korzenia drzewa powiązań i zrobieniem go agregatem. Dla przykładu, w aplikacji bankowej mamy wyróżnione encje: klienta, konta osobistego i przelewu połączone wzajemnymi zależnościami. Powstaje agregat, którego korzeniem bedzie encja klient. Jeśli w pewnym momencie klient zrezygnuje z korzystania z usług banku, to usunięcie jego konta będzie oznaczało wywołanie jednej metody na agregacie. Gdyby zrealizować to inaczej, ciężko byłoby zapewnić usunięcie wszystkich danych związanych z klientem i  zagwarantować ich integralność. Wiadomo, że za integralność danych w głównej mierze odpowiada system bazy danych, natomiast model domeny powinien pomagać  rozwiązywać część z tych problemów.

Agregaty świetnie sprawdzają się również do trzymania niezmienników. Niezmienniki to warunki biznesowe, które muszę być sprawdzane zawsze, gdy zmieniają się dane. Ciężko byłoby to zrealizować, jeśli referencje do zmieniających się danych znajdowałyby się w wielu obiektach modelu. Dzięki agregatom jest prościej. Warto pamiętać, że obiekty domeny mogą trzymać referencję tylko do korzenia agregatu i jedynie poprosić go o wykonanie pewnych operacji. Tylko agregat mozę zmieniać swój stan wewnętrzny, co jest bezpieczne, bo może pilnować niezmienników domeny.

Agregat może przekazywać referencje na obiekty wartości z wnętrza agregatu, bo są to obiekty niezmienne. Jeśli obiekty agregatu są zapisywane w bazie, to jedynie korzeń agreagtu powinien być dostępny do pobrania bezpośrednio za pomocą zapytań sql.

Domain-Driven Design Services

W modelu dziedziny moga istnieć pewne operacje, które nie pasują naturalnie do odpowiedzialności żadnego obiektu domenowego. Nie można ich pominąć, bo  domena stanie sie niekompletna. Wtedy takie operacje umieszcza sie klasach zwanych serwisami.

Serwisy są tworzone w momencie, gdy logika biznesowa związana jest z wieloma encjami lub obiektami wartości. Ma to miejsce zazwyczaj przy wykonywaniu skomplikowanych obliczeń wymagających informacji znajdujących się w kilku oddzielnych elementach. Jeśli spróbujemy umieścić taką operację w obiekcie, rozmyjemy jego odpowiedzialność doprowadzając do złamania zasady Single Responsibilty Principle. Serwis nie skupia sią na operacji wykonywanej na obiekcie, ale raczej na funkcji operującej na obiektach.

Dla przykłądu, gdy chcemy zrobić przelew pieniedzy z jednego konta na inne. Ciężko tą operację przyporządkować do któregoś z obiektów, bo do którego? Wtedy trzeba stworzyc operację w klasie serwisu, przyjmującą dwa parametry będące kontami osobistymi (źródłowe i docelowe).

Według Erica Evansa, twórcy DDD dobry serwis powinien:

  • zawierać operacje należące do domeny, które nie są naturalną częścią żadnej z encji lub obiektów wartości. Serwisy można traktować jako zbiory metod, które są istotne ze względu na projektowaną domenę, ale nie mogą być traktowane jako odpowiedzialność tylko jednego obiektu.

  • być bezstanowy. Kolejne wywołania operacji są niezależne
    od wcześniejszych i stan obiektu nie jest zapamiętywany pomiędzy nimi.

Najczęściej serwis udostępniany jest za pomocą interfejsu, by ułatwić komunikacje z nim, jak i ze względu na wszelkie korzyści jakie niesie ze sobą paradygmat programowania obiektowego.

Serwisy można podzielić na dwa rodzaje.

  • pierwszy rodzaj został scharakteryzowany powyżej i nosi nazwę serwisu domenowego.
  • serwis aplikacyjny. Używany jest do uzewnętrzniania operacji dostępnych w warstwie domeny obiektowej i stanowią jedynie delegaty wywołań metod z niższych warstw. Może być dodatkowo wzbogacony o takie rzeczy jak obsługa wyjątków, transakcje czy zliczanie ilości wywołań konkretnej metody.

Podjęcie decyzji o tym, do której warstwy należy pewna operacja czesto nie jest zadaniem prostym, jako że obie operują powyżej encji i obiektów wartości. Jeżeli operacja używa wyłącznie obiektów domenowych i jest ściśle powiązana z domeną, nie przemyca żadnych konceptów aplikacyjnych to powinna znaleźć się w warstwie domeny.

Należy pamiętać, że serwis nie powinien zastępować operacji wykonywanych na konkretnym obiekcie. Nasza domena nie powinna się składać z samych serwisów, ale te które powstają powinny możliwie małe.

Domain-Driven Design Value Objects

W poprzednim poście opisywałem encje i ich rolę w projektowaniu domeny rozwiązania. Ale co jeśli nie zależy nam na rozróżnianiu obiektów posiadajacych te same właściwości? Koszt tworzenia identyfikatora w obiekcie i zapewniania jego unikalności staje się niepotrzebnym narzutem.

Obiekty  wartości w odróżnieniu do encji nie posiada tożsamości. Używane są do modelowania elementów dziedziny, które są istotne dla projektu ze względu na wartości jakie przechowują. Dla przykładu, adres może zostać zamodelowany jako obiekt wartości, gdyż nie interesuje nas jego unikalność a jedynie wartość jego atrybutów. Właściciela sklepu internetowego lub osobę odpowiedzialną za rozsyłanie paczek, nie interesuję fakt, że z tego samego adresu korzysta kilku klientów. To, na co zwraca uwagę, to wartości występujące w polach: miasto, kod pocztowy czy ulica. Głównym celem zastosowania obiektów wartości jest uproszczenie implementacji. Nie posiadając toższamości obiekty wartości mogą być prosto tworzone i porzucane. Ważne jest by były niezmienne „immutable”, tworzone za pomoca konstruktora i nigdy nie modyfikowane. Jeśli potrzebujesz nowej wartości w obiekcie wartości, wystarczy stworzyc nowy.

Dzięki temu, że obiekty wartości są niezmienne i nie posiadają tożsamości mogą być współdzielone. Współdzielenie obiektów może wyrządzić wiele szkody, jeśli chodz i o integralność danych w instancji obiektu. Problem jest bardzo wyraźny w stosunku do encji, nie występuje jednak dla obiektów wartośći.

Mogą one posiadać referencje do innych obiektów wartości, ale również encji.

Domain-Driven Design Entities

Po zaprojektowaniu modelu mentalnego domeny rozwiązania problemu, przychodzi czas na przeniesienie go do kodu. DDD dostarcza tkz. „building blocks”, czyli standardowe wzorce do stworzenia modelu w kodzie źródłowym.

ddd-buildingblocks

Podstawowym rodzajem elementu, od którego należy zacząć projektowanie modelu dziedziny problemowej są encje. Encja to obiekt, który nie jest charakteryzowany przez swoje atrybuty, lecz przez sam fakt istnienia. W książce wydawnictwa InfoQ „Domain-Driven Design Quickly”, autor wyjaśnia ją na podstawie człowieka. Każda osoba posiada zbiór różnego rodzaju cech, które odróżniają ją od innych, ale które zmieniają się wraz z czasem. Nie istnieje ani jedna właściwość, która opisywałaby człowieka przez całe jego życie, a jednak jest to wciąż ta sama osoba. W metodyce Domain-Driven Design encją jest wszystko to, co posiada swoją tożsamość
i jest rozróżnialne spośród innych obiektów, nawet w przypadku, gdy kilka z nich posiada identyczne wartości atrybutów. Może być to osoba, samochód, los na loterii czy transakcja bankowa. Jednak należy zwrócić uwagę, na fakt, że o tym, czy wybrany obiekt ze świata rzeczywistego zostanie zamodelowany jako encja, decyduje kontekst użycia tego obiektu i … projektant modelu dziedziny. W jednym przypadku los na loterii jest obiektem encji, gdyż każdy kupon posiada fizyczny numer zakładu, co więcej ten numer jest unikalny pośród wszystkich dostępnych losów. W tym przypadku, przy zakupie kuponu jedyną rzeczą, która go wyróżnia spośród pozostałych jest właśnie ta tożsamość wyrażona kodem. Z drugiej strony, aplikacja finansowo-księgowa, nie musi posiadać szczegółowych informacji o numerach losów. Wystarczy informacja o ilości i cenie sprzedanych. W tym przypadku modelowany obiekt nie jest encją. Należy pamiętać, iż rzeczywisty obiekt nie musi posiadać fizycznego identyfikatora, żeby zostać sklasyfikowana jako encja.

Naturalną rzeczą związaną z tym procesem jest wyodrębnianie atrybutów i operacji dla obiektu. Bardzo istotne jest zwrócenie uwagi na ciągłość i niezmienność, tak aby zachowanie obiektu było jasne i przewidywalne przez cały okres jego życia. Sprowadza się to do odnalezienia obiektu i wyodrębnienia tylko tych właściwości, które wskazują na jego tożsamość i będą używane przy jego odnajdywaniu lub porównywaniu z innymi. Ponadto powinien posiadać tylko operacje, które to umożliwiają.

Każdy wyodrębniony obiekt modelowanej dziedziny jako encja powinien dostarczać sposobu na określenie swojej tożsamości. Istnieje wiele sposobów na radzenie sobie z tym zagadnieniem. Może to być kombinacja wartości atrybutów, która w specyficznych warunkach może zapewnić unikalność obiektu w ramach systemu informatycznego. Można spróbować oznaczyć klasę specjalnym identyfikatorem składającym się z ciągu liczb i cyfr, wskazującego bezpośrednio na obiekty danej klasy, na przykład w systemie do obsługi przesyłek kurierskich, kazda przesyłka posiada unikalny kod, wygenerowany niezależnie przez system.

Domain-Driven Design Architekura warstwowa

Architektura warstwowa w DDD zakłada dołożenie jeszcze jednej, dodatkowej warstwy na model domeny.ddd-layersWarto zauważyć na tym diagramie, ze każda z wartsw komunikuje się tylko z wartwą poniżej. Poza tym warstwa domeny jest jawnie wydzielona i odseparowana od pozostałych. Komunikuje się z nią tylko warstwa UI i aplikacyjna, a ona sam może komunikować się tylko z wartwą infrastrukturalną. Co to oznacza? Warstwa domeny nie wie nic o środowisku w jakim uruchomiona jest aplikacja, nie wie nic o technikaliach takich jak transakcje, sessje, dostęp do bazy danych. Obiekty w tej warstwie nie realizują wyświetlania, zapisywania do bazy danych. Koncetrują się wyłącznie na domenie problemu. Z drugiej strony, jeśli kod domenowy jest porozrzucany po pozostalych warstwach, zrozumienie modelu domeny czy wprowadzanie do niego zmian jest praktycznie niemożliwe.

Przykładowy przypadek użycia w tej architekturze mógłby wyglądać mniej wiecej tak:

  1. użytkownik chce wykonać przelew ze swojego konta na konto znajomego i wysyła takie żądanie na serwer aplikacyjny
  2. warstwa aplikacyjna zakłada transakcje, loguje dane żądania oraz informacje o  aktualnie zalogowanym użytkowniku.
  3. Wczytują potrzebne obiekty domenowe, wykonuje na nich potrzebne operacje (np. sprawdzenie salda konta, weryfikacja numeru konta znajomego itd.) .
  4. Po zakonczeniu operacji na obiektach domenowych, warstwa aplikacji utrwala odpowiednie komponenty domenowe.

Domain-Driven Design – budowanie wiedzy o domenie

  • Dobre oprogramowanie to zrozumienie domeny

Głównym celem powstawania systemów informatycznych jest automatyzacja lub usprawnienie pewnych procesów biznesowych. Żeby to osiągnąć oprogramowanie musi dokladnie wpasować się w domenę, dla której zostało zaprojektowane. W przeciwnym wypadku wprowadzi tylko zamięszanie, liczne błędy i chaos. Aby tego uniknąć, oprogramowanie powinno odzwierciedlać domenę biznesu, powinno być modelem domeny.

Dlatego pierwszym etapem prac nad projektem, jest cykl spotkań z ekspertami domeny. Ekspert domeny jest osobą, którą doskonale zna daną domenę biznesową, zdobył w niej praktyczne doświadczenie i umie przekazać swoją wiedzę innym. Zdaża się, że zamawiający system nie koniecznie jest w niej ekspertem. Jeśli cieżko o eksperta domenowego w tej organizacji, trzeba pomyśleć o zatrudnieniu tak owego z zewnątrz.

Domain-Driven Design dostarcza pewnych wskazówek odnośnie sposobu prowadzenia takich spotkań. Po pierwsze, oprocz ekspertów domenowych i analityków, powinien w nich uczestniczyć zespoł deweloperski, tak by mógł nauczyć się jak najwięcej o biznesie, dla którego system będzie tworzył. Zespól poznaje nowe pojęcia, pewne specyficzne konstrukcje, zaczyna uczyć się języka biznesu. Poprzez zadawanie pytań i analizowanie otrzymanych odpowiedzi zostaje wypracowany pewień szkic domeny podstawowej. To bardzo ważny etap projektowania systemu. Kierunek komunikacji nie jest jednostronny, od eksperta do deweloperów. Ekspert zna domenę, ale używa jej na codzien tylko w jeden specyficzny sposób. Natomiast zdolności analityczne członków zespołu pozwalają rzucić nowe, świeże spojrzenie na biznes. Zespoł jest w stanie zweryfikować koncepty pod względem implementacyjnym. W wyniku tych niezliczonych godzin poswięconych na spotkania powinien powstać model, który będzie rozwiązywał rzeczywiste problemy biznesowe.

  • Dobre oprogramowanie to jeden wszechobecny język

W momencie, gdy dwa zupełnie rozbieżne światy spotykają się, by rozwiązywyc problemy, zawsze powstają problemy komunikacyjne. Eksperci domenowi bedą używać specyficznego, bardzo specjalizowanego słownictwa, by wyrazić biznes.  Natomiast z drugiej strony, osoby techniczne bedą używały żargonu technicznego. Projekt stanie przed dużym wyzwaniem, jezeli nie uda się wprowadzić wspólnego jeżyka, zrozumiałego dla obu stron. Komunikacja bedzie ograniczona koniecznością ciągłego tłumaczenie specjalistycznych terminów i pojęć. Który język powinien zostać użyty w modelu? Główna zasada Domain-Driven Design mówi, model powinien zostać opisany za pomocą języka specyficznego dla biznesu. Jako, że chcemy by nasze oprogramowanie bylo jak najblizej modelu jak to mozliwe, to i wspolny jezyk powinien byc przeniknięty biznesem. Kazdy z czlonkow zespolu powininen dbac o to, by uzywać języka modelu, zwnego tutaj Ubiquitous Language. To nie jest tak, ze wspolny jezyk powstaje z dnia na dzien. Wymaga to duzo wspołpracy pomiedzy zespołem deweloperskim a ekspertami domenowymi. Celem powinno byc stworzenie modelu i jezyka scisle zwiazanego z domena biznesowa. Jesli model i jezyk jest w pelni zrozumialy przez ekspertów domenowych i poprawny z punktu widzenia architektury systemu i implementacji, to jest to dobry model.

  • Dobre oprogramowanie to model w kodzie źródłowym

Model moze zostac wyrazony za pomocą diagramu, kodu źródłowego czy opisu w języku naturlanym. Co wybrac? Jak wyraźić esencję problemu, tak by każda osoba zaangażowana później w projekt była w stanie ją zrozumieć? Jak zapewnić, żeby model nie rozsynchronizował się z biznesem na żadnym etapie tworzenia oprogramowania? Najlepiej by model został odrazu wyrażony w kodzie źródłowym, ponieważ to przy pomocy kodu robimy różnicę dla klienta. Kod powinien byc tak skonstruowany pakiety, klasy, metody, nazwy zmiennych by nie tylko komunikował nam co robi ale i dlaczego to robi. Powinien za to ukrywac przed nami w jaki sposób to robi. Należy pamietać, ze kod który działa, nie koniecznie dobrze komunikuje swoje zamiary. Z tego powodu, stworzenie dobrego modelu w kodzie jest zadaniem bardzo, bardzo trudnym.

Czy nie mozna uzyc do tego notacji UML? UML nadaje sie do wyrazania klas, atrybutów i relacji pomiedzy klasami, ale slabo sprawdza sie w modelowaniu zachowania klas i warunków biznesowych. Po drugie, nie tłumaczy wyborów architektonicznych. Poza tym projekt w UML bardzo szybko się starzeje i dezaktualizuje. Z tego samego powodu, wynikiem „crunching knowledge”, czyli kruszenia wiedzy pomiedzy ekspertem domenowym a deweloperami, nie powinny byc zadne dokumenty, opisy i specyfikacji. Powinien pozostać działajacy kod.

  • Dobre oprogramowanie to model w pakietach

W dużych i bardziej złożonych aplikacjach model domeny rozrasta się do takich rozmiarów, że nie jest zrozumiały jako całość. Pojawia się potrzeba wprowadzenia w domenie kolejnej warstwy abstrakcji, która pomoże łatwiej zrozumieć koncept domeny. Patrząc na moduły jakie zawiera model, na powiązania pomiędzy nimi,  łatwiej pojąć domenę jako całość. Dopiero jeśli potrzebujemy poznać szczegóły konkretnej części domeny zagłębiamy się wewnątrz modułu.

Drugim argumentem za używaniem modułów jest posiadanie kodu, który jest bardziej spójny i mniej powiązany pomiędzy sobą. Moduły powinny zawierać kod który jest ze sobą powiązany funkcjonlanie oraz dostarczać interfejsu, w którym zamknięte są wszystkie powiązania z innymi modułami. Nazwa modułu powinna opisywac historię, którą realizuje moduł i powinna wywodzić sie ze wspólnego języka.

Domain-Driven Design – pierwsze spojrzenie

Projektowanie systemów używające Domain-Driven Design jest zbiorem wzorców architektonicznych i reguł pomocnych analitykom i projektantom w tworzeniu obiektowych systemów informatycznych. Poprawnie zastosowana pozwala na enkapsulację skomplikowanej logiki biznesowej w obiektach domeny, co zmniejsza lukę pomiędzy przestrzenią problemową a implementacją systemu oraz lepiej odzwierciedla rzeczywistość. Metodyka została zbudowana na dwóch głównych założeniach:

  • skupienie się na dziedzinie problemu i logice jej towarzyszącej,
  • odzwierciedlenie skomplikowanej domeny problemowej za pomocą modeli

Według Erica Evansa, jednego z prekursorów metodyk Agile oraz twórcy Domain-Driven Design, największe zagrożenie przy realizacji projektu związane jest z poznaniem dziedziny problemowej, czyli przestrzeni użytkowania programu. Dlatego metodyka przez niego stworzona kładzie silny nacisk na poprawne zaprojektowane dziedziny, między innymi ze względu na koszt wprowadzania późniejszych poprawek.

Wspólny język

W swojej książce „Domain-Driven Design: Tackling Complexity in the Heart of Software” Evans opisuje szereg koncepcji, które mają pomoc w realizacji tego celu. Należy do nich przede wszystkim używanie wspólnej terminologii i języka (ang. Ubiquitous Language), zrozumiałego dla ekspertów z dziedziny domenowej i używanej w całym projekcie przez analityków, architektów oraz programistów. Dzięki temu uzyskuję się bardzo obiektowy model danych zrozumiały dla wszystkich. W tej metodyce wspólna nomenklatura wyraża model zarówno w rozmowie, projekcie jak i implementacji. Umożliwia modelowanie systemów przez specjalistów znających specyfikę problemu, ale już niekoniecznie znających architekturę systemów. Z tego względu wspólnym językiem musi być język biznesowy. Ważna rzeczą, na którą należy zwrócić uwagę przy używaniu ubiquitous language, jest sposób prowadzenia rozmów z klientem. To eksperci domeny prowadzą rozmowę używając specjalistycznej terminologii, a analitycy i architekci systemów informatycznych starają się dostosować, tak aby po krótkim okresie czasu swobodnie jej używać.

Kontekst

Stworzenie i używanie wspólnego języka okazuje się nie być prostym zadaniem,
jeśli chodzi o skomplikowane i duże projekty. W tym przypadku należy wprowadzić ograniczone konteksty (ang. Bounded Contexts). Są to części aplikacji, z których każda posiada dokładnie zaznaczone granice i swój model. Każda z nich jest odpowiedzialna za coś innego i dzięki takiemu podziałowi łatwiej stwierdzić, gdzie powinna się znajdować poszczególna logika biznesowa. Poza tym może się zdarzyć tak, że w różnych kontekstach będą używane te same terminy, ale ze względu na miejsce, w którym są użyte, będą miały różne znaczenie. Dzieje się tak dlatego, że każdy pojedynczy kontekst może posiadać swój język niezależny od pozostałych. Taki podział niesie ze sobą następujące zalety:

  • Modułowość (ang. Modularity),
  • Rozdzielenie pojęć (ang. Separation of Concerns),
  • Luźne powiązania pomiędzy modułami (ang. Loose Coupling).

Natomiast do komunikacja pomiędzy kontekstami używa się ogólnie dostępnego obiektu zwanego mapą kontekstu (ang. ContextMap).

Abstrakcje

Kolejnym paradygmatem wyodrębnionym przez Evansa, jest konieczność dokonania abstrakcji modelu dziedziny, czyli swego rodzaju uproszczenia. Związane jest to z prostym przykładem, w którym użytkownik końcowy pracuje wyłącznie z pewną częścią modelowanej dziedziny problemowej. Dla przykładu, system do zarządzania rezerwacjami linii żeglugowych nie powinien wiedzieć nic o naprawach statków poza faktem, czy konkretny statek jest gotowy do rejsu czy nie. Taki rodzaj abstrakcji stosowany jest w celu ułatwienia realizacji fazy projektowania oraz skupienia się w większym stopniu na niezbędnych funkcjach systemu.

Ignorowanie utrwalania

W metodyce Domain-Driven Design istnieje pojecie określane w skrócie jako PI
(ang. Persistence Ignorance), czyli ignorowanie aspektu utrwalania. Zasada ta mówi,
że powinnyśmy unikać oznaczania kodu źródłowego jakimikolwiek informacjami o sposobie przechowywania obiektów modelu dziedziny. Ma to związek z chęcią posiadania luźnych powiązań pomiędzy implementacją modelu a sprawami technicznymi, jak na przykład rodzaj bazy danych.

Brak technicznego bełkotu

Ostatnim ważnym zagadnieniem, na które warto zwrócić uwagę jest fakt, że podczas rozmów z klientem nie powinno się używać zagadnień typowo informatycznych z dwóch względów. Po pierwsze, zamawiający system informatyczny często nie zna nomenklatury programistycznej, a z drugiej strony, świadczy to o tym, że analityk myśli już o konkretnym sposobie implementacji. Na tym poziome prowadzenia projektu nie można tworzyć specyfikacji wymagań użytkownika pod katem konkretnych technologii.

Podsumowanie

Z rozmowy przeprowadzonej z Evans’em przez redaktora infoq.com można wywnioskować, że Domain-Driven Design ma tak duże znaczenie dzisiaj, ze względu na złożoność tworzonych systemów i sposobu w jaki ta metodyka rozwiązuje ten problem. Związane jest z długoletnim procesem wdrażania rozwiązań informatycznych w coraz to nowe gałęzie przemysłu i biznesu. Poza tym tworzenie implementacji modelu dziedziny może zostać przeprowadzone bez użycia żadnych specjalistycznych narzędzi i bibliotek. Dzięki temu może zostać wykorzystana bez względu na użyty do implementacji obiektowy język programowania.