⚔️ Moc i magia DDD w świecie Heroes III: Praktyczne modelowanie Bounded Contextów. Epizod 1: Jednostki

Grafika została złożona ze zrzutów ekranu zrobionych podczas rozgrywki w grę Heroes of Might and Magic III.

// todo: moze same jednostki na razie!

Statystyki bohatera wpływają na jednostki w bitwie, a wynik bitwy przecież na armię bohatera. Czyli co musimy zrobić najpierw? Czy mogą pracować nad tym osobne zespoły. Zobacz w znanej Ci domenie Heroes III jak praktyki takie jak DDD i Event Modeling rozwiązują problemy znane Ci z codziennej pracy przy projektach IT.

💾 Z życia na kodach

Mój pan od fizyki w liceum mówił, że po rysowaniu tych wektorów na lekcjach, teraz wszędzie widzi działające na świat siły. Ja mam trochę tak samo, można to nazwać DDDozą codzienną. Kiedy coś robię, w mojej głowie już formują się Bounded Contexty, podobnie jak w głowie tytułowego bohatera Good Doctor - diagnozy dla pacjentów. Tak samo było ostatnio, kiedy po latach znowu odpaliłem Heroes III.

🧟 Nieśmiertelna gra

To gra wiecznie żywa, tak samo jak jej community. Niektórzy fani próbują nawet odwzorować silnik gry jako projekt open source. Zacząłem się zastanawiać gdzie tutaj miejsce na DDD? Gdzie Bounded Contexty? Jest tego aż tyle, że z pewnością może powstać cała seria wpisów. Zacznijmy od przykładu różnych reprezentacji jednostki.

Czas otworzyć puszkę pandory i poznać nieznane dotąd czary!

To nie będzie odwzorowanie 1 do 1. Poruszajac się po tej domenie zobaczymy jak czynić silnik gry wg. zasady Open-Closed. Kolejne ewoluowały, ale była do dalej ta sama gra. Zmieniała sie grafika, mechanika pozostawała. Odpowiednio zrealizowany powinien nadązyć, tak samo jak przesiębiorstwo.

Niezależne klocki, z których utworzymy całą grę. Dany zespół może zostać oddelegowany do pracy nad jednym kontekstem.

👾 Jednostka

Naiwnosc - baza

Zacznijmy naiwnie, jeśli ju.z ten etap masz zas sobą, i wiesz, że na większości studiów nie nauczą Cię właściwie modelować oprogramowania, to możesz pominąc ten etap. Tylko zacząłem tworzyć obiekty, a juz doszedłem do tego, że jeśli chcę określić frakcję do jakiej należy jednostka, to co potrzebuje frakcja? Tutaj już określane jest też jakie budynki mozna wybudowac, jaki level gildii magów, to relacja 1 do 1. Niestety, wielu z nas tak robiło, czy dalej robi. Tak czy siak ten wpis jest właśnie dla Ciebie!

Próbujemy odwzorować “realny świat”, czy świat Heroes, opisując wszystko co wiemy o danym “obiekcie”. Obciążenie poznawcze jest bardzo duże i kołysze się jak trzcina na wietrze, co skonczyc - od czego zaczac?

data class Creature(
    val id: String,
    val name: String,
    val faction: Faction,
    val level: Int,
    val upgrades: Set<Creature>,
    val cost: Cost,
    val abilities: Set<SpecialAbility>
    val shots: Int = 0,
    val doubleWide: Boolean = false
)

data class Stats(
    val attack: Int,
    val defense: Int,
    val damage: Range,
    val health: Int,
    val speed: Int,
    val growth: Int,
)
data class Range(val min: Int, val max: Int)
typealias Amount = Int
data class Cost(val resources: Map<ResourceType, Amount>)
enum class ResourceType {
    GOLD,
    WOOD,
    ORE,
    MERCURY,
    SULFUR,
    CRYSTAL,
    GEMS
}

sealed interface Faction {
    data object Castle : Faction
    // określenie budynków, jednostek, kosztów itp.
}

Dlaczego to tak wyglada? Pomimo, że programujemy “obiektoow”, to gdzieś z tyłu głowy wtłoczono nam, że wszystko i tak będzie tabelką. Nie raz “trzecia postać normalna”, brak duplikacji czy kanoniczny model danych. To są z pozoru dobre pojęcia, które mogą spowodować implozję w Twoim projekcie. Pamiętam jak dziś pierwszą pracę i rozmowy o modelu danych. NIE ZACZYNAJ PROJEKTU OD MODELU DANYCH. Czas na dziel i zwyciężaj. Jak więc dzielić projekt? Sposobów zapewne jest wiele, pokażę Ci jak ja do tego podchodzę.

