Niedawno natknąłem się na StackOverflow interesujące pytanie dotyczące Domain-Driven Design. Chciałbym się z Wami podzielić moimi przemyśleniami.

Pytanie dotyczyło zaprojektowania logiki biznesowej dla domeny składającej się z trzech obiektów: Książki (Book), Rozdziału (Chapter) oraz Strony (Page):

Diagram klas dla domeny

Problem polega na tym, który element, z przedstawionych trzech, powinien być korzeniem agregatu? Na wszelki wypadek, dla nowych czytelników wyjaśnię:

Agregat w Domain-Driven Design to podzbiór elementów modelu domeny, który stanowi spójną całość w ramach której spełniane są warunki integralności danych. Agregat posiada dokładnie jeden element będący jego korzeniem. Elementy spoza agregatu mogą posiadać referencję tylko do jego korzenia (referencję do wewnętrznych elementów innego agregatu są zabronione).

Wracając do tematu… Odpowiedź jak zwykle brzmi: to zależy. A od czego zależy? Również jak zwykle — od kontekstu. Kontekst modelu określany jest przez problem, do rozwiązania którego model jest tworzony. W wypadku domeny książek możemy wyobrazić sobie wiele problemów, jednak ograniczę się do dwóch przypadków.

Problem związany z książkami

Jeśli operacje wykonywane na modelu są zorientowane na książki, korzeniem agregatu powinien być obiekt książki. Jest to najbardziej oczywisty — kiedy korzeniem agregatu jest obiekt, który jest nadrzędny w stosunku do innych na diagramie domeny (nie mylić z diagramem modelu domeny).

Model domeny z książką, jako korzeniem

Taki model świetnie sprawdzałby się w przypadku, kiedy np. użytkownicy wybierają z listy książki i dokonują w nich jakiegoś rodzaju modyfikacji — wtedy założenie, że nad spójnością całości czuwa obiekt Book jest bardzo rozsądne.

Problem związany z rozdziałami

Ten przypadek nie jest już taki oczywisty. Mimo, iż diagram domeny pokazuje jasno, że najbardziej zewnętrznym obiektem jest książka, przypadki użycia sugerują, że problemy stawiane przed naszym modelem dotyczą poszczególnych rozdziałów, podczas gdy książki stanowią jedynie tło — są obiektami referencyjnymi.

W takim wypadku korzeniem agregatu powinien być obiekt reprezentujący rozdział. Co jednak zrobić z książką? Nie możemy uczynić jej częścią agregatu rozdziału, ponieważ wiele rozdziałów miałoby referencję do jednego obiektu książki, co jest sprzeczne z ideą agregatów (agregaty nie mogą współdzielić danych). Może więc książka jako osobny agregat? Ma to jakiś sens, jednak przez skórę czuć, że obiekt książki jest nieco “inny” niż pozostałe…

Z pomocą przychodzi książka Domain-Driven Design Erica Evansa, a dokładniej rozdział dotyczący struktur wielkoskalowych. Zastosujmy warstwy!

Diagram modelu domeny z warstwamiTak, model domeny także (podobnie jak architektury, cebule oraz ogry) może posiadać warstwy. Nie dajmy się jednak ponieść analogiom z (czysto technicznymi) warstwami architektury. Warstwy modelu mają charakter biznesowy i wynikają z charakteru rozwiązywanego problemu.

Warstwa operacyjna (operations) zawiera te elementy modelu, które są związane z codzienną aktywnością biznesu. W naszym wypadku są to obiekty reprezentujące rozdziały. Warstwa potencjału (potential, capabilities) zawiera zaś obiekty, które są umożliwiają funkcjonowanie biznesu, jednak nie są elementami jego codziennej aktywności. Odnosząc to do przykładu, istnienie książki umożliwia przetwarzanie rozdziałów nadając mu niezbędny kontekst, punkt odniesienia.

I tak to kolejny raz problem z pozoru techniczny (wybór korzenia agregatu) okazał się mieć źródło w nieodkrytym problemie biznesowym (jaki jest kontekst modelu?). Dopiero znalezienie rozwiązania tego drugiego problemu pozwoliło właściwie rozwiązać ten pierwszy.

VN:F [1.8.7_1070]
Rating: 5.0/5 (3 votes cast)
Przypadek książkowy5.053