Cześć! Witam Was w kolejnym już wpisie w Cesarstwie-Dev! Ostatnio poruszaliśmy mocno techniczne tematy, nieraz schodząc do poziomu implementacji. Dzisiejszy temat jest bardziej miękkim zagadnieniem, lecz zdecydowanie nie jest oderwany od programistycznej rzeczywistości. Mówiąc ogólnie – przestańmy nadużywać getterów i setterów! W poniższym wpisie opiszę problemy związane z posługiwaniem się technicznym żargonem. Dodatkowo przestawię korzyści płynące ze stosowania języka biznesu w naszym kodzie. Jeśli uważasz, że kwestia nazewnictwa czy języka nie są tak istotne to… tym bardziej zachęcam do zapoznania się ze wpisem! Głód na zagadnienia techniczne zawsze można rozwiązać później, na przykład dzięki wpisowi na temat architektury heksagonalnej. Tymczasem, zapraszam do czytania! W przykładach będę używał, jak zawsze, języka C# oraz framework’a do testów – XUnit.

Czym jest język biznesu?

Warto wspomnieć, że nie ma jednego uniwersalnego języka biznesu. Wszystko zależy od branży, w której pracujemy. Językiem biznesu nazywamy ogół słownictwa używany przez różnych ekspertów domenowych. W czasie spotkań z nimi warto doprecyzować wszelkie niejasności, gdyż język ten powinien być w pełni transparentny i jednoznaczny. Tak wypracowanym słownictwem powinni się porozumiewać wszyscy, związani w danej firmie z konkretnym systemem. Niezależnie od tego, czy są to analitycy, menadżerowie, inni pracownicy etatowi, czy my, programiści. Wspólny język znacząco usprawnia komunikację w firmie, co sprawia, że nasza praca jest łatwiejsza i szybsza. W końcu od razu po zgłoszeniu błędu wiemy, do którego miejsca w kodzie musimy spojrzeć. Jedną z technik odkrywania (między innymi) języka wszechobecnego jest Event Storming. Polecam serdecznie podcast na ten temat u unikalnego Macieja Aniserowicza.

W kontekście DDD mówimy o języku wszechobecnym w ramach pewnego kontekstu. Już po raz kolejny w Cesarstwie-Dev odsyłam do niezastąpionego Martina Fowler i jego artykułu na ten temat. Kolejnym znaczącym aspektem używania języka biznesu są jego granice. Konkretny termin może oznaczać co innego w różnych kontekstach w ramach jednej firmy. Weźmy dla przykładu wpis w ramach projektu Blogging. Dla odbiorców wpis będzie czymś, co mogą przeczytać, ocenić, skomentować i udostępnić. Takie też zachowania powinna udostępnić odpowiednia klasa w danym kontekście. Jednak jeśli spojrzymy na blog z perspektywy recenzenta, to zauważymy zupełne inne słownictwo. W tym kontekście klasa powinna udostępniać zachowania związane z akceptowaniem, zaznaczaniem błędów czy np. przypominaniem odpowiednim osobom o procesie recenzji.

Konsekwencje

Wiele razy w życiu spotkałem się z kodem, który korzysta z klas biznesowych jak zwykłych śmietników na dane. Klasy takie nie przejawiają żadnych zachowań związanych z domeną, lecz po prostu zbierają wartości w jeden obiekt. Zachowania natomiast są przechowywane w klasach, których nazwy zwykle kończą się na Service czy Processor. Można powiedzieć, że zaprojektowane są poprzez używanie żargonu technicznego. Przy takiej implementacji w rozmowach z ekspertami dziedziny nie można przekładać ich słów dokładnie na kod. Gdybyśmy jednak w kodzie posługiwali się odpowiednim słownictwem to nawet nietechniczne osoby będą w stanie pomóc nam zidentyfikować problem, bądź zaprojektować rozwiązanie! W końcu to oni nam powiedzą, że w chwili opublikowania wpisu (zdarzenie PostPublished) powinniśmy powiadomić subskrybentów (kontekst Subscriptions) poprzez wybraną przez nich metodę notyfikacji (metoda Notify(PostPublished postPublished) z klasy subskrybenta).

