środa, 17 września 2025

A teraz z innej beczki

Ostatnio u nas w firmie pojawił się temat technicznego retro, zgłosiłem się na ochotnika, cóż w końcu trzeba się nauczyć występować.

Prezentowałem nietypowe podejście do pewnej funkcjonalności w naszym systemie. Nie będę tu zagłębiał się w szczegóły, ale w dużym skrócie, chodziło o relacje i podejście rekordowe w bazie danych. Było też trochę o normalizacji.

Pomyślałem, że to dobry pretekst do napisania jakiegoś krótkiego posta. Przez te kilka lat wyszedłem z wprawy. W między czasie szykuje się model z poprzedniego posta o DDD.

Do brzegu

Nie sposób przy tej okazji nie wspomnieć o tym, że podobny problem, opierający się na rozwiązaniu z wieloma kolumnami miałem w aplikacji do zarządzania maratonem rowerowym. Ten problem mogę tu przybliżyć, koncept jest podobny (zresztą na tym blogu kilka lat temu już o nim pisałem).

Problem

W aplikacji do maratonu rowerowego jedna z funkcjonalności, właściwie główna opierała się na pomiarze czasu, pomiarze czasu zawodników. Zawodnicy mieli karty RFID i odbijali się na poszczególnych checkpointach na 100 km-etrowych pętlach. 

Ilość checkpointów była zależna od dystansu na który zawodnik się zapisał, dystansów było kilka jak zaczynałem to były 100, 200, 300, 400, 500, 600 i 650 km, w kolejnych edycjach doszedł dystans 50 i 700. Zawodnicy startowali o różnych porach tak żeby zmieścić się w 24h, zapomniałem wspomnieć że to był maraton 24 godzinny.

Rozwiązanie - pierwsze

Jak to wtedy zamodelowałem?

Jako, że jestem fanem (mam nadzieje że już nie długo) techniki rozpoczęcia projektowania od stworzenia bazy, to zacząłem od zbudowania tabeli, która pozwoli mi na prosty i łatwy dostęp do czasu danego zawodnika. Oczywistym było zrobienie tabeli, która ma ilość kolumn równą ilości checkpointów, maksymalnej ilości checkpointów.

Problemy napotkałem w drugiej edycji, dotyczące tego rozwiązania, jeżeli ktoś się odbił dwa razy to drugi czas przechodził do kolejnego checkpointa - kolumny, jak ktoś zapomniał to znowu brakowało czasu. W tym miejscu trzeba nadmienić, że np dla jednego dystansu mieliśmy trzy checkpointy jak jednego brakło odbicia to mieliśmy przekłamanie.

Kolejny problem jest bardziej złożony, w którejś edycji dołożyliśmy checkpoint w takim modelu kolumnowym dołożenie kolejnych kolumn wiąże się ze zmianą modelu w backendzie i masą "logiku", szczególnie, że w pierwszych edycjach nie używałem entity frameworka a czystego ADO. Dodanie kolejnych wpisów musiało trafić w odpowiednią kolumnę, co też sprawiało problem.

Więcej problemów nie pamiętam.

Link do posta opisującego te rozwiązanie

Rozwiązanie - drugie, właściwe

W ostatniej edycji maratonu 2018/2019, maraton zaczynał się we wrześniu 2018 a konczył w czerwcu 2019, wpadłem na lepszy pomysł.

Tabela rekordowa zamiast kolumnowej, prosta zmiana dojście do tego zajeło mi 5 lat (pięć edycji).

Taka tabela jest znacznie prostrza, nie ma tyle kolumn, a cała logika zapisu polega na wierszach w takiej formie nie potrzebujemy kolumn na kolejne checkpointy, bo wystarczy nam jedna kolumna prezentująca czas.

Rozwiązanie jest zaprezentowane w w tym poście. Jakie są jeszcze zalety?

Przy takiej formie tabeli, nie muszę dbać o czasy pośrednie, bo tak naprawdę liczy się dla mnie tylko czas pierwszy i ostatni ich różnica da mi czas który jest tak naprawdę istotny czyli czas przejazdu całego dystansu. Owszem mogę liczyć checkpointy i odbicia ale czy ich będzie 1 czy 10 nie ma to różnicy w tym podejściu. Samo wyliczanie przejechanych checkpointów odbywa się po stronie aplikacji. Ilość checkpointów nie gra roli.

Wnioski

Warto czasem rozważyć, czy tabela kolumnowa w dłuższej perspektywie czasu będzie dobrym rozwiązaniem? Czy przyniesie więcej korzyści przekształcenie jej w tabele wierszową?

To też w dużej mierze zależy od problemu, w aplikacji z maratonu rowerowego, pomiar czasu i związane z tym problemy przy rozwiązaniu kolumnowym otworzyły mnie na głębsze zastanawianie się nad zastosowaniem właśnie podejścia rekordowego, co też teraz często stosuje.