Event Storming

Zacząłem od jednostki. Modelujemy jednostkę. Co może się “wydarzyć z taką” Jednostką? Designer też już przygotował jakieś widoki, którymi możemy się posiłkować budując nasze wspólne rozumienie.

Spróbowałem też porozmawiać z ChatemGPT i przeprowadzić taką sesję oraz zidentyfikować Bounded Contexty. Zapis rozmowy jest dostępy TUTAJ. Wnioski są takie, że o ile chat dobrze orientuje się w DDD, to domeny (jak np. Heroes) zna powierzchownie. Oczywiście nie będzie tym bardziej ekspertem domenowym w jakimś konkretnym przedsiębiorstwie. Musielibyśmy mu bardzo dokładnie opisać co tam się dzieje, czyli wydobyć wiedzę od ekspertów, a do tego właśnie służy Event Storming.

Event Modeling

// znajdujemy logicznie powiazania miedzy eventami // tak definiujemy bounded contexty

Pokazac co bedzie miał taki model, czyli Creature w kilku przypadkach.

Bitwa

Dzialajace czary Szczescie

Na pewno bedzie miala wplyw na armie bohatera. Ale czy mozemy developować to dwoma osobnymi zespołami? Tak? Wazne ustalic kontrakt miedzy nimi i sposob integracji. Mapa kontekstów. Ani jedne ani drugi nie bedzie wiedział o sobie. Zdarzenia inside/out - zwiekszamy coupling.

Wiemy, ze sie rozpoczela i zakonczyla. Proces całego Scenariusza bedzie to koordynował. To umozliwia łatwe wproawdzanie trybów jak np. pojedynki, które weszły w Heroes V. Taki podział ze względu na Capabilities, mozna uznac kolejne modelu domenowego. // todo: zrobic rysunek z warstawami Umozliwia wprowadzane nowych produktów na rynek, tez komponowanie. Np. Uber ostatnio mi wysłał o paczkach. Bo na dole maja mozliwosc przewozu. Jesli moga ludzi, to czemu nie jakis karton?

Rekrutacja

Zamek, przyrost (astrologowie oglaszaja), ogarnac przyrost, ze rozne konteksty nam na to wplywaja, ktore bedziemy modelowac pozniej.

Rekrutacja moze sie odbywac w zamkach czy też siedliskach na mapie. W zamku też są siedliska, dobrze to zamodelować osobno od zamku, który będzie tylko z tego korzystał Rekrutacja w zamku to taka “kompozycja” siedlisk.

Zamek jest m. in. wzorcem projektowym Composite z wielu siedlisk robimy jedno.

Mapa

Strażnik skarbu/kopalni

  • Czy interesuje nas czyjego ta jednostka jest koloru?
  • Czy jakie ma artefakty? Bohater?
  • Działajace na nia czary?

Nie… wazny jest tylko typ jednostki i co na niej jest i gdzie stoi.

Bohater

Armia Wpływ bohatera stats na jednostke Wpływ artefaktów

Księga zaklęć

Spellbook Jak wiemy w Heroes III, ale juz w V jednostki miały swoja wlasna ksiege zaklec. Po co ksiega ma wiedziec, ze nalezy do heroesa? Zrobmy tak, zeby byla niezalezna. To Heroes moze wiedziec, ze ma dana ksiege.

Artefakty

Zobrazowac konteksty, jakie dane i agregaty jak wygladaja. Co sie w nich dzieje, jakie oepracje eventy/command i dane

Na pewno jeszcze pominałem jakieś kwestie. Co kolejnego byś zamodelował? Widzisz jakieś konteksty. Daj znać :)

TL;DR

Jeśli chcesz, żeby Twoja wiedza o Bounded Contextach nie weszła na kolejny poziom Gildii Magów, to po prostu przewiń do instrukcji instalacji. Jesteś tutaj dalej? Czas otworzyć puszkę pandory i poznać nieznane dotąd czary! Jesli chcesz, zeby Twoja wiedze o Bounded Contextach spowijala dalej mgla wojny (czarna mgla) to przewin od razu do instrukcji instalacji (to w tym drugim)

Event SOurcing - przykład AI dla Heroes. Statystyki jak w Age of Empires. Wiadomo ile jednostek jak grac itp. co sie bardziej oplaca. Wejscie do procesu - zegar, mozna wtedy zrobic gre online w trybie rzeczywistym jak plemiona. Walka w Heroes, teraz mozna od razu zaakceptowac wynik. Ale to jest command, ktory moze zostac odrzucony. Mamy event.