Czy to oznacza, że wszędzie powinniśmy tak projektować nasze rozwiązania? Odpowiedzmy jak wszyscy porządni konsultanci: to zależy. Pragmatyzm również jest bardzo ważny. Nie wszystkie konteksty w ramach jednego systemu będą równie ważne i skomplikowane. Niektóre będziemy mogli kupić, inne będą zwykłymi CRUD-ami. W takich przypadkach proces rozwiązywania problemów z danej dziedziny wygląda zupełnie inaczej. W przypadku skomplikowanych, ważnych i nietrywialnych kontekstów warto stosować się do rad opisanych w tym wpisie. Wiąże się to z wieloma korzyściami, które wstępnie już przedstawiłem w postaci teoretycznej. Zobaczmy jednak, jak wygląda to w praktyce.

Język biznesu a kod

Wyobraźmy sobie, że implementujemy logikę związaną z oddawaniem wpisu do recenzji. Współpracujący z naszą firmą interesariusze mówią następująco: Autor może zakończyć edycję wpisu tylko jeśli zawiera tytuł, treść, jak i przynajmniej jeden tag. Dodatkowo wpis ten musi być obecnie szkicem. Wpis po zakończeniu edycji jest wpisem stworzonym. Po zakończeniu edycji przez autora powinniśmy powiadomić dwóch recenzentów, że mogą rozpocząć swoją pracę związaną z danym wpisem. Przenieśmy więc to zdanie na kod! Użyjemy tutaj dokładnego słownictwa z języka biznesu. Istotne jest, że zdecydowaliśmy na rozgraniczenie tych dwóch kontekstów. Pierwszy z nich wiąże się z etapem wytwarzania wpisu, drugi natomiast skupia się wyłącznie na jego recenzji. Przejdźmy do zaprojektowania klasy wpisu wraz z odpowiednim zachowaniem. Na wstępnie zauważę, że wszystkie klasy będą posiadały minimum kodu, potrzebnego do przedstawienia idei opisywanej w tym wpisie.

Spójrzmy na język, który opisuje powyższe zachowanie! Przypomnijmy słowa eksperta: Autor może zakończyć edycję wpisu tylko jeśli zawiera tytuł, treść, jak i przynajmniej jeden tag. Dodatkowo wpis ten musi być obecnie szkicem. Wpis po zakończeniu edycji jest wpisem stworzonym. Zdanie to jest dokładnie zawarte w naszym kodzie! Spójrzmy na metodę FinishEditing (zakończ edycję). Pierwszy if sprawdza, czy wpis jest szkicem. Następnie przypisujemy odpowiednie pola, jak i sprawdzamy warunki, które wypowiedzieli ludzie biznesu. Na końcu tworzymy odpowiednie zdarzenie. W zdaniu wypowiedzianym przez eksperta widzimy pewne słowa kluczowe: Po zakończeniu edycji wpisu. Fragment ten sugeruje nam, że powinniśmy stworzyć odpowiednie zdarzenie oraz powiadomić pozostałe partie systemu o pewnym fakcie. Nazewnictwo tych zdarzeń również warto konsultować z ekspertami dziedziny, przy okazji stosując się do prostych zasad. Po pierwsze, nazwa zdarzenia powinna zawierać czasownik w czasie przeszłym. Po drugie, zdarzenie powinno być niemutowalne.

Obsługa zdarzeń

Ten króciutki akapit nie dotyczy dokładnie opisywanego tematu języka biznesu. Zdecydowałem się jednak opisać pewne szczegóły implementacji, dla tych z Was, którzy chcą dowiedzieć się, jak postanowiłem obsługiwać zdarzenia w projekcie Blogging. Przy okazji będzie to chwilowy odpoczynek od głównego tematu! Jak możecie zauważyć, klasa wpisu dziedziczy po bazowej klasie, która zawiera kolekcję zdarzeń domenowych. W ten sposób możemy osiągnąć takie zachowanie:

  1. Podczas wykonywania pewnej logiki biznesowej dodawane są zdarzenia do kolekcji
  2. W ramach jednej transakcji bazodanowej utrwalane są zmiany w agregacie, jak i zdarzenia domenowe
  3. Zdarzenia są wysyłane za pomocą wzorca Outbox Pattern