Ale rozwiązanie wierszowe jest trudniejsze na start, opiera się też między innymi o relacje.

Przykład inny, spotykam się często zrobieniem list danych, ograniczonych zbiorów na kolumnach tabeli co jest dla mnie sygnałem że takie rozwiązanie może się szybko zemścić, gdy nagle się okaże że listę danych trzeba rozszerzyć.

A co do wpisywania list do tabel rekordowych? Dla mnie jest to oczywiste ale wiąże się z tym ze daną tabele z taką listą trzeba wpiąć przez relacje do głównej tabeli która tę listę zawiera, potrzebuje.

Jeżeli mamy relacje to przy zapytaniu potrzebujemy joina, co wpływa na wydajność, rozwiązanie kolumnowe jest szybsze, nie ma joina (chyba że są setki kolumn).

Kolejna "słabość", to transakcje. Bardzo możliwe że będziemy potrzebowali użycia transakcji do obsłużenia wielu tabel wchodzących w skład tabeli głównej.

Czy to jest zawsze opłacalne? To pytanie jest otwarte, warto sobie je zadać przy projektowaniu i podejmowaniu decyzji, bo za niewłaściwe zapłata przychodzi często z opóźnieniem.


Nowe otwarcie - powrót po latach

 Nowy początek - przemyślenia


Ponad cztery lata po stworzeniu event stormingu na temat aplikacji "Maraton Rowerowy" (kawałek event stormingu plus kod) i sześć lat po zakończeniu ostatniej edycji (kod do ostatniej edycji), postanowiłem wrócić do tego tematu.

Zachęciła mnie do tego chęć przybliżenia sobie wzorca Domain Model. Być może powinienem go znać, gdyż ES z maratonu powstał na bazie szkolenia DNA gdzie wałkowane było DDD, ale wtedy nie zrozumiałem dobrze tego wzorca. Kod napisany po poprzednich częściach DNA był no cóż kiepski.

Po pięciu latach zrozumiałem że sercem DDD jest model i stąd ten pomysł żeby w końcu spróbować za modelować, porządnie, jakiś kontekst z maratonu. 

Każda firma w której pracowałem, miało jakieś legacy, projekty, które uczą jak nie programować, do których nie wchodzi się z uśmiechem na twarzy, a bardziej z trwogą. Czasami sam robiłem takie legacy i zostawiałem w odmętach danej firmy, tak było jak pracowałem na kopalni. 

Jeżeli chce innego wyniku to nie mogę nonstop rozwiązywać problemu w taki sam sposób. 

W obecnej firmie,  też mamy legacy system, ale zmieniło się coś we mnie zacząłem dostrzegać w nim potencjał, ma on swoje ciemne strony, ale ma też spore pole do refaktoringu, zrozumienia naszego biznesu. Legacy to nie tylko problem ale to część czyjeś historii, zestaw decyzji, które zaważyły na aktualnym stanie. Czas pokazuje, że nie wszystkie były trafne ale czy to powód do krytyki? nie sądzę.

Wróciłem do książki  Praca z zastanym kodem, sięgnąłem również po książkę Martina Fowlera, dotyczącą refaktozyzacji, mam też szkolenie Legacy Fighter i w tym ostatnim droga prowadzi z legacy do DDD.

Nie mogłem też w moim zestawieniu pominąć Andrzeja Krzywdy występującego w podcaście Better Software Desing mówiącym o refaktoryzacji. Te lektury, sprawiły że legacy zacząłem widzieć w innym świetle, legacy stało się wyzwaniem nie tylko problemem.

Świat związany z programowaniem zmienia się tak szybko, nie nadążam już, jestem człowiekiem po czterdziestce, czasami potrzebuje czegoś stabilnego, czegoś czemu mogę zaufać, czegoś niezmiennego.

Są takie rzeczy od lat stałe, choćby normalizacja baz danych, koncept z przed półwieku, taki stary to każdy go pewno zna i rozumie. Nic bardziej mylnego. DDD, przecież to ma z 20 lat, kogo się nie spytasz to zna DDD i jeszcze w tym pracuje, a jak zgłębisz temat to jest tak samo jak z normalizacją.

Może nie trzeba szukać nowych frameworków, może wystarczy zrozumieć te stare, wciąż aktualne koncepty? zrozumieć i używać, ale używać tam gdzie to jest potrzebne.

Ostatnia rzecz, która wydaje się niezmienna od lat, to potrzeby klienta, użytkownika, biznesu i zrozumienie tego, zrozumienie ich.

Krótka historia.

Pisałem aplikacje do obsługi maratonu rowerowego w latach 2013 - 2019. Co roku tworzyłem na nowo, uczyłem się na tym, nie było jeszcze AI, który by mi wygenerował kod, może coś by wymyślił, podpowiedział, poprawił. Jak kończyłem ostatnią edycje pojawił się temat event stormingu, zachwyciło mnie te podejście, to była końcówka roku 2018, jeździłem wtedy jeszcze na meetup-y, zobaczyłem ES i spodobało mi się. Odkryłem narzędzie którego mi brakowało, sposób na zrozumienie, dogadanie się z drugą stroną.

Dlatego poszedłem na DNA?, bo był event storming, reszta mnie nie interesowała, w między czasie przeczytałem DDD Erica Evansa (strasznie nudna książka). 

Rok temu zacząłem, na nowo odkrywać DDD, wracać do ES, wydaje mi się że musiało minąć 5 lat żeby coś zrozumieć, coś wykiełkowało, doszło do mnie. Do książki Erica Evansa też wróciłem, już nie jest nudna.

Ale ta droga nie była taka jak sobie ją na początku wymarzyłem, po kilku próbach z kolegami, po których pozostały :

Przyszedł czas na test w boju, dostałem zadanie napisania aplikacji do zarządzania przedsiębiorstwem produkującym, wynajmującym i sprzedającym automaty do gier. Żeby zrozumieć proces i kontekst, zaproponowałem event storming. Spotykaliśmy się przez dwa miesiące, bo to był projekt który robiłem po pracy, zaczęło się i skończyło na ES-ie. Po analizie trzeba było zrobić wycenę, poszło o kasę, ale robiąc event storming już wiedziałem że nie dam rady tego "wyklepać", miałem za małe doświadczenie, umiejętności.
Teraz jak bym dostał takie zadanie, nie próbował bym go zrobić, raczej spróbował bym co się da oddelegować na gotowe narzędzia i zaproponować integracje, a kodzić jak najmniej. Mądry ten kto napisał że "najlepszy kod to taki który nie istnieje".

Te doświadczenia spowodowały  u mnie odejście od event stormingu, skupienie się nad poprawą warsztatu. Nie da się jednak uciec od problemów, od legacy. Można narzekać na taki kod ale to on często przynosi największą wartość firmie. To on ma największy potencjał do zmiany, niełatwej ale możliwej, to tu można się najwięcej nauczyć.

Dlaczego powrót do Event Stormingu? Dzięki nie mu mogę lepiej zrozumieć proces, odkryć reguły, znaleźć granicę, ale jest coś ważniejszego. Ta druga strona, biznes, może współtworzyć  to, może być częścią tego procesu wyklejania karteczek i może go rozumieć. Tekst wszystkiego nie ogarnie, nie w taki sposób jak tablica na Miro, gdzie będę mógł widzieć cały proces i powiększyć sobie kawałek z niego, przejść przez "Happy patha" ale też wyznaczyć ścieżki mniej oczywiste. Nie będzie potopu słów którego nie jestem w stanie szybko ogarnąć bez robienia sobie dodatkowych notatek.

Zdobywanie wiedzy od biznesu i tak polega na rozmowie tylko zamiast "excela", dostaje borda z karteczkami.

Plan

Post ten powstał żeby na nowo zrozumieć DDD, wzorzec domain model i sam event storming ale w tej kolejności. Głównym zadaniem będzie nauczyć się modelować i w tym pomocny będzie temat "Maratonu rowerowego", oraz event stormingu który został dla nie go stworzony. To ułatwi mi następujące etapy:

  • rozpisać jeden lub dwa konteksty odkryte na event stormingu z maratonu rowerowego,
  • rozpisać scenariusze w obrębie wybranego kontekstu, coś takiego jest w rozdziale o budowaniu agregatów w książce Erica Evansa o DDD,
  • na koniec chce spróbować to zamodelować w kodzie 
To co robiłem do tej pory opierało się o modele anemiczne nawet jak logika byłą większa, potrzebowałem kolejnego roku żeby to zrozumieć, żeby nie bać się modelu, to tam ma być logika nie gdzie indziej.

Pozostała też kwestia, że w mojej pracy starałem się promować model anemiczny, co było błędem z mojej strony, ktoś by mógł zadać pytanie przecież zrobiłeś kurs DNA, czytałeś Evansa, słuchałeś podcastów, czytałeś artykuły, to gdzie to wszystko się podziało?
Dobre pytanie, może tak naprawę nigdy nie rozumiałem? Może potrzebowałem czasu żeby dostrzec te rozwiązaniem bo nie zawsze DDD jest słuszne czasami model anemiczny pasuje, relacje w bazie są właściwe a czasami, potrzebuje tabel bez relacji albo bazy nierelacyjnej.
Wydaje mi się że w moim przypadku to czas, problemy, kod, coraz częstsze pytania i wątpliwości z powrotem doprowadziły mnie do tego miejsca.




A teraz z innej beczki

Ostatnio u nas w firmie pojawił się temat technicznego retro, zgłosiłem się na ochotnika, cóż w końcu trzeba się nauczyć występować. Prezent...