Astrologowie oglaszaja, ze symbolem tego tygodnia bedzie… Bounded Context

Behaving / Becoming z sobotki DDD Event SOurcing przykład AI dla Heroes III

Wzorzec Decider, co jest nam potrzebne? Jeremi metody evolve? Jako command aktualny stan naszego portfela. CO chcemy zarekrutowac. Jesli mamy pieniadze i sa dostepne jednostki - rekrutujemy. To jest aktualny stan np.

Jednostka na zamku/ planszy czy w Twojej armii. Modułowość rozwiązania. Czy to będą stronnicy czy nie. Pokazać jaka jest roznica kiedy myslimy o innym przyjkladem. Aktywny/ nieaktwyny uzytkownik systemu dodajesz pozniej. Nie wazne jak ktos dolaczyl do armii.

Księga czarów. W przypadku “podróży” wystarczy nam tylko mana. Tak mozemy rozwijac software w zasadzie Open-Closed. Moglibsmy mie czary. Nie modyfikujemy juz poprzedniego stanu.

Czary: Spell casted - Magia ziemi 3 level - spell point used

Oddzielnie READ od Crud - Andrzej krzywda poczatek podcastu 74 BSD. To powinie nbyc default.

Jednostka na zamku/ planszy / twojej armii. Modulowosc rozwiazania

Perspektywy BEHAVING / BECOMING - BEHAVING, zueplnie inaczej sie zachowuje. Mozesz go kupic. Dolaczanie - rozne wejscia do Armii. Mozesz kupic w zamku, ale to moga byc tez stronnicy. Jaka jest roznica kedy myslimy o innym przykladem jest aktwny/nieaktywny uzytkownik - standardowym. Pokazac jak rozni sie myslenie Event-Driven.

Do prezetntacj: Nie myslalem, ze Was tyle bedzie, to tak jak zaatakowac szkielety na planszy. Nie patrzysz na mpie ,a potem masz tysiac na swoje kilka rosalek. Horda

Wygrywasz sokole oko

Bohater w karczmie

Zamek na mapie - czy jest zbudowana cytadela. Jaki level. Zamek wewnatrz juz konkret nas interesuje. Co jest, co mozemy, czy budowalismy tamtego dnia

Po walce - w innym konteksie interesuje nas tylko wynik. Ile jednostek stracilem. Czy dolaczyly i czy stracilem. Nie wazne z jakiego powodu. Czy to byla walka / czy to byl wir. Czy to byli stronnicy.

Jest tez wazny kierunek zaleznosc. Mapa kontekstow. Czy dany kontekst publikuje event czy jest consumerem. Bo np. zwiekszanie naszego przychodu. Jesli bylby to np. jest artefakt i wtedy wprowadzenie takiego, czy ability bohatera musialoby zmieniac ciagle kontekst przychodu. Nie jest to Open-Closed.

Czasem jeden command prodikuje wiele eventow. Np. zakoncz ture. Na sam koniec mamy ostatnia ture

Magia ziemii - spell casted, point used na … i potem odnawiamy, bo np. magia ziemii itp. To tez taka dostepnosc, konto?

Skarbiec, czy Phli Targ - czy znalezione zasoby czy coś innego - nowego, nagroda (“od papieża”). To nie ma znaczenia. Tak samo jak Twoje konto w banku nie wie o wszystkich możliwościach zarobków. Tylko masz wpływy i wydatki. Zarządca skarbca też nie ma o tym pojęcia. Możnaby nazwać takiego managera zarządcą właśnie, który jak to się stanie spisuje.

BONUS: Instrukcja instalacji Heroes III na MacOS

Gra przez internet

Czasy kiedy spotykamy sie juz bezpowrtonie minely. Teraz kazdy siedzi w swoim domowym zaciszu.

Inne tytuly:

  • ‘⚔️ Bounded Contexty w świecie Heroes III’
  • ’+ BONUS: Instrukcja instalacji na MacOS’ - osobno title: ‘⚔️ Moc i magia Bounded Contextów w świecie Heroes III | Praktyczne modelowanie DDD’ title: ‘⚔️ Moc i magia DDD w świecie Heroes III: Praktyczne modelowanie Bounded Contextów’

⚔️ Moc i magia DDD w świecie Heroes III: Wataha/Horda Bounded Contextów