Jak widać obsługa zdarzeń może być prosta i przyjemna. W celu odpowiedniej implementacji powyższego zachowania należy dobrze zaprojektować warstwę persytencji, tak aby obsługiwane były transakcje, jak i zdarzenia dodawały się do odpowiedniej tabeli (bądź w inne miejsce). Nie napisałem jeszcze, w jaki sposób konteksty mogą się komunikować ze sobą. Odpowiedź? To zależy! Jeśli jesteśmy w środku modularnego monolitu, to najpewniej nie będziemy potrzebowali żadnych dodatkowych systemów. W przeciwnym razie warto skusić się na korzystanie z Kafki czy RabbitMQ. Temat wyboru odpowiednich narzędzi, jak i uproszczona implementacja takiego problemu, na pewno pojawi się w jednym z kolejnych wpisów w Cesartwie-Dev!

Język biznesu a testy

Jednym z większych korzyści płynących z używania języka biznesu jest znaczące ułatwienie procesu projektowania testów jednostkowych! Wymagania, które korzystają z języka wszechobecnego, bardzo łatwo możemy przełożyć na testy dobrze zaprojektowanych systemów. Weźmy pod lupę znane już nam zdanie: Autor może zakończyć edycję wpisu tylko jeśli zawiera tytuł, treść, jak i przynajmniej jeden tag. Skupmy się na ostatnim warunku i napiszmy odpowiedni test.

Jak widać, powyższy test weryfikuje poprawność dokładnie jednej części zdania wypowiedzianego przez eksperta. Dzięki temu możemy w szybki sposób upewnić się, czy nasze rozumienie problemu jest zgodne z tym, co oczekują od nas eksperci domeny. Dodatkowo możemy skopiować nazwy wszystkich testów i przekazać je do odpowiednich osób, by zweryfikowali, czy na pewno pokrywamy wszystkie przypadki biznesowe. Ostatecznie, nawet osoba nietechniczna może przygotować nam zestaw nazw testów, do których my przygotujemy implementację. Jedna zmiana w sposobie myślenia, niezliczone korzyści!

Podsumowanie

Mam nadzieję, że powyższy wpis zachęcił Was do odpowiedniego projektowania zachowań biznesowych w Waszych projektach. Jak wspominałem, nie jest to zawsze wymagane. Nieraz spotykamy się z prostymi systemami, gdzie zwykłe gettery, settery, a do tego wykorzystanie jakiegoś ORM-a w zupełności wystarczy. Jednak w sytuacjach gdy projektujemy bardziej skomplikowany system, którego logika biznesowa jest nietrywialna, to zdecydowanie warto zapoznać się z pojęciami biznesowymi panującymi w firmie.

Posługiwanie się jednym językiem wiąże się z licznymi korzyściami. Wśród nich można wymienić sprawniejszą komunikację, większe zrozumienie problemów, ułatwienie współpracy pomiędzy zespołami, zacieśnianie więzów w firmie czy ułatwiony proces pisania testów. Dodatkowo, dzięki posługiwaniu się językiem biznesu możemy śmiało zapraszać na spotkania związane z projektowaniem systemu ludzi nietechnicznych. Unikniemy też ich zdziwionego wzroku, gdy już kolejny raz słyszą o jakimś serwisie wpisów, procesorze recenzji czy encji bazodanowej.

Mam nadzieję, że spędziliście razem ze mną miłe chwile w Cesartwie-Dev! Liczę na to, że będziecie mogli wykorzystać porady zawarte w tym wpisie w swoich prywatnych, bądź komercyjnych, projektach. Dajcie znać, w komentarzu bądź mailowo, czy wpis się podobał, oraz czy zamieszczać więcej wpisów o podobnej tematyce. Jeśli odczuwacie ochotę przeczytania kolejnego wpisu, to co powiecie na temat odpowiedniego dostarczania klienta API? Nie wykluczam, że bardziej zainteresuje Was przetwarzanie bezserwerowe na platformie Azure. Niezależnie, dziękuję Wam za uwagę! Widzimy się za tydzień z okazji kolejnego wpisu w Cesarstwie-Dev!

Książkowy update:

W kolejce:

  • TDD. Sztuka tworzenia dobrego kodu
  • Mikroserwisy w akcji

W trakcie:

  • Netflix – to się nigdy nie uda
  • Kubernetes – Wzorce projektowe

Skończone:

  • Software Craftsman

1 Komentarz

dotnetomaniak.pl · 2020-10-12 o 22:30

Używaj języka biznesu! – Cesarstwo Dev

Dziękujemy za dodanie artykułu – Trackback z dotnetomaniak.pl

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *