Przejdź do treści

Bounded context w DDD 👀

Technika Bounded Context jest najbardziej wyrafinowaną i subtelną z technik DDD. Zakłada ona istnienie różnych modeli opisujących te same byty, używanych w różnych kontekstach.


Cześć 🙂

Jest to trzeci wpis z serii o DDD. Dziś porozmawiamy o tym czym jest Bounded Context (BC).

W dzisiejszym artykule:


Zrozumieć Bounded Context

Czym jest Bounded Context (BC)? Tłumacząc to bezpośrednio na nasz polski język to jest to Ograniczony kontekst. Prawdę mówiąc to, ta translacja jest w 100% poprawna. Ale jeżeli jesteś nowy w DDD i pierwszy raz słyszysz o BC, to możesz się zastanawiać co w rzeczywistości oznacza ograniczony kontekst?

Bounded Context definiuje granice podsystemu. Zawiera swój model domenowy i co jest bardzo ważne nie współdzieli danych modelu z innym kontekstami. W praktyce oczywiście jest tak, że różne Bounded Context’y muszą komunikować się ze sobą. Komunikacja taka nie jest niczym złym – bez tego nasze oprogramowanie miałoby ciało ale nie miało przykładowo rąk czy nóg, innymi słowy – nie działałoby jako całość. BC komunikują się między sobą przez jasno zdefiniowane API.

Razem z pojęciem BC często pojawia się także pojęcie Ubiquitous Language (wszechobecny język). Oznacza ono, używanie wspólnego języka w danym podsystemie przez wszystkich. Kim są wszyscy? Ludzie od biznesu, product owner, scrum master, developerzy – wszyscy, którzy pracują w danym podsystemie.

Język ten jest platformą komunikacji pomiędzy tymi wszystkimi ludźmi – tylko trzeba pamiętać – w ramach danego bounded context’u. Jak jest to przedstawione na obrazku wyżej, Produkt w kontekście Shopping Context będzie charakteryzował się innymi właściwościami niż ten w Offers Context. W ofercie ważne będzie podkreślenie jego charakterystycznych cech np. w czym pomoże potencjalnemu użytkownikowi oraz jaka jest jego cena. W kontekście sprzedaży cena również będzie ważna ale dodatkowo istotne będzie czy produkt jest dostępny i można go kupić. W kontekście samego produktu istotne może być np. moment dodania produktu do sklepu czy też ilość produktu w magazynie. Dodatkowo, z czasem język może ewoluować. Eksperci domenowi mają większą wiedzę, wymagania biznesu się zmieniają lub po prostu dochodzą nowe.


Subdomena vs Bounded Context

Nie będę się specjalnie rozpisywał w tej sekcji.

Najważniejsza różnica pomiędzy obiema definicjami jest taka: subdomena opisuje problem a bounded context jest jego rozwiązaniem. Subdomeny odkrywamy a bounded context definiujemy. Jest to po prostu przełożenie wszystkich informacji jakie do tej pory zebraliśmy na model. Model, który za pomocą wszechobecnego języka definiuje zachowanie konkretnego bounded context’u.


Przykład BC

Przykład został zaczerpnięty z dokumentacji MS i nieco zmodyfikowany.

Scenariusz: Usługa dostaw przy pomocy dronów.
Firma XYZ uruchamia usługę dostaw przy pomocy dronów. XYZ zarządza całą flotą dronów.  Jej użytkownicy mogą poprosić o drona do odbioru towaru. Kiedy klient planuje odbiór, system backendowy przydziela drona i powiadamia użytkownika o przewidywanym czasie dostawy. W trakcie realizacji dostawy klient może śledzić lokalizację drona, dzięki stale aktualizowanemu systemowi. XYZ pozwala również na usługi firm zewnętrznych – firma chcąca być podwykonawcą rejestruje się w serwisie i również może dostarczać przesyłki. Z punktu widzenia klienta końcowego usługi nadal są świadczone przez firmę XYZ.

Analiza:

Problem opisany powyżej można podzielić na kilka subdomen (nie wszystko zostało ujęte w scenariuszu):

Shipping – jest umieszczony w centrum diagramu, ponieważ jest to rdzeń biznesu.
Zarządzanie Dronami – również jest podstawą działalności firmy. Funkcjonalność, która jest ściśle związana z zarządzaniem dronami, obejmuje naprawę dronów oraz wykorzystanie analizy prognostycznej do przewidywania, kiedy drony będą wymagały obsługi i konserwacji.
Analiza ETA – umożliwia oszacowanie czasu odbioru i dostawy.
Third party – umożliwia aplikacji planowanie alternatywnych metod transportu, jeżeli paczka nie może być wysłana w całości przez drona.
Dzielenie dronów – jest możliwym rozszerzeniem podstawowej działalności. Firma może mieć nadmierną pojemność dronów w określonych godzinach i może wynajmować drony, które w przeciwnym razie pozostałyby bezczynne. Ta cecha nie pojawi się w początkowym wydaniu.
Nadzór wideo – to kolejny obszar, w którym firma może rozwinąć się później.
Konta użytkowników, fakturowanie i call center to subdomeny, które wspierają podstawową działalność firmy.

 