Fajne grafiki: https://nextulu.github.io/homm3-cheat-sheet/

Generator wiadomosci Heroes III: https://lehazyo.github.io/homm3-messages/

https://heroes3tools.netlify.app/

statsy z saveów: https://github.com/oysteinmyrmo/homm3tools

Gdy ktos probuje wielki Models: https://github.com/Sajjon/Makt/tree/main/Sources/Malm/Models

Magie itp obrazki: https://github.com/Shemplo/Middle-Earth-RMG

Parafraza z Learning DDD:

Jesli wezmiemy model Jednostki z mapy, bedzie on zbyt prosty i nie spelni wymagan, w druga strone wprowadzimy niepotrzebne skomplikowanie. Taka amibiguty nie jest problemem kiedy gracze siedza przy komputerze. Pojecie Jednostki nie jest spojne, mowiac tak mamy co innego na mysli. Jak sobie z tym poradzic? Tradycyjnie robili Kanoniczny Model Danych. Taki model mial wszystko ogarniac, ale w rzeczywistosci nie nadawał się do niczego.

refix mozna MapCreature / BattleCreature Zwieksza nam obciazenie poznawsze I sprawia, ze skoro te modele istnieja obok siebie ,to mozna je uzyc w zlym kontekscie. I dodatkowo - taka implementacja nie bedzie sie pokrywac z jezykiem biznesu. Nikt tak nie mowi. Ludzie nie potrzebuja czegos takiego, bo polegaja wlasnie na kontekscie rozmowy.

Rozwiazanie Ubquiquitous Languagae: podzielenie na mniejsze jezyki, i okreslenie kazdemu z nich kontekstu, w jakim moze byc uzywany. Kontekst Ograniczony po polsku.

Model to nie kopia realnego świata. Przykład z samochodami czy mapami. Model jest robiony w konkretnym celu, żeby rozwiazac problem. Nie moze istniec bez granic, bo bedzie probowal ozwierciedlac realny swiat. Model nie moze istniec bez problemu, a Jezyk Wszechobecny bez okreslonego kontekstu, w ktorym bedzie aplikowany. Dlatego nie ma po co tworzyc sztucznie bytów.

Model nie musi byc maly/duzy - musi byc uzyteczny. Im wiekszy, tym ciezej zapewnic spojnosc. Patrz na to co sie zmienia przy podziale. Nie moze byc tak, ze . Znajdz spojne use case, ktore dzialaja na tych samych danych, zeby uniknac dekompozycji w zbyt male.

Takie modele, np. projektowanie kuchni do mojego mieszkania. Otrzymalem wizualizacje, aby sobie wyobrazic,ale tez projekt z dokładnymi wymiarami. To były 2 różne reprezentacje, tego samego w rzeczywistosci.

Podziel się wpisem:

✉️ Lista Mailingowa

Zostaw swój adres e-mail i zobacz moje spojrzenie na codzienność programisty. Możesz liczyć na materiały o Event Sourcingu, Event Modelingu, Domain-Driven Design, programowaniu obiektowym i funkcyjnym oraz innych powiązanych tematach.

🫱🏻‍🫲🏽 Mentoring Online

Nauka Domain-Driven Design? Podział projektu na moduły? Zaplanowanie architektury? Konsultacja CV? A może rozwój w kierunku Seniora? Spotkajmy się! Umów się na mentoring lub konsultacje. Wspólnie opracujemy plan dla Ciebie 🫵

📖 SOLIDne CV?

🤔 Masz wymagane kompetencje, ale nikt nie daje Ci szansy ich zaprezentować?!

CV na kodach

💪 Przeprowadziłem ponad 100 rozmów rekrutacyjnych i widziałem tysiące CV. Nieraz miałem okazję porównać CV odrzucane, z tymi które robiły największe wrażenie. Na tej podstawie opracowałem porady, które pomogą Ci przejść ten etap rekrutacji.

Mailing Domain-Driven Design

Wciąż za mało życiowych cheatów?

Zostaw swój adres e-mail i zobacz moje spojrzenie na codzienność programisty.

Na sam początek opowiem Ci o zetknięciu z Domain-Driven Design, zmianie myślenia i nowej erze mojego programistycznego ja.

Możesz liczyć na materiały o Event Sourcingu, Event Modelingu, DDD, programowaniu obiektowym i funkcyjnym oraz innych powiązanych tematach.

Na pewno poświęcę trochę maili umiejętnością miękkim.

Będziesz też informowany o nowościach Życia na kodach prosto na Twoją skrzynkę!