Tuesday, November 29, 2011

Bounded Context

Jasne, że nie będę od teraz pisał o DDD, bo już inni o tym ciekawie piszą. Chciałbym się tylko trochę uzewnętrznić w temacie, który szczególnie mnie poruszył, gdyż rozwiązuje dość poważny problem z architekturą. Jeśli nie nie zetknąłeś się z filozofią (w moim rozumieniu to bardziej sposób myślenia niż toolbox; taka obiektowość podniesiona level wyżej - na poziom architektury) DDD to na wstępie proponuję:

O jakim problemie mowa?

Powiedzmy, że rozpoznajemy, co też dzieje się domenie sklepu internetowego (nie wiem dlaczego to sklep zazwyczaj przychodzi na myśl:)). Powiedzmy, że dzieje się jak poniżej:
Jest to jakaś interakcja pomiędzy obiektami w dziedzinie.

Gdy zaczynamy modelować, naturalnie pojawiają się klasy takie jak: Zamówienie, Koszyk, itd. Powstaje model złożony z powiedzmy 30-50 klas. Wszystko wygląda super świetnie, ale zbiegiem czasu coś zaczyna nie grać. Pojawiają się następujące symptomy:
  • W związku z kolejnymi wymaganiami, do obiektów dochodzi coraz więcej atrybutów i metod
  • Programista implementujący przypadek użycia związany ze złożeniem zamówienia z trudem odnajduje się w gąszczu atrybutów i metod dodanych przez kogoś, kto implementował realizację Zamówienia
  • Niektóre obiekty są używane w tak wielu miejscach systemu, że jakakolwiek w nich zmiana ma spore skutki w innych odległych miejscach
Co więcej: jeśli z wymagań wynika jakaś konkretna zmiana w jednym miejscu systemu, to obija się ona głośną czkawką w zupełnie innym właśnie z powodu "reużywania" obiektów modelu.

Niby wszystko zostało przygotowane zgodnie z regułami sztuki, ale jednak wszyscy czują, że coś śmierdzi...tylko nie wiadomo z jakiej przyczyny.

Powód jest taki, że ten sam obiekt modelu używany jest wielu różnych kontekstach. Zamówienie wynikające z interakcji użytkownika z Koszykiem jest nieco inną sprawą niż Zamówienie realizowane przez magazyn.

"Bounded context should have a name so that you can talk about them"

Rację mieli starzy Indianie, gdy twierdzili, że jeśli poznasz czyjeś imię, zyskujesz nad tym kimś władzę. Nie inaczej jest z bounded contexts. Jeśli nie zauważymy i nie nazwiemy kontekstów użycia modelu, to mogą nam zrobić krzywdę. Nienazwane lubią się mieszać i dokładać do obiektów modelu rożnego rodzaju dodatki właściwe dla swej specyfiki. W skutek czego powstaje model-potworek, który w założeniu miał być super, a w wykonaniu i tak jest kolejną wersją big ball of mud.

Jeden model w jednym kontekście

W związku z dokonanymi odkryciami warto zalecać:
  • Nazwij kontekst, w którym może być wykorzystywany model. Już sama próba nazwania sprawi, że kontekstów pojawi się kilka (o ile tam są).
  • Jeden model może być wykorzystywany tylko w jednym kontekście (bounded context). Zamówienie w kontekście Koszyka to nie dokładnie to samo, co zamówienie w kontekście Magazynu.
  • Odizoluj poszczególne konteksty i właściwe im modele od siebie

W powyższych zasadach można dopatrzyć się echa Single Resposibility Principle. Z odpowiedzialności modelu powinien wynikać jednoznaczny kontekst jego użycia. Tyle, że Bounded Context definiuje to wprost i wyraźnie, a z zasady odpowiedzialności trzeba sobie wywnioskować.

Jeżeli w konsekwencji mamy zdefiniowanych kilka zwartych modeli o jednoznacznie określonych kontekstach użycia, to musi istnieć coś, co będzie potrafiło skonwertować obiekty z jednego kontekstu w drugi (jeśli jest taka potrzeba). W DDD ta potrzeba jest zaspokajana poprzez zdefiniowanie Context map w postaci zestawu usług-translatorów (w apachowych commonsach nazywanych transformerami). Ich odpowiedzialność to właśnie konwersja.

Podsumowując zyski z wprowadzenia konceptu Bounded Context:
  • Redukcja echa w systemie - zmiana w modelu w jednym miejscu nie skutkuje oddźwiękiem w innym
  • Zmiany wynikające z biznesu mają na poziomie architektury ograniczony do kontekstu zasięg
  • Można lepiej zorganizować prace nad projektem (tutaj DDD proponuje kilka pomysłów w zależności od tego jakie relacje występują pomiędzy kontekstami).

5 comments:

  1. Innym wartym wspomnienia sposobem na realizację komunikacji między kontekstami jest model zdarzeniowy.

    ReplyDelete
  2. W ogólności konteksty mogą integrować się poprzez:
    - dane - gdzie np Repozytorium jednego kontekstu pobieranie sobie część danych z serivsu apliakcyjnego drugiego kontekstu (drugi kontekst ukrywa model, zwraca rodzaj projekcji)
    - czynności - najprostszy scenariusz, gdzie po prostu wołamy serwisy z innego kontekstu
    - zdarzenia - o których właśnie pisał Krzysztof. Dają nam decoupling (ze wszystkimi konsekwencjami), umożliwiają odcięcie się od strzałki czasu (asynch), architekturę pluginową...
    A orkiestracja wielu zdarzeń jest możliwa dzięki Sagom biznesowym.

    Ale za każdym razem kluczowe jest hermetyzowanie modelu danego kontekstu (znowu zasada OO na poziomie arch. apliakcji).

    ReplyDelete
  3. @Sławek

    Nie mogłem już dłużej wytrzymać braku postów na twoim blogu i wiedziałem, że to Cie sprowokuje :)

    Spójrzmy przez pryzmat DDD na rozdział From the Mud to Structure z POSA 4. Takie np. Shared Repository przedstawia komunikację między komponentami poprzez dane. Dobre dla systemów data-driven - np. jakieś aplikacje pomiarowe. Mejk sens?

    ReplyDelete
  4. Czy przypadkiem przekazanie "czegoś" do innego kontekstu to nie "żądanie", które w odpowiedzi dostaje "obiekt" w odpowiedzi, nie koniecznie "żądany" obiekt a jego "kopię" lub wersję?

    Jeżeli konteksty były by obsługiwane przez odrębne podsystemy (komponenty) przekazanie czegokolwiek między nimi właśnie tak by wyglądało (to coś jak zaświadczenie w urzędzie: dostaje jakiś pełny lub częściowy odpis tego co urząd ma...)

    ReplyDelete