Trzy litery DDD w świecie IT oznaczają podejście do projektowania systemów, które zaczyna się od biznesu, a nie od technologii. Metoda ta, znana jako Domain Driven Design, pomaga ogarnąć złożone aplikacje dzięki wspólnemu modelowi tworzonymu razem z ekspertami biznesowymi. Jeśli zastanawiasz się, co dokładnie oznacza ten skrót i kiedy warto z niego korzystać, jesteś we właściwym miejscu. Zapraszam Cię do krótkiego przewodnika po najważniejszych założeniach i elementach DDD.
DDD co to jest?
W kontekście inżynierii oprogramowania skrót DDD oznacza Domain Driven Design – podejście do projektowania aplikacji opisane w 2003 roku przez Erica Evansa w książce „Domain-Driven Design: Tackling Complexity in the Heart of Software”. Celem tej koncepcji jest radzenie sobie ze złożonością systemów przez skoncentrowanie się na domenie biznesowej, czyli realnym obszarze działania firmy, a nie na szczegółach technicznych.
W praktyce oznacza to, że programiści i eksperci biznesowi tworzą wspólny model domeny, który staje się punktem odniesienia dla kodu. Logika biznesowa, nazwy klas, moduły i granice systemu wynikają z tego modelu. Dzięki temu aplikacja odzwierciedla rzeczywistość biznesową, a zmiany wymagań można przełożyć na zmiany w kodzie bez chaosu.
Istota Domain Driven Design to jeden spójny model domeny biznesowej, opisany tym samym językiem przez programistów i ekspertów biznesowych.
Jakie są podstawowe założenia Domain Driven Design?
Fundamentem podejścia domenowego jest założenie, że prawdziwe źródło złożoności leży w biznesie, a nie w technologii. Zamiast zaczynać od frameworka czy bazy danych, zespół zaczyna od analizy domeny biznesowej, jej pojęć, reguł i wyjątków.
Domena i model domeny
Domena to obszar działalności, w którym ma działać system – na przykład sprzedaż online, księgowość, logistyka czy obsługa polis ubezpieczeniowych. W DDD nie chodzi o ogólne opisy, ale o bardzo konkretne procesy, zasady, ograniczenia i cele, z którymi pracuje organizacja na co dzień.
Model domeny to abstrakcyjna reprezentacja tej rzeczywistości biznesowej. Zawiera pojęcia, relacje i reguły, które są istotne dla danego systemu. Model nie jest diagramem do szuflady – powinien żyć w kodzie, w nazwach klas, metod, modułów. Dlatego style projektowania obiektowego świetnie współgrają z DDD, bo pozwalają przełożyć model na konkretne struktury jak encje czy obiekty wartości.
Subdomeny i współpraca z ekspertami?
W większych organizacjach jedna domena jest podzielona na kilka subdomen, które można rozwijać i utrzymywać niezależnie. Przykład to system e‑commerce, gdzie osobno myślimy o katalogu produktów, koszyku, płatnościach czy logistyce. Każdy z tych obszarów ma inne reguły i inne priorytety biznesowe.
Żeby uchwycić te różnice, zespół techniczny pracuje wspólnie z ekspertami domenowymi – osobami, które na co dzień żyją danym fragmentem biznesu. Wiele zespołów stosuje warsztaty typu Event Storming, podczas których na osi czasu układa się zdarzenia biznesowe, decyzje i dane. Z takiego spotkania powstaje szkic procesu, który potem przekłada się na bardziej szczegółowy model domeny.
W trakcie takiej pracy często wyróżnia się trzy typy subdomen:
- obszar kluczowy dla firmy, gdzie powstaje przewaga konkurencyjna,
- obszary wspierające, potrzebne, ale mniej unikalne,
- obszary ogólne, które można zrealizować standardowymi rozwiązaniami.
Jakie elementy modelu domeny wyróżnia się w DDD?
Model domenowy nie składa się wyłącznie z ogólnych pojęć. W Domain Driven Design używa się zestawu taktycznych wzorców: Entity, Value Object, Aggregate, Repository oraz różnego rodzaju serwisów i fabryk. Dzięki nim kod staje się bardziej spójny z modelem biznesowym.
Entity
Encja to obiekt, który ma trwałą tożsamość. Liczy się to, że „to jest ten sam klient” albo „to jest to samo zamówienie”, nawet jeśli jego atrybuty ulegają zmianom. Identyfikator może być techniczny (np. GUID) albo biznesowy (numer umowy), ważne jednak, by jednoznacznie wskazywał konkretną instancję.
W dobrze zaprojektowanej encji logika biznesowa jest skupiona wokół jej odpowiedzialności. Obiekt nie jest tylko „workiem na dane” – zawiera metody, które egzekwują reguły domenowe, na przykład weryfikują limit kredytowy czy zmieniają status zamówienia wyłącznie w dozwolonych sytuacjach.
Value Object
Value Object reprezentuje pojęcia, które definiuje ich wartość, a nie tożsamość – na przykład kwota pieniędzy, adres, przedział czasu. Dwa obiekty wartości o tych samych atrybutach można traktować jak wymienne. Dlatego zazwyczaj są niezmienne: zamiast zmieniać istniejący obiekt, tworzy się nowy z innymi wartościami pól.
Umieszczanie istotnej logiki w obiektach wartości bardzo porządkuje kod. Przykład to walidacja numeru NIP albo operacje na kwotach w różnych walutach. Zamiast rozrzucać warunki po wielu metodach, zasady można zamknąć w jednym, dobrze opisanym typie.
Agregaty i repozytoria
Aggregate to grupa powiązanych encji i obiektów wartości, traktowana jak jedna całość przy modyfikacji danych. Tylko główna encja – „root” – jest wystawiana na zewnątrz, a wewnętrzna struktura agregatu jest ukryta. Dzięki temu reguły spójności są pilnowane w jednym miejscu, a zewnętrzny kod nie może ich przypadkowo naruszyć.
Repository udostępnia agregaty, nie zdradzając szczegółów ich przechowywania. Dla warstwy domenowej nie ma znaczenia, czy dane siedzą w relacyjnej bazie, dokumencie JSON czy w pamięci – liczy się to, że można pobrać i zapisać cały agregat jako spójną jednostkę. Wiele zespołów wspiera się też fabrykami do tworzenia złożonych obiektów oraz wzorcem Specification do opisywania reguł biznesowych w formie, którą można łatwo testować.
| Element | Cechy | Przykład z systemu sprzedaży online |
| Entity | Stała tożsamość, zmienne atrybuty | Klient, Zamówienie, Produkt |
| Value Object | Brak tożsamości, ważna jest wartość, zwykle niezmienny | Adres dostawy, Cena, Ilość sztuk |
| Aggregate | Grupa powiązanych obiektów, jeden root pilnujący spójności | Zamówienie wraz z pozycjami i adresem dostawy |
Agregat to granica, wewnątrz której obowiązują konkretne reguły spójności, a na zewnątrz widać tylko jeden obiekt – root.
Czym są Bounded Context i Context Map?
Przy większych systemach sam model domeny nie wystarczy. Te same słowa mogą znaczyć coś innego dla różnych działów firmy, a próba stworzenia jednego „wielkiego modelu wszystkiego” kończy się zwykle bałaganem. Tutaj wchodzą w grę pojęcia Bounded Context i Context Map.
Bounded Context
Bounded Context to wyraźnie określona granica, w której dany model jest spójny, a pojęcia mają jednoznaczne znaczenie. W tym obszarze obowiązuje wspólny język, uzgodnione definicje i konkretne reguły biznesowe. Po drugiej stronie granicy te same słowa mogą mieć inne znaczenie, ale to jest akceptowalne, bo dotyczą innego fragmentu systemu.
Przykład: słowo „klient” w kontekście sprzedaży oznacza kogoś, kto złożył zamówienie, a w kontekście marketingu – anonimowego użytkownika, który zostawił tylko adres e‑mail. W Domain Driven Design każdy z tych zespołów może mieć własny model i własny kod, pod warunkiem że granice ich kontekstów są dobrze opisane.
Context Map
Context Map to mapa pokazująca, jak różne Bounded Contexts komunikują się ze sobą. Opisuje relacje typu „upstream–downstream”, miejsca integracji oraz wzorce ochronne, na przykład warstwę antykorupcyjną, która chroni jeden model przed nieuporządkowanym wpływem innego.
Taka mapa pomaga uniknąć sytuacji, w której jeden zespół nieświadomie łamie założenia innego kontekstu, np. bezpośrednio czytając jego bazę danych. Zamiast tego integracja odbywa się przez jasno zdefiniowane API, zdarzenia domenowe lub dedykowane translatory modeli. To ułatwia zarówno rozwój, jak i późniejsze modyfikacje architektury, w tym przejście do mikroserwisów.
Bounded Context porządkuje język i model, a Context Map porządkuje relacje między fragmentami systemu.
Jak stosować DDD w praktyce?
Czy każdy projekt potrzebuje podejścia domenowego? Nie. DDD najlepiej sprawdza się tam, gdzie domena biznesowa jest złożona, pełna wyjątków i zmieniających się reguł, a błędne decyzje projektowe bywają kosztowne. Prosty system CRUD do ewidencji danych zwykle nie wymaga tak rozbudowanego podejścia.
Typowy proces wdrożenia można ująć w kilku krokach:
- Rozmowy z ekspertami domenowymi i wspólne warsztaty (np. Event Storming) w celu odkrycia procesów i zdarzeń.
- Wydzielenie subdomen i Bounded Contexts oraz nazwanie ich w sposób zrozumiały dla biznesu.
- Zaprojektowanie modelu domenowego z użyciem encji, obiektów wartości, agregatów i repozytoriów.
- Określenie sposobów integracji między kontekstami i zewnętrznymi systemami na bazie Context Map.
- Dopiero na tym etapie wybór technologii, frameworków i szczegółów infrastruktury.
Implementacja podejścia domenowego jest możliwa w wielu technologiach. W ekosystemie Java często korzysta się z Spring Framework, w świecie .NET z ASP.NET Core, a w JavaScript z Node.js. Niezależnie od języka, wzorce takie jak agregaty, repozytoria czy obiekty wartości pozostają te same – zmienia się tylko składnia i biblioteki pomocnicze.
| Obszar | Korzyść z podejścia domenowego | Potencjalne wyzwanie |
| Współpraca z biznesem | Wspólny język i model domeny, mniej nieporozumień | Potrzeba zaangażowania ekspertów domenowych w pracę zespołu |
| Architektura systemu | Czytelne granice Bounded Contexts, łatwiejsze dzielenie na moduły | Trudność w poprawnym wyznaczeniu granic na początku projektu |
| Rozwój i utrzymanie | Łatwiejsze wprowadzanie zmian w regułach biznesowych | Wyższy koszt startowy i potrzeba doświadczonych projektantów |
W praktyce metoda DDD dobrze „niesie” zespoły, które akceptują iteracyjny sposób pracy: model domeny jest stale doprecyzowywany, a kod co jakiś czas wymaga refaktoryzacji, by nadążać za zmianami biznesu. Gdy zespół wejdzie w ten rytm, refleksja nad domeną przestaje być jednorazowym warsztatem i staje się stałym elementem pracy nad oprogramowaniem. Regularne rozmowy z biznesem stają się wtedy stałym punktem dnia programistów i analityków.