Teraz, mając już zdefiniowane subdomeny naszego problemu możemy przejść do definiowania Bounded Context’ów (BC’s).

Modelem, znajdującym się w centrum domeny jest model drona. Obojętne z jakiej subdomeny spojrzysz na projekt – dron jest w jego centrum. Zarządzanie dronami (Drone Management) będzie definiowało historię konserwacji, przebieg, rocznik, numer modelu, itd. Ale kiedy jest czas na zaplanowanie dostawy, nie dbamy o te rzeczy. Podsystem planowania musi tylko wiedzieć, czy dron jest dostępny oraz jaki jest przewidywalny czas odbioru i dostawy.

Idąc starym podejściem (moim zdaniem biorącym się z chęci szybkiego dostarczenia wartości i braku myślenia nad tym co robimy) po 3 miesiącach pracy mogłoby się okazać, że nasz model wyglądałby w taki sposób:

class Drone {
    // Drone Management
    MaintenanceHistory maintenanceHistory;
    int mileage;
    int age;
    String modelNumber;

    // Shipping
    boolean isAvailable;
    LocalDateTime pickUp;
    LocalDateTime delivery;
    
    // pozostale sub-domeny
    //...
}

Do czego to końcowo doprowadzi? Do kodu, który jest

  1. Nieutrzymywalny – dodanie czegoś nowego / modyfikacja istniejących właściwości to zmora i tylko pogłębienie problemu.
  2. Trudny w zrozumieniu – jak wejdzie ktoś nowy na projekt, to chcąc nie chcąc musisz wytłumaczyć mu działanie wszystkiego co kręci się wokół modelu drona, inaczej może tylko dodatkowo nabałaganić.

Jak można rozwiązać ten problem? Wprowadzając BC! Po pierwsze trzeba zastanowić się jak zdefiniować granice pomiędzy sub-domenami. Mogłoby to wyglądać następująco:

I teraz najistotniejsze. Chcemy aby nasz model drona był czymś innym w zależności od tego w jakiej sub-domenie się znajdujemy! Czyli zamiast jednego wielkiego modelu będziemy mieli kilka innych! Takich, które będą odpowiadać tym właściwościom jakie są wykorzystywane w konkretnej sub-domenie.

// Drone Management
class Drone {
    MaintenanceHistory maintenanceHistory;
    int mileage;
    int age;
    String modelNumber;
    
    // metody specifyczne do wykonania w tej domenie
    // ...
}

// Shipping
class Drone {
    boolean isAvailable;
    LocalDateTime pickUp;
    LocalDateTime delivery;

    // metody specifyczne do wykonania w tej domenie
    // ...
}

W taki sposób definiujemy zachowania i właściwości specyficzne dla danego Bounded Context’u. Zwiększamy również czytelność i możliwość łatwiejszego wdrożenia nowych osób. Nowa osoba nie musi już wiedzieć wszystkiego o wszystkim. Jeżeli ma zająć się sub-domeną zarządzania dronami to wystarczy jej wiedza w obrębie tego konkretnego modelu.


Podsumowanie

Bounded Context (ograniczony kontekst) nie jest czymś specjalnie trudnym do zrozumienia. W nowych projektach, gdzie mamy okazję modelować subdomena – bounded context  w relacji 1:1 wszystko wydaje się być łatwe. Problem pojawia się kiedy wchodzimy w świat legacy (lub sami go tworzymy) i okazuje się, że nie jest już tak idealnie. Nasz bounded context zaczyna rozwiązywać problemy z kilku domen a po kilku miesiącach zostaje już tylko context – bounded zostało zjedzone.

Oczywiście tak nie musi być :). Jako programiści / architekci musimy zawsze czuwać nad kodem i myśleć jaki wpływ będzie mieć zmiana, którą właśnie implementuję. Niestety, z doświadczenia wiem, że biznes chce wszystko na już i niespecjalnie daje nam czas na zastanowienie się nad kodem. Co robić w takich sytuacjach? Może to zabrzmi arogancko ale.. nie zawsze spełniać na hura zachcianki klienta. Ile razy spotkałeś się, że klient coś chciał a za miesiąc się rozmyślał? Mi kilka razy się zdarzyło… 🙂

Źródła:


Za tydzień

Chcę poruszyć swoje indywidualne kwestie – tak jak zrobiłem to w tym wpisie. Właściwie, to wydaje mi się to dobrym pomysłem żeby robić takie comiesięczne podsumowania + przemyślenia co dalej.

4.7 7 votes
Article Rating
Subscribe
Powiadom o
guest
1 Komentarz
najnowszy
najstarszy oceniany
Inline Feedbacks
View all comments
Marcin
Marcin
3 lat temu

Dzięki za artykuł. Pragmatyczna esencja odnośnie kilku kwestii dekompozycji. Szkoda, że nie ma dalszej cześći i pokazania bardziej skomplikowanego przypadku, kiedy BC nie jest 1:1 z subdomeną

1
0
Would love your thoughts, please comment.x