Jak czytać to kompendium
mechanizmy, nie definicje do wkuciaTo nie jest katalog klas do przepisania. Każdy rozdział pokazuje jeden mechanizm: jakie zdania w wymaganiach go zdradzają, jak wygląda jego szkielet, jakie ma konfiguracje i gdzie łatwo się wyłożyć. Prawie każdy rozdział ma diagram, który możesz klikać. Ma też przycisk 💥, który psuje model w typowy sposób, żebyś zobaczył skutki.
Podstawą jest szkolenie Archetypy Oprogramowania (Bartłomiej Słota, Jakub Pilimon, Sławomir Sobótka) i jego publiczne repozytorium kodu. Szkolenie traktuje archetypy jako uzupełnienie DDD i architektury. Do tego dochodzi literatura: Arlow i Neustadt Enterprise Patterns and MDA, Fowler Analysis Patterns, Coad Java Modeling in Color with UML, Evans Domain-Driven Design i Silverston The Data Model Resource Book. Nazwy klas w tekście (np. PartyRelationship) pochodzą z repozytorium szkolenia. Kodu z repozytorium nie kopiujemy: jest na licencji CC BY-NC-SA 4.0.
Kompendium ma poziomy. Rozdziały i bloki mają znaczki: L1 podstawy, L2 praktyk, L3 ekspert, L4 mistrz (studia przypadków i antywzorce). Głębokość wybierasz przełącznikiem w lewym dolnym rogu. Mapa poniżej przenosi do dowolnego rozdziału i zaznacza przeczytane.
Zaczynasz od zera? Ustaw głębokość 1 i przeczytaj najpierw Część 0. Wyjaśnia, czym są archetypy, jak z nich korzystać krok po kroku i od którego zacząć. Potem w każdym rozdziale archetypu czytaj w tej kolejności: blok 🔰 „Co to jest”, schemat anatomii, „Kiedy stosować, a kiedy nie”, tabelę opcji i „Minimum na start”. Dopiero po nich przychodzą przykłady z repozytorium, nazwy klas i bloki eksperckie. Głębokość zwiększysz, gdy podstawy przestaną zaskakiwać.
Kolory archetypów są stałe w całym tekście: QuantityPartyProductPricingRulesInventoryOrderingAccountingSchedulingPlan vs Execution
Kierowca firmy kurierskiej tankuje na stacji. Płaci kartą flotową wydaną przez firmę leasingową. Firma leasingowa obciąża potem kuriera, a on obciąża swojego klienta za paliwo w cenie usługi. Ilu „klientów” jest w tej historii i ile różnych modeli danych potrzebujesz, żeby ją obsłużyć? Zapamiętaj swoją odpowiedź. Wrócimy do niej na końcu.
Start: archetypy od zera
Dla osób, które słyszą o archetypach pierwszy raz. Czym są, jak z nich korzystać krok po kroku, gdzie siedzą w kodzie i od którego zacząć.
Archetyp w 5 minut
ten sam problem rozwiązany raz, porządnieW typowej firmie Jan Kowalski istnieje trzy razy. Dział sprzedaży ma go w CRM jako „klienta”. Księgowość ma go w programie do faktur jako „kontrahenta”. Sklep internetowy ma go jako „użytkownika”. Każdy z tych systemów zbudował inny zespół, w innym roku, z innym modelem danych. Działa to do pierwszej przeprowadzki Jana.
Problem nie polega na tym, że ktoś źle napisał kod. Polega na tym, że każdy zespół od nowa wymyślił pojęcie, które ludzkość dawno opisała. „Ktoś, kto występuje w różnych rolach” to stary, dobrze poznany problem. Tak samo „rzecz z katalogu kontra konkretny egzemplarz”, „cena zależna od warunków” albo „saldo, które musi się zgadzać”.
Archetyp to gotowy, sprawdzony szkielet modelu dla takiego powtarzalnego pojęcia. Mówi, z jakich części pojęcie się składa, które części są obowiązkowe, które opcjonalne i jakie pytania zadać biznesowi, żeby dobrać wariant. Najbliższa analogia z kuchni to przepis bazowy, np. ciasto drożdżowe. Mąka, drożdże i wyrastanie są zawsze. Kruszonka, śliwki albo ser to warianty. Nie wymyślasz ciasta od zera dla każdej okazji. Bierzesz przepis i dobierasz dodatki do gości.
Słowniczek startowy
Te dziesięć pojęć wraca w każdym rozdziale. Wystarczy je rozumieć intuicyjnie. Dokładne definicje są w rozdziałach i w słowniku.
- Archetyp to sprawdzony szkielet modelu dla pojęcia, które powtarza się w prawie każdym biznesie.
- Ma części obowiązkowe i opcjonalne. Opcje dobierasz do wymagań, jak dodatki do przepisu bazowego.
- Rozwiązuje trzy problemy: wymyślanie od nowa, ifologię i brak historii.
- Zaczynasz od dwóch, trzech archetypów w wersji minimalnej.
Jak korzystać z archetypów: proces w 5 krokach
od zdania w wymaganiach do modeluArchetypy nie są listą klas do skopiowania. Są narzędziem do czytania wymagań. Ten sam proces działa dla sklepu, banku i szpitala. Przejdziemy go na jednym przykładzie: wypożyczalni rowerów miejskich.
- Wypisz wymagania jako zdania. Rozmawiaj z biznesem i zapisuj pełne zdania z liczbami i wyjątkami: „pierwsze 20 minut za darmo, potem…”, a nie hasła w rodzaju „cennik”.
- Znajdź sygnały. W każdym zdaniu zaznacz frazę, która coś zdradza: „osoba albo firma” (role), „numer ramy” (egzemplarz), „zarezerwować na 15 minut” (blokada z czasem), „saldo” (konto). Ściąga sygnałów jest w rozdziale Jak rozpoznać archetyp.
- Dobierz konfigurację. Każdy archetyp ma opcje. Rower to egzemplarz śledzony indywidualnie, a nie „5 sztuk na stanie”. Stacja to pula stojaków. Opcje każdego archetypu znajdziesz w jego tabeli „Opcje i konfiguracje”.
- Połącz archetypy. Archetypy rozmawiają przez identyfikatory (przejazd zna identyfikator roweru), migawki (przejazd pamięta dane użytkownika z chwili startu) i zdarzenia („przejazd zakończony” uruchamia opłatę). Nigdy przez wspólne tabele.
- Zacznij od minimum. Zbuduj najprostszą wersję, która obsłuży dzisiejsze zdania. Opcje dokładaj, gdy pojawi się nowe zdanie, które ich wymaga. Na koniec sprawdź model z biznesem na konkretnych scenariuszach: „klient rezerwuje, rezygnuje po minucie, ile płaci?”.
| Krok | Pytanie kontrolne | Sygnał, że trzeba wrócić |
|---|---|---|
| 1. Zdania | Czy każde wymaganie ma czasownik i przykład z liczbami? | Na liście są same rzeczowniki: „klient”, „cennik”, „rezerwacja”. |
| 2. Sygnały | Czy każde zdanie ma przypisany co najmniej jeden archetyp? | Zdanie „nie pasuje nigdzie”. Często to proces albo raport, a nie nowe pojęcie. |
| 3. Konfiguracja | Czy przy każdej opcji jest zdanie z wymagań, które jej potrzebuje? | Opcja jest w modelu „bo może się przyda”. |
| 4. Połączenia | Czy archetypy łączą tylko identyfikatory, migawki i zdarzenia? | Jeden moduł czyta tabele drugiego albo trzyma referencję do jego obiektu. |
| 5. Minimum | Czy da się to zbudować w kilka dni i sprawdzić na scenariuszach? | Pierwsza wersja ma wszystkie opcje wszystkich archetypów. |
Najczęstszy błąd początkujących to zrobienie klasy z każdego rzeczownika w wymaganiach. Powstają wtedy Uzytkownik i UzytkownikFirmowy, Rower i RowerElektryczny, Cennik i CennikAbonamentowy. Każda para to ten sam archetyp w innym kostiumie, a różnica między nimi powinna być daną (rolą, typem, wersją), a nie klasą.
Siłownia: „Karnet miesięczny kosztuje 150 zł, studenci płacą 120 zł. Zajęcia grupowe mają 12 miejsc i zapisuje się na nie w aplikacji. Trener prowadzi zajęcia tylko z ważnym certyfikatem. Niewykorzystane wejścia z karnetu 10-wejściowego wygasają po 3 miesiącach.” Przejdź kroki 2–4.
Odpowiedź
Sygnały: „studenci” to rola klienta (Party) i warunek reguły ceny (Pricing lub Rules). „12 miejsc i zapisuje się” to Inventory: zajęcia w danym terminie jako pula o pojemności 12. „Ważny certyfikat” to kompetencja z okresem ważności w Party. „Wejścia wygasają po 3 miesiącach” to Accounting: konto wejść z ważnością zapisu i transakcją kompensującą. Połączenia: zapis na zajęcia zna identyfikator klienta i zajęć, a wejście na salę to zdarzenie, które zdejmuje jedno wejście z konta.
- Pięć kroków: zdania, sygnały, konfiguracja, połączenia, minimum.
- Sygnałem są frazy z liczbami, czasem i wyjątkami, a nie same rzeczowniki.
- Archetypy łączą się przez identyfikatory, migawki i zdarzenia.
- Pierwsza wersja ma tylko te opcje, których wymagają dzisiejsze zdania.
Gdzie archetyp siedzi w kodzie i architekturze
moduł z jedną fasadąW kodzie archetyp to najczęściej osobny moduł: pakiet, biblioteka albo usługa z jednym wejściem (fasadą). W środku jest model archetypu, polityki, które zmienia biznes, i repozytorium do zapisu. Na zewnątrz wychodzą tylko identyfikatory, widoki i zdarzenia. Repozytorium szkolenia jest zbudowane właśnie tak: każdy archetyp to osobny moduł Maven (party, product, pricing, inventory, ordering, accounting i inne).
Co jest kodem, a co daną
| Kod (zmienia programista) | Dane (zmienia biznes, z wersją) |
|---|---|
| szkielet: Party ma role, transakcja sumuje się do zera | jakie role i relacje istnieją i kto może je mieć |
| rodzaje kalkulatorów ceny | parametry kalkulatorów: progi, stawki, okresy ważności |
| rodzaje reguł wyboru i warunków | konkretne pakiety, promocje i ich kolejność |
| mechanizm blokad i kolejek | czas trwania blokady, polityka kolejki, pojemności |
| mechanizm reguł księgowania | konkretne reguły: kiedy naliczyć prowizję, podatek, bonus |
Ta granica to poziom wiedzy (opisany szerzej w rozdziale Poziom wiedzy): typy i reguły są danymi, a kod zna tylko mechanizm. Nie przesadzaj jednak w drugą stronę. Jeśli wariant zmienia się raz na dwa lata, stała w kodzie jest tańsza niż ekran konfiguracji.
- Archetyp to moduł: fasada, model, polityki, repozytorium, zdarzenia.
- Szkielet jest kodem. Warianty biznesu są danymi z wersją.
- Moduły wymieniają identyfikatory, migawki i zdarzenia, a nie tabele.
Dziesięć archetypów w pigułce
jedna karta na archetypKażda karta odpowiada na cztery pytania: czym archetyp jest, z czego się składa, po jakim zdaniu go poznać i jakie ma główne opcje. Szczegóły są w rozdziale, do którego prowadzi link.
Liczba zawsze razem z jednostką albo walutą.
Częściwartość, jednostka lub waluta, operacje sprawdzające jednostki
Sygnał„litry”, „kWh”, „w euro”, „podziel na raty”
Opcjekonwersje jednostek, polityka zaokrągleń, alokacja kwot, procenty
Rozdział →Osoba albo organizacja, która występuje w wielu rolach.
Częściosoba lub organizacja, role, identyfikatory, adresy, relacje
Sygnał„ten sam klient jest też dostawcą”, „kto był pełnomocnikiem w marcu?”
Opcjepolityki ról i identyfikatorów, relacje z ważnością, kompetencje
Rozdział →Co sprzedajesz: typ z katalogu i konkretny egzemplarz.
Częścityp, egzemplarz, cechy, wpis w katalogu, strategia śledzenia
Sygnał„numer seryjny”, „partia”, „wariant”, „pakiet”, „wycofany z oferty”
Opcjepięć strategii śledzenia, partie, pakiety z regułami, relacje produktów
Rozdział →Cena jako drzewo składników, z których każdy liczy osobny kalkulator.
Częścikalkulator, komponent, zależności, rozbicie ceny, wersje
Sygnał„cena zależy od…”, „pierwsze 5 GB w cenie”, „ile kosztowało w lutym?”
Opcje8 kalkulatorów, 3 interpretacje ceny, wersje z ważnością
Rozdział →Wyjątki i promocje jako dane: kiedy działają, co robią i czego nie wolno.
Częściwarunek (predykat), zmiana (aplikator), strażnik, łańcuch
Sygnał„chyba że”, „dla VIP −10%”, „promocje się (nie) łączą”
Opcjeprocent od bazy lub od wyniku, kwota, cena stała, strażnik marży, algebry
Rozdział →Co jest dostępne, ile i kto to zablokował.
Częścizasób, model dostępności, blokada z właścicielem, rezerwacja
Sygnał„czy jest wolne?”, „zarezerwuj”, „lista oczekujących”
Opcjeegzemplarz, pula, slot czasu, grupy slotów, zasób złożony, kolejki
Rozdział →Zlecenie: kto zamawia, co, za ile i w jakim jest stanie.
Częścistrony z rolami, linie, wycena linii, stany, porty do innych modułów
Sygnał„zamawia dział, płaci spółka, odbiera oddział”, „status zamówienia”
Opcjerole na zamówieniu i liniach, stany wyceny, migawki, kompensacje
Rozdział →Saldo jako suma niezmiennych zapisów, a każda operacja się bilansuje.
Częścikonto, zapis, transakcja, reguła księgowania
Sygnał„saldo”, „limit”, „punkty”, „portfel”, „na dzień”
Opcjetypy kont, reguły księgowania, dwa zegary, ważność zapisów, korekty
Rozdział →Harmonogram jako graf zależności, z którego wynikają daty.
Częścikroki, zależności, czasy trwania, porządek, ścieżka krytyczna
Sygnał„nie wcześniej niż”, „po zakończeniu”, „co się opóźni, jeśli…”
Opcjetypy zależności (w repozytorium gotowy jest FS; SS/FF/SF i zwłoka to rozszerzenia), wykrywanie cykli, algorytmy grafowe
Rozdział →Plan zapisany jako osobny byt i porównywany z faktami jawnymi regułami.
Częściplan z wersjami, wykonanie, tolerancja, delta
Sygnał„planowaliśmy, a wyszło”, „harmonogram rat a wpłaty”
Opcjestrategie tolerancji, rozdzielczość porównania, symulacje „co jeśli”
Rozdział →- Kto: Party. Co: Product. Ile: Quantity, Pricing, Rules. Czy wolne: Inventory.
- Zlecenie: Ordering. Saldo: Accounting. Kolejność: Scheduling. Zamiar kontra fakt: Plan vs Execution.
Mapa decyzji na start
dziesięć pytań, Twoja ścieżka czytaniaNie musisz czytać wszystkiego. Zaznacz pytania, na które w Twoim projekcie odpowiedź brzmi „tak”. Dostaniesz listę rozdziałów do przeczytania najpierw. Pełne drzewo decyzyjne z konfiguracjami jest na końcu kompendium, w rozdziale Drzewo decyzyjne.
Jedno albo dwa zaznaczone pytania to dobry znak: masz mały, czytelny start. Kolejne archetypy przyjdą same, razem z nowymi zdaniami w wymaganiach. Dalej czytaj Część I, która uczy rozpoznawać archetypy w tekście wymagań.
Myślenie archetypami
Czym archetyp różni się od wzorca projektowego, po czym go poznać w wymaganiach i jak archetypy łączą się w system.
Czym jest archetyp
ten sam szkielet, inny kostiumKredyt hipoteczny, przesyłka kurierska i sesja ładowania auta elektrycznego wyglądają jak trzy różne światy. Każdy ma jednak kogoś, kto kupuje, coś, co jest sprzedawane, cenę zależną od parametrów i zobowiązanie rozliczane w czasie. Pod kostiumem branży jest ten sam szkielet. Archetyp to nazwa takiego szkieletu razem z wiedzą, jak go zbudować.
Arlow i Neustadt definiują business archetype jako „primordial thing that occurs consistently and universally in business domains and business software systems”, czyli pierwotną rzecz, która występuje stale i powszechnie w dziedzinach biznesowych i w systemach, które je obsługują. Ich przykładem jest Party: identyfikowalna, adresowalna jednostka, która może mieć status prawny. Zwykle to osoba albo jakaś organizacja. Gdy archetypy współpracują w powtarzalny sposób, mamy archetype pattern. Według autorów współpraca Party, Product i Order jest podstawą niemal każdego biznesu, który sprzedaje towary lub usługi.
Archetyp nie jest wzorcem projektowym w sensie Gang of Four. Wzorzec GoF porządkuje kod: jak obiekty tworzą się, składają i komunikują. Archetyp porządkuje pojęcia biznesowe: jakie są, jakie mają cechy i reguły oraz jak zmieniają się w czasie. W podsumowaniu transmisji o archetypach na devstyle.pl pada porównanie: wzorce projektowe są jak wzory skróconego mnożenia, a archetypy jak prawa fizyki, bo działają tak samo niezależnie od specyfiki biznesu. Ten sam tekst opisuje je jako „wieloaspektowe wzorce modelowania łączące funkcje, logikę i strukturę informacji”.
Wcześniej, w 1999 roku, Peter Coad, Eric Lefebvre i Jeff De Luca opisali w Java Modeling in Color with UML cztery bardzo ogólne archetypy oznaczane kolorami. Różowy to moment-interval: coś, co dzieje się w chwili lub przez okres i co trzeba śledzić z powodów biznesowych lub prawnych, np. sprzedaż lub wynajem. Żółty to role, czyli sposób uczestnictwa osoby, miejsca lub rzeczy. Niebieski to description, opis katalogowy, np. marka i model auta opisujące wiele fizycznych pojazdów. Zielony to party, place or thing: coś namacalnego i jednoznacznie identyfikowalnego. Klasyfikując klasę, pyta się po kolei: różowa? żółta? niebieska? Jeśli żadna, to zielona.
Arlow i Neustadt zauważają, że archetypy Coada są na dużo wyższym poziomie abstrakcji. Mimo to warto je znać. „Niebieski” opis to zalążek poziomu wiedzy, a „różowy” moment-interval to szkielet zamówień, rezerwacji i zapisów księgowych.
Wypożyczalnia rowerów miejskich: użytkownik aplikacji, firma sponsorująca stacje, rower o numerze ramy, stacja dokująca z 20 miejscami, cennik „pierwsze 20 minut za darmo”, przejazd. Przypisz każde pojęcie do archetypu.
Odpowiedź
Użytkownik i sponsor to Party (osoba i organizacja w różnych rolach). Rower z numerem ramy to egzemplarz Product śledzony indywidualnie. Stacja z 20 miejscami to Inventory typu pula. Cennik to Pricing z kalkulatorem progowym po czasie. Przejazd to Ordering (zlecenie z cyklem życia) i źródło zapisów w Accounting.
- Archetyp to powtarzalny szkielet pojęcia biznesowego razem ze sprawdzonym sposobem modelowania.
- Wzorzec archetypów to powtarzalna współpraca archetypów (Party + Product + Order).
- Archetyp ma części opcjonalne i warianty (pleomorfy). To przepis, a nie biblioteka.
- DDD wyznacza granice i język, a archetyp podpowiada treść modelu w tych granicach.
Jak rozpoznać archetyp w wymaganiach
czasowniki i pytania, nie rzeczownikiKlasyczna rada „podkreśl rzeczowniki, to będą klasy” prowadzi prosto do klas Kierowca, Firma, Klient i Pracownik, które po roku mają po 80% wspólnych pól. Archetyp zdradza się inaczej: przez zachowanie w czasie i przez pytania, których biznes jeszcze nie zadał, ale zada.
| Sygnał w rozmowie lub w kodzie | Podejrzany archetyp | Pytanie kontrolne |
|---|---|---|
| Ta sama osoba lub firma siedzi w kilku tabelach (klient, dostawca, pracownik) | Party | „A co, jeśli nasz pracownik zostanie też klientem?” |
| „Zależy od…” przy cenie, opłacie, prowizji | Pricing | „Ile kosztowało to 3 miesiące temu i dlaczego?” |
| Rabaty, wykluczenia, „chyba że”, wyjątki dla VIP | Rules | „Kto zmienia tę regułę i jak często?” |
| Numer seryjny, partia, data ważności, pakiet, wariant | Product | „Czy rozróżniamy egzemplarze, czy tylko liczymy sztuki?” |
| „Czy jest wolne?”, rezerwacja, „ile zostało”, kolejka chętnych | Inventory | „Co się dzieje, gdy dwie osoby chcą tego samego naraz?” |
| Status, zatwierdzenie, anulowanie, kto zamawia, kto płaci, kto odbiera | Ordering | „Czy zamawiający i płacący to zawsze ta sama strona?” |
| Saldo, limit, „na dzień”, korekta, wygasanie środków | Accounting | „Jakie było saldo 31 marca według stanu wiedzy z 2 kwietnia?” |
| „Nie można zacząć, zanim…”, kolejność kroków, konflikty zasobów | Scheduling | „Co się przesunie, jeśli ten krok się spóźni?” |
| Harmonogram, „planowaliśmy, a wyszło”, odchyłka, tolerancja | Plan vs Execution | „Jaki był plan wczoraj i dlaczego się zmienił?” |
Liczba bez jednostki, waluta w nazwie kolumny, double price | Quantity | „W jakiej jednostce i jak zaokrąglamy?” |
Najmocniejszy sygnał w kodzie to ifologia po typie: if (klient.typ == FIRMA), switch (produkt.rodzaj), rozsiane po serwisach. Taki if mówi, że typ powinien być daną na poziomie wiedzy, a nie gałęzią w kodzie. Wrócimy do tego w następnym rozdziale.
Kliknij zdanie
Tu pojawi się, co zdradza archetyp i jaka konfiguracja pasuje.
Nie wszystko jest archetypem. Gdy pojęcie nie zmienia się w czasie, nie ma wariantów i biznes nie pyta o jego historię, zwykła encja wystarczy. Archetyp kosztuje: więcej pojęć, więcej konfiguracji, więcej testów. Płacisz ten koszt tylko wtedy, gdy sygnały z tabeli rzeczywiście występują. Więcej w rozdziale o antywzorcach.
Zdanie z wymagań: „Wynajmujący może podnająć lokal, ale tylko za zgodą właściciela, a czynsz od podnajemcy nie może przekroczyć 120% czynszu głównego”. Ile archetypów słyszysz?
Odpowiedź
Co najmniej trzy. Party: ta sama osoba jest najemcą w jednej relacji i wynajmującym w drugiej, a zgoda właściciela to warunek utworzenia relacji (polityka relacji). Pricing: czynsz podnajmu zależy od innej ceny (zależność komponentów). Rules: limit 120% to „strażnik” odrzucający niedozwolony wynik.
- Szukaj zachowań w czasie i pytań „a co, jeśli…”, a nie samych rzeczowników.
- Ifologia po typie to sygnał, że typ powinien być daną (poziom wiedzy).
- Jedno zdanie biznesowe często dotyka kilku archetypów naraz.
- Brak sygnałów oznacza, że zwykła encja wystarczy.
Poziom wiedzy i poziom operacyjny
meta-wzorzec pod każdym archetypemFowler w Analysis Patterns (1997) dzieli model na dwa piętra. Poziom operacyjny to fakty: ta umowa, ta paczka, ten zapis. Poziom wiedzy (knowledge level) to reguły, które mówią, jakie fakty są dozwolone: jakie są typy umów, jakie role może pełnić firma, jakie konta istnieją. Evans w Domain-Driven Design opisuje Knowledge Level jako jedną ze struktur dużej skali.
Każdy archetyp w tym kompendium ma oba piętra. W repozytorium szkolenia widać to wprost:
| Archetyp | Poziom wiedzy (typ, reguła) | Poziom operacyjny (fakt) |
|---|---|---|
| Party | dozwolone role, polityki relacji, wymagania kompetencji | Anna jest pełnomocnikiem firmy X od 1 marca |
| Product | ProductType: cechy, ograniczenia, strategia śledzenia | egzemplarz z numerem seryjnym, partia |
| Pricing | komponent, kalkulator, wersja z okresem ważności | wyliczona cena z rozbiciem |
| Accounting | typ konta, reguła księgowania (posting rule) | zapis na koncie, transakcja |
| Inventory | model dostępności, polityka kolejki | blokada złożona przez właściciela |
Praktyczny skutek: nowy wariant biznesu staje się nowym wierszem danych, a nie nową gałęzią w kodzie. Repozytorium showcase szkolenia pokazuje to na serwisie logistycznym w czterech wersjach. Wersja 1 to if-y wybierające kalkulator. W wersji 4 każda opcja (express, SMS, pobranie) jest produktem, ich kombinacja jest nazwanym ProductSet, a wybór kalkulatora to wyszukanie w mapie ProductSet → kalkulator. Autorzy podsumowują to tak: „konfiguracja jest DANYMI, nie KODEM”.
Poziom operacyjny: if-y w serwisie
Poziom wiedzy: tabela ProductSet → kalkulator
Poziom wiedzy kusi, żeby wszystko zrobić konfigurowalnym. Kończy się to własnym, gorszym językiem programowania w tabelach (tzw. inner-platform effect). Zasada praktyczna: przenoś do danych to, co biznes faktycznie zmienia i co ma się zmieniać bez wdrożenia. Algorytm kalkulatora zostaje w kodzie, a jego parametry i wybór trafiają do danych. Konfiguracja potrzebuje wersji z okresem ważności, inaczej zmiana cennika dziś zmieni wyliczenie wczorajszego zamówienia (przycisk 💥 na diagramie).
🔬 Głębiej: skąd się bierze ifologia i dlaczego wraca
Ifologia powstaje, gdy przestrzeń wyboru (który wariant?) miesza się z przestrzenią obliczeń (jak policzyć?). Showcase szkolenia pokazuje pośredni etap: jeden „mądry” kalkulator, który ma wszystkie if-y w sobie. Z zewnątrz wygląda czysto, ale problem tylko się przeniósł. Rozwiązanie rozdziela te przestrzenie: wybór jest indeksem (zestaw produktów → identyfikator kalkulatora), a obliczenie jest małym, testowalnym kalkulatorem bez if-ów biznesowych.
Ifologia wraca, gdy do indeksu trafiają warunki, które nie są nazwanymi pojęciami biznesu („jeśli kwota > 1000 i klient z Mazowsza i wtorek”). Jeśli kombinacja nie ma nazwy w języku biznesu, to zwykle nie jest wariantem produktu, tylko regułą. Jej miejsce jest w archetypie Rules.
W ubezpieczeniach komunikacyjnych co kwartał pojawia się nowy „wariant” polisy: inne sumy ubezpieczenia, inne wyłączenia, czasem nowy dodatek (assistance, szyby). Co powinno być na poziomie wiedzy, a co w kodzie?
Odpowiedź
Na poziomie wiedzy: typy produktów i dodatków, cechy z ograniczeniami (suma ubezpieczenia w zakresie), reguły dopuszczalnych kombinacji, wersje taryf z okresem ważności. W kodzie: algorytmy kalkulatorów (np. funkcja progowa, procent od bazy), walidacja reguł i mechanizm wyboru wersji. Nowy wariant to wtedy nowe dane, a nowy rodzaj obliczenia to nowy kalkulator w kodzie.
- Poziom wiedzy opisuje, co jest dozwolone, a poziom operacyjny zapisuje, co się stało.
- Nowy wariant biznesu to nowy wiersz, a nie nowy if.
- Oddziel wybór wariantu (indeks) od obliczenia (kalkulator).
- Konfiguracja potrzebuje wersji z okresem ważności. Nie rób konfigurowalnym wszystkiego.
Jak archetypy łączą się w system
identyfikatory i migawki, nie wspólne obiektyArchetypy rzadko występują pojedynczo. Zamówienie potrzebuje stron (Party), tego, co zamawiane (Product), ceny (Pricing), sprawdzenia dostępności (Inventory) i pieniędzy (Accounting). W repozytorium szkolenia zatwierdzenie zamówienia robi dokładnie to: dla każdej linii prosi magazyn o alokację, potem autoryzuje i pobiera płatność, a na końcu uruchamia realizację. Jeśli którykolwiek krok się nie uda, zamówienie zostaje w stanie DRAFT.
Kluczowe jest to, jak się łączą. Zamówienie nie trzyma obiektu klienta. Trzyma jego identyfikator i migawkę (PartySnapshot: identyfikator, nazwa, dane kontaktowe) z chwili złożenia. Gdy klient zmieni adres, wysłane zamówienie nie może zmienić się wstecz.
- Archetypy współpracują przez identyfikatory, migawki i zdarzenia, a nie przez wspólne obiekty.
- Ordering jest orkiestratorem: korzysta z Party, Product, Pricing, Inventory i płatności.
- Accounting zwykle słucha zdarzeń (np. zapisów księgowych), a Plan vs Execution porównuje plan z tym, co wykonano (wpłaty, produkcja, dostawy).
Fundamenty: wielkości i podmioty
Liczby z jednostką, pieniądze, które nie gubią groszy, i podmioty, które pełnią wiele ról naraz.
Quantity i Money
liczba bez jednostki to plotka23 września 1999 roku NASA straciła sondę Mars Climate Orbiter. Oprogramowanie naziemne dostawcy podawało impuls w funtach-sekundach (lbf·s), a system nawigacji oczekiwał niutonosekund (N·s). Sonda weszła za nisko w atmosferę Marsa. W 1983 roku Boeing 767 Air Canada (lot 143, „Gimli Glider”) skończył paliwo w locie, bo przy tankowaniu pomylono przelicznik na kilogramy z przelicznikiem na funty. W obu przypadkach liczba była poprawna. Zła była jej jednostka.
Quantity to liczba zawsze związana z jednostką (5 kg, 12 kWh, 3 szt.). Money to kwota zawsze związana z walutą (100,00 PLN). Operacje na nich pilnują jednostek i nie gubią groszy.
✅ Sięgnij, gdy
- ta sama rzecz bywa liczona w różnych jednostkach (paliwo w litrach i w tonach, czas w minutach i w godzinach);
- dzielisz kwoty: raty, udziały, rozksięgowanie kosztu na działy;
- obsługujesz więcej niż jedną walutę;
- zaokrąglenia mają znaczenie prawne lub podatkowe (VAT, odsetki).
⛔ Odpuść, gdy
- liczba nie ma jednostki z natury (numer wersji, liczba kliknięć w raporcie);
- cały system liczy jedną rzecz w jednej jednostce i nic tego nie zmieni. Nawet wtedy pieniądze trzymaj w typie dziesiętnym.
Opcje i konfiguracje
| Opcja | Co robi | Kiedy wybrać | Koszt / ryzyko |
|---|---|---|---|
| Jednostka jako typ | Ilość to para (wartość, jednostka). Dodawanie różnych jednostek kończy się błędem. | Zawsze, gdy liczysz coś fizycznego lub umownego (szt., kg, l, h, min). | Niski. Trzeba ustalić listę jednostek. |
| Zakaz wartości ujemnych | Ilość nie może być mniejsza od zera. W repozytorium sprawdza to konstruktor Quantity. | Stany, zamówione ilości, pojemności. | Ruchy „minus” trzeba wtedy modelować osobno, np. zapisem rozchodu. |
| Konwersja jednostek | Jawne przeliczenie z zapisanym współczynnikiem (Fowler: Conversion Ratio). | Kupujesz w tonach, sprzedajesz w litrach. Rozliczasz godziny i minuty. | Współczynnik bywa zmienny (gęstość zależy od temperatury). Zapisuj go razem z wynikiem. |
| Money z walutą | Kwota + kod waluty, w typie dziesiętnym. Różnych walut nie dodaje się bez kursu. | Każde pieniądze w systemie. | Kurs to dana z datą i źródłem, a nie stała w kodzie. |
| Polityka zaokrągleń | Ustala, kiedy (linia czy suma), jak (w górę, do parzystej) i gdzie trafia różnica. | VAT, odsetki, ceny jednostkowe z wieloma miejscami po przecinku. | Zmiana polityki zmienia kwoty na dokumentach. Wersjonuj ją. |
| Alokacja | Dzieli kwotę na części tak, że suma części zawsze równa się całości. | Raty, udziały, podział kosztu, zwroty częściowe. | Trzeba zdecydować, która część dostaje resztę groszy. |
| Procent jako typ | Osobny typ procentu (Percentage), żeby 5% nie pomylić z 0,05 ani z 5 punktami procentowymi. | Stawki, rabaty, prowizje, oprocentowanie. | Niski. |
- Dzień pierwszy: pieniądze w typie dziesiętnym z walutą, ilości z jednostką, zakaz dodawania różnych jednostek.
- Sygnał „rata” lub „udział”: dodaj alokację zamiast dzielenia.
- Sygnał „VAT” lub „odsetki”: zapisz politykę zaokrągleń jako regułę z nazwą.
- Sygnał „kupujemy w tonach, sprzedajemy w litrach”: dodaj jawną konwersję z zapisanym współczynnikiem.
doubledla pieniędzy. Skutek:0.1 + 0.2 ≠ 0.3i rozjazd sum na raportach.- Kwota bez waluty „bo i tak jest PLN”. Skutek: pierwszy klient z euro psuje wszystkie sumy.
- Dzielenie 100 zł na 3 przez zaokrąglenie każdej części. Skutek: 99,99 zł i grosz, którego nikt nie umie znaleźć.
W praktyce i w repozytorium
Archetyp Quantity (Fowler, Analysis Patterns; Arlow i Neustadt mają osobne archetypy Quantity i Money) mówi prosto: ilość = wartość + jednostka, a operacje sprawdzają jednostki. W repozytorium szkolenia Quantity to para (kwota BigDecimal, Unit). Dodawanie i odejmowanie różnych jednostek kończy się wyjątkiem, a ujemna ilość jest odrzucana już w konstruktorze. Money opakowuje JavaMoney (JSR 354), czyli kwotę z walutą.
double? Przecież ma dużo miejsc po przecinku.double to liczba binarna. 0,1 nie da się w niej zapisać dokładnie, więc 0.1 + 0.2 daje 0.30000000000000004. Do pieniędzy używaj typów dziesiętnych (BigDecimal) albo liczb całkowitych w groszach. Do tego potrzebna jest jawna polityka zaokrągleń.„Zaokrąglij do grosza” to nie wszystko. Trzeba wiedzieć kiedy (po każdej linii czy od sumy), jak (połówki w górę czy do parzystej, tzw. zaokrąglenie bankierskie) i gdzie trafia różnica. Ilustracyjny przykład: trzy pozycje po 0,10 zł netto z 23% VAT. Zaokrąglając podatek w każdej linii, dostajesz 3 × 0,02 zł (bo 0,023 ≈ 0,02) = 0,06 zł VAT. Liczony od sumy wychodzi 0,30 × 0,23 = 0,069 ≈ 0,07 zł. Różnica to grosz. Każda z metod może być poprawna, jeśli jest zapisana jako reguła i stosowana konsekwentnie.
Z Money wiąże się jeszcze procent kontra punkt procentowy. Podwyżka stopy z 5% do 6% to +1 punkt procentowy, ale +20%. Repozytorium ma osobny typ Percentage, właśnie żeby nie mieszać „0,05” z „5”.
Hurtownia paliw sprzedaje olej napędowy w litrach, kupuje go w tonach, a akcyzę rozlicza w tysiącach litrów w temperaturze referencyjnej. Ile archetypów Quantity widzisz i gdzie jest pułapka?
Odpowiedź
Jeden archetyp z trzema jednostkami (l, t, 1000 l) i co najmniej jedną konwersją zależną od kontekstu (gęstość i temperatura). Pułapka to „cicha” konwersja w kodzie z jedną stałą gęstością. Wtedy stany magazynowe w litrach i w tonach rozjeżdżają się z każdą dostawą. Lepiej zapisywać ilość w jednostce, w której ją zmierzono, i konwertować jawnie, z zapisanym współczynnikiem.
- Ilość to wartość + jednostka. Różnych jednostek nie dodajesz bez jawnej konwersji.
- Pieniądze to kwota + waluta, w typie dziesiętnym, nigdy w
double. - Dzielenie pieniędzy to alokacja: suma części zawsze równa całości.
- Zaokrąglenia (kiedy, jak, gdzie trafia różnica) to reguła biznesowa.
Party: kto jest kim
jedna osoba, wiele kapeluszyStrona szkolenia opisuje problem tak: „wieczny chaos z userami”. Klient, firma, pracownik i partner siedzą w osobnych strukturach, które się rozjeżdżają. Rozwiązanie: zamiast osobnych klas Client czy Partner modelujesz uniwersalny Party i przypisujesz mu role.
Weź bank. Jan Kowalski ma tam konto osobiste (klient detaliczny). Pracuje w tym banku, więc obowiązują go zasady konfliktu interesów. Jest poręczycielem kredytu brata. Zasiada też w zarządzie spółki, która jest klientem korporacyjnym. W modelu „tabela na rolę” Jan to cztery rekordy, które o sobie nie wiedzą. Dział ryzyka nie zobaczy wtedy, że jedna osoba łączy cztery ekspozycje. Rozporządzenie CRR ma na to pojęcie „grupy powiązanych klientów” (group of connected clients). Bez Party nie da się go policzyć.
Party to każdy, kto może być stroną w biznesie: osoba albo organizacja. „Klient”, „dostawca”, „pracownik” i „płatnik” to nie osobne typy, tylko role, które ta sama strona pełni naraz albo po kolei.
✅ Sięgnij, gdy
- ta sama osoba lub firma pojawia się w kilku rolach (klient i dostawca, pacjent i pracownik);
- obsługujesz i osoby, i firmy, i działy firm;
- ktoś pyta „kto był pełnomocnikiem w marcu?” albo „kto kontroluje tę spółkę?”;
- dane tej samej strony rozjeżdżają się między systemami.
⛔ Odpuść, gdy
- system ma jedną rolę i nie zanosi się na drugą (np. wewnętrzna lista uczestników szkolenia);
- stroną zarządza zewnętrzny system (CRM, ERP), a Ty potrzebujesz tylko jego identyfikatora. Wtedy trzymaj identyfikator i migawkę danych.
Opcje i konfiguracje
| Opcja | Co robi | Kiedy wybrać | Koszt / ryzyko |
|---|---|---|---|
| Osoba / organizacja / jednostka | Dwa rodzaje stron: osoba i organizacja. Organizacja to firma albo jednostka organizacyjna (dział, oddział). | Zawsze. Jednostki dokładasz, gdy działy mają własne role (np. płacą osobno). | Niski. Pułapka: jednoosobowa działalność to osoba, a nie firma. |
| Role przez politykę | Rola to nazwany „kapelusz”. Polityka decyduje, kto może mieć jaką rolę. | Gdy role mają warunki, np. „lekarz” tylko dla osoby. | Polityki trzeba utrzymywać razem z biznesem. |
| Identyfikatory z polityką | PESEL, paszport, NIP, REGON, KRS jako osobne obiekty. Polityka pilnuje, że PESEL ma tylko osoba, a REGON tylko organizacja. | Gdy identyfikatorów jest kilka albo pochodzą z różnych krajów. | Walidacja numerów (sumy kontrolne) to osobna praca. |
| Adresy jako osobny byt | Adres pocztowy, e-mail, telefon, WWW z zastosowaniami: rozliczeniowy, korespondencyjny, dostawy, zamieszkania, kontaktowy. | Gdy faktura i towar idą na różne adresy albo adresy często się zmieniają. | Dokumenty muszą zapisywać migawkę adresu, a nie referencję. |
| Relacje bez ważności | Nazwane powiązanie dwóch ról, np. „oddział należy do firmy”. | Relacje trwałe z natury, w małym systemie. | Brak historii. Zmiana relacji kasuje przeszłość. |
| Relacje z ważnością | Powiązanie ma datę od i do. | Zatrudnienie, pełnomocnictwo, opieka nad klientem, kontrola kapitałowa. | Każde zapytanie musi mówić „na kiedy”. |
| Polityka relacji | Decyduje, które role mogą być powiązane jaką relacją. | Gdy relacje tworzą użytkownicy lub integracje. | Domyślna polityka w repozytorium pozwala na wszystko. Reguły musisz dopisać sam. |
| Kompetencje i zakresy | Co strona potrafi, gdzie, kiedy, ile i na jakim poziomie, z datą ważności. | Dopasowanie wykonawcy do zlecenia: uprawnienia, certyfikaty, regiony. | Ważność trzeba sprawdzać w chwili przydziału. |
| Zdarzenia i wersja | Każda zmiana daje zdarzenie. Pole wersji służy do wykrywania równoległych zmian. W repozytorium Party tylko je przechowuje, a sprawdzanie konfliktów trzeba dopisać. | Gdy inne moduły reagują na zmiany stron albo kilka osób edytuje te same dane. | Potrzebny mechanizm publikacji zdarzeń. |
- Dzień pierwszy: osoba i organizacja, lista ról, jeden identyfikator (np. NIP), jeden adres.
- Sygnał „faktura na inny adres niż dostawa”: adresy jako osobny byt z zastosowaniami.
- Sygnał „działa w imieniu”, „pełnomocnik”, „opiekun klienta”: relacje z ważnością.
- Sygnał „tylko z uprawnieniami”, „tylko w regionie”: kompetencje z zakresami.
- Osobne tabele
Klient,Dostawca,Pracownik. Skutek: ta sama firma istnieje trzy razy i nikt nie widzi łącznej ekspozycji. - Pole
typKlientazmieniane w czasie. Skutek: historia znika, a stare dokumenty pokazują dzisiejszy typ. - Login jako Party. Skutek: księgowa obsługująca 30 firm „jest” jedną z nich.
W praktyce i w repozytorium
W repozytorium szkolenia Party jest klasą zamkniętą (sealed) z dwiema gałęziami: Person i Organization. Organizacja dzieli się na Company i OrganizationUnit (np. dział, oddział). Party ma:
- role: nazwane kapelusze (
Role), dodawane przez politykęPartyRoleDefiningPolicy. Ponowne dodanie tej samej roli nic nie zmienia i daje zdarzenie „pominięto”, a naruszenie polityki zwraca błądPOLICY_NOT_MET; - zarejestrowane identyfikatory (PESEL, paszport, NIP, REGON, KRS), sprawdzane polityką: identyfikatory osobowe tylko dla osób, organizacyjne (REGON, KRS) tylko dla organizacji;
- wersję do blokowania optymistycznego i zdarzenia dla każdej zmiany.
Silverston w The Data Model Resource Book wydziela mechanizm kontaktu (contact mechanism) z Party. Adres pocztowy, e-mail, telefon i strona WWW to różne rodzaje tego samego pojęcia. Repozytorium szkolenia robi podobnie. Adresy są osobnym agregatem (Addresses) z rodzajami GeoAddress, EmailAddress, PhoneAddress i WebAddress. Każdy adres ma zastosowania (AddressUseType): BILLING, MAILING, SHIPPING, RESIDENTIAL, CONTACT.
Dlaczego osobno? Bo adres ma własny cykl życia. Firma przenosi siedzibę, ale magazyn zostaje. Faktura idzie na adres księgowości, a towar na adres magazynu. Zamówienia nie trzymają referencji do adresu, tylko jego migawkę z chwili złożenia.
Konto logowania to sposób uwierzytelnienia, a nie podmiot. Księgowa obsługuje 30 firm z jednego loginu. Właściciel firmy ma login prywatny i firmowy. Klient korporacyjny ma 200 pracowników z dostępem. Gdy połączysz User z Party w jedną tabelę, każda z tych sytuacji staje się hackiem. Trzymaj tożsamość i dostęp (osobny bounded context, jak u Vernona w Implementing DDD) oddzielnie od Party. Łącz je relacją „działa w imieniu” z zakresem uprawnień.
🔬 Głębiej: RODO, anonimizacja i role
Prawo do usunięcia danych (RODO, art. 17) ma wyjątki, m.in. gdy przetwarzanie jest potrzebne do wypełnienia obowiązku prawnego (art. 17 ust. 3 lit. b), np. przechowywania dokumentów księgowych. Party z rolami pomaga tu naturalnie. Gdy klient odchodzi, możesz anonimizować dane osobowe w Party i jednocześnie zachować identyfikator, do którego odwołują się zapisy księgowe i zamówienia. Migawki w zamówieniach też trzeba objąć polityką retencji. Często to właśnie one są ostatnim miejscem, gdzie zostaje nazwisko.
Marketplace: osoba prywatna kupuje, potem zaczyna sprzedawać, potem zakłada jednoosobową działalność, a na końcu spółkę z o.o. i przenosi do niej sklep. Ile Party, ile ról i co się dzieje z ocenami sprzedawcy?
Odpowiedź
Dwa Party: osoba (z rolami kupujący, sprzedawca, przedsiębiorca, bo JDG nie ma odrębnej osobowości prawnej) i spółka (nowa organizacja z rolą sprzedawca). Między nimi relacja „wspólnik/założyciel” i „następca sklepu” z datą. Oceny sprzedawcy są przypięte do roli sprzedawcy konkretnego Party. Przeniesienie ich na spółkę to decyzja biznesowa zapisana relacją, a nie „zmiana typu klienta” w tabeli.
- Party to osoba albo organizacja. Klient, dostawca i pracownik to role, a nie typy.
- Role i identyfikatory dodaje się przez polityki, a każda zmiana daje zdarzenie.
- Adres ma własny cykl życia i zastosowania. Zamówienie zapisuje jego migawkę.
- Login to nie Party. Łącz je relacją „działa w imieniu”.
Role i relacje między stronami
relacja łączy role, nie ludziRelacja między stronami to nazwane powiązanie dwóch ról (np. „pełnomocnik” i „mocodawca”), zwykle z okresem ważności. Polityka relacji decyduje, które powiązania są dozwolone.
firma_id w tabeli osób. Taki klucz pamięta tylko jedno, bieżące powiązanie i nie ma nazwy ani dat.
Ubezpieczenie na życie: ubezpieczający zawiera umowę i płaci składkę. Ubezpieczony to osoba, której życie jest chronione. Uposażony dostaje świadczenie. Pracodawca może być ubezpieczającym dla stu pracowników, a każdy z nich wskazuje innych uposażonych. Ta sama osoba może być ubezpieczonym w jednej polisie i uposażonym w trzech innych. Takie sieci powiązań to codzienność archetypu Party.
Kluczowa decyzja z repozytorium szkolenia: PartyRelationship łączy role (PartyRole = Party + rola), a nie gołe Party. Relacja ma nazwę i okres ważności (Validity). Tworzy ją polityka PartyRelationshipDefiningPolicy, która dostaje rolę źródłową, rolę docelową i nazwę relacji, i decyduje, czy relacja jest dozwolona. Domyślna polityka pozwala na wszystko. W prawdziwym systemie to właśnie tu mieszka wiedza dziedzinowa.
Fowler opisuje to samo jako Accountability: typowaną relację odpowiedzialności między stronami, z okresem obowiązywania. Typy relacji i reguły, kto może być po której stronie, należą do poziomu wiedzy. Dzięki temu ten sam mechanizm obsługuje strukturę organizacyjną, nadzór, pełnomocnictwa i kontrolę kapitałową, a do tego kilka hierarchii naraz, np. podległość służbową i podległość regionalną w organizacji macierzowej.
| Konfiguracja | Co daje | Kiedy |
|---|---|---|
Relacja bez okresu ważności (Validity.ALWAYS) | Najprostsza. Brak historii. | Relacje trwałe z natury, np. „oddział należy do firmy” w małym systemie. |
| Relacja z okresem ważności | Odpowiedź na pytanie „kto był prezesem 3 lata temu?”. | Pełnomocnictwa, zatrudnienie, kontrola kapitałowa, opieka nad klientem. |
| Polityka relacji (role × role × nazwa) | Model sam odrzuca nonsensowne powiązania. | Gdy relacje tworzą użytkownicy lub integracje, a nie tylko administrator. |
| Wiele typów hierarchii naraz | Podległość służbowa ≠ regionalna ≠ kapitałowa. | Holdingi, organizacje macierzowe, sieci franczyzowe. |
| Atrybuty relacji (udział %, zakres pełnomocnictwa) | Relacja staje się bytem z danymi. To rozszerzenie: PartyRelationship w repozytorium ma tylko strony, nazwę i ważność. | Beneficjenci rzeczywiści, pełnomocnictwa rodzajowe. |
Przepisy AML każą ustalić beneficjenta rzeczywistego klienta, czyli osobę fizyczną, która ostatecznie go kontroluje. Dyrektywy unijne wskazują jako przesłankę m.in. posiadanie ponad 25% udziałów. W Polsce takie dane trafiają do Centralnego Rejestru Beneficjentów Rzeczywistych. W modelu Party to przejście po grafie relacji kontroli: udziały mnoży się po ścieżce, a ścieżki sumuje. Spółka A ma 60% B, a B ma 50% C, więc A ma pośrednio 30% C. Bez typowanych relacji z atrybutem „udział” takie zapytanie staje się ręcznym arkuszem.
Sieć franczyzowa: centrala, 300 franczyzobiorców (spółki i JDG), kierownicy sklepów, opiekunowie regionów z centrali. Franczyzobiorca kupuje towar od centrali, a centrala kupuje od niego usługi marketingu lokalnego. Jakie relacje i polityki?
Odpowiedź
Relacje: „umowa franczyzy” (centrala jako franczyzodawca ↔ franczyzobiorca), „opieka regionalna” (opiekun ↔ franczyzobiorca, z okresem ważności, bo opiekunowie rotują), „kieruje sklepem” (osoba ↔ jednostka organizacyjna). Ta sama para stron ma dwie relacje handlowe w przeciwnych kierunkach: klient/dostawca i dostawca/klient. Polityka: opiekunem może być tylko osoba w roli pracownika centrali. Umowa franczyzy wymaga roli franczyzobiorcy z ważnym identyfikatorem podatkowym.
- Relacja łączy role (Party + rola), ma nazwę i okres ważności.
- Polityka relacji to miejsce na wiedzę: kto z kim i w jakiej roli może być powiązany.
- Ten sam mechanizm obsługuje wiele hierarchii naraz (Fowler: Accountability).
- Atrybuty relacji, takie jak udział czy zakres, zamieniają pytania regulacyjne w zapytania po grafie.
Kompetencje i zakresy działania
rola wymaga, strona potrafiKompetencja mówi, co strona potrafi, a zakres działania mówi gdzie, kiedy, ile i na jakim poziomie. Rola może wymagać kompetencji, a system dopasowuje wykonawców do zleceń.
Rola mówi, kim ktoś jest w relacji. Nie mówi, co potrafi. Dyspozytor transportu nie szuka „przewoźnika”. Szuka przewoźnika z uprawnieniem ADR do przewozu materiałów niebezpiecznych, który działa na Śląsku, w weekend, i ma wolną cysternę. Szpital nie szuka „radiologa”, tylko radiologa poziomu senior z ważnym prawem wykonywania zawodu w szpitalu A.
Repozytorium szkolenia rozdziela te pojęcia. Capability to kompetencja strony: typ (np. „ADR”), lista zakresów działania (OperatingScope) i okres ważności. Zakresy to zamknięta lista siedmiu rodzajów, a każdy umie powiedzieć, czy spełnia wymaganie:
| Zakres | Spełnia wymaganie, gdy… | Przykład |
|---|---|---|
LocationScope | zawiera wszystkie wymagane lokalizacje | przewoźnik obsługuje Śląsk i Małopolskę |
TemporalScope | pokrywa wymagane dni i godziny | serwis dostępny w soboty 8–14 |
QuantityScope | ten sam okres i limit ≥ wymaganego (albo bez limitu) | do 5 zleceń dziennie |
SkillLevelScope | ranga ≥ wymaganej (junior < mid < senior < expert) | radiolog senior |
ProtocolScope | obsługuje wszystkie wymagane protokoły lub procedury | zespół pracujący wg procedury sterylizacji X |
ProductScope | obejmuje wszystkie wymagane produkty | autoryzowany serwis marek A i B |
ResourceScope | dysponuje wszystkimi wymaganymi zasobami | ma cysternę i dźwig HDS |
Po drugiej stronie są RoleRequirements: rola wymaga listy kompetencji, każdej z wymaganymi zakresami. Rola jest spełniona, gdy każde wymaganie pokrywa któraś ważna kompetencja. Wygasła kompetencja nie spełnia niczego. W scenariuszach repozytorium radiolog z wygasłym prawem wykonywania zawodu po prostu znika z wyników wyszukiwania. Fowler w rozdziale o Accountability też opisuje zakresy działania (Operating Scopes), co pokazuje, że to dojrzały pomysł, a nie wynalazek jednego projektu.
OperatingScope z repozytorium szkolenia.Kompetencja z okresem ważności to nie ozdoba. Uprawnienia zawodowe, certyfikaty i badania lekarskie wygasają. System, który sprawdza je tylko przy rejestracji, po roku przydziela zlecenia ludziom bez uprawnień. Sprawdzaj ważność w chwili przydziału (repozytorium ma do tego satisfiesAt(requirement, instant)), a nie przy zapisie.
- Rola mówi „kim”, a kompetencja mówi „co potrafi, gdzie, kiedy, ile i na jakim poziomie”.
- Siedem rodzajów zakresów: lokalizacja, czas, ilość, poziom, protokół, produkt, zasób.
- Rola jest spełniona, gdy każde wymaganie pokrywa któraś ważna kompetencja.
- Ważność sprawdzaj w chwili przydziału.
Produkt, cena, reguły
Co sprzedajesz, ile to kosztuje teraz i kiedyś, i jak nakładać wyjątki tak, żeby się nie pozabijały.
Product: typ, egzemplarz, partia
„iPhone” to nie jest ten iPhoneProduct opisuje to, co sprzedajesz: towar, usługę, umowę. Rozdziela typ (opis z katalogu, np. „kredyt Stała stopa 5 lat”) od egzemplarza (ta konkretna umowa, ten telefon, ta wizyta).
✅ Sięgnij, gdy
- sprzedajesz coś z katalogu, w wariantach albo z parametrami;
- musisz wiedzieć, który egzemplarz dostał klient (gwarancja, serwis, wycofanie);
- produkt może zniknąć z oferty, ale umowy na niego dalej trwają;
- sprzedajesz zestawy i pakiety z regułami wyboru.
⛔ Odpuść, gdy
- masz kilka stałych pozycji bez cech i wariantów (np. trzy rodzaje biletu wstępu). Wystarczy prosta lista typów;
- katalogiem zarządza zewnętrzny system (PIM). Trzymaj wtedy identyfikator i migawkę opisu.
Opcje i konfiguracje
| Opcja | Co robi | Kiedy wybrać | Koszt / ryzyko |
|---|---|---|---|
| Typ i egzemplarz | Opis katalogowy osobno, konkretna rzecz lub umowa osobno. | Zawsze, gdy egzemplarze się różnią albo trzeba je śledzić. | Niski. Dla towarów zamiennych egzemplarz może być tylko ilością. |
| Cechy z ograniczeniami | Typ definiuje cechy (obowiązkowe lub opcjonalne) i ograniczenia: lista wartości, zakres liczb, zakres dat, wyrażenie regularne. Egzemplarz ma wartości. | Warianty: kolor, pojemność, okres umowy, kwota kredytu. | Ograniczenia są danymi, więc trzeba je testować jak konfigurację. |
| Śledzenie: unikat | Dokładnie jeden egzemplarz na świecie, z numerem. | Dzieła sztuki, nieruchomości, instrumenty kolekcjonerskie. | Niski. |
| Śledzenie: indywidualne | Każdy egzemplarz ma numer seryjny (tekstowy, IMEI, VIN). | Gwarancja, serwis, leasing, wypożyczanie. | Każda sztuka to rekord. |
| Śledzenie: partia | Egzemplarze należą do partii z datą produkcji i datami ważności. | Żywność, leki, chemia, wycofania. | Trzeba pilnować, z której partii wydano towar. |
| Śledzenie: numer i partia | Numer seryjny i partia naraz. | Elektronika, leki na receptę. | Największy koszt danych. |
| Śledzenie: zamienne | Egzemplarze są nieodróżnialne, liczy się tylko ilość. Numer i partia są zabronione. | Śruby, materiały sypkie, energia. | Brak możliwości wycofania „tej jednej sztuki”. |
| Wpis w katalogu z ważnością | Nazwa wyświetlana, kategorie i okres, w którym produkt jest w ofercie. | Produkty sezonowe, wycofywane taryfy. | Trzeba odróżniać „nie ma w ofercie” od „nie istnieje”. |
| Ograniczenie stosowalności | Warunek, komu i w jakim kontekście wolno zaproponować produkt (np. wiek 18–45). | Produkty finansowe, oferty regionalne, oferty dla segmentów. | Warunki są danymi: potrzebują wersji i testów. |
| Pakiet | Produkt złożony z nazwanych zestawów i reguł wyboru: dokładnie jeden, najwyżej dwa, „jeśli A, to B”. | Abonament z telefonem, usługa kurierska z dodatkami. | Reguły trzeba sprawdzać przy każdym wyborze klienta. |
| Relacje produktów | Sześć typów: przejście na lepszy, zamiennik, następca, uzupełnienie, zgodny, niezgodny. | Migracje taryf, cross-sell, konfiguratory. | Relacje trzeba utrzymywać razem z katalogiem. |
- Dzień pierwszy: typ z nazwą i jednostką, egzemplarz (albo sama ilość dla towarów zamiennych), jedna strategia śledzenia.
- Sygnał „warianty”, „parametry umowy”: cechy z ograniczeniami zamiast nowych kolumn.
- Sygnał „wycofanie”, „data ważności”: partie jako osobny byt.
- Sygnał „zestaw”, „pakiet”, „tylko z”: pakiety z regułami wyboru i relacje produktów.
- Kolumna
cenaw tabeli produktów. Skutek: pierwsza promocja albo cennik dla firm wymaga przebudowy. - Nowa kolumna na każdą cechę. Skutek: tabela z setką pustych pól.
- Usunięcie produktu z bazy, gdy znika z oferty. Skutek: stare umowy wskazują na nieistniejący typ.
W praktyce i w repozytorium
Strona szkolenia ujmuje to tak: niemal każdy biznes to sklep, który sprzedaje „produkt” (ubezpieczenie, usługę kurierską, kredyt) o określonej konfiguracji i cenie. Pierwsza rzecz do rozdzielenia to typ i egzemplarz. ProductType „iPhone 15 Pro 256 GB” to opis z katalogu. Twój telefon z numerem IMEI to ProductInstance. Kredyt hipoteczny „Stała stopa 5 lat” to typ, a umowa nr 123 to egzemplarz z konkretną kwotą.
Typ w repozytorium szkolenia ma: identyfikator (UUID, GTIN, ISBN), nazwę i opis, preferowaną jednostkę (sztuki, litry, kWh), definicje cech (obowiązkowe lub opcjonalne, z ograniczeniami: lista dozwolonych wartości, zakres liczb, zakres dat, wyrażenie regularne), ograniczenie stosowalności (dla kogo i w jakim kontekście produkt jest dostępny) oraz strategię śledzenia. Egzemplarz ma wartości cech, które muszą spełniać ograniczenia typu, numer seryjny (tekstowy, IMEI, VIN) albo partię.
Osobno jest wpis w katalogu (CatalogEntry): nazwa wyświetlana, kategorie i okres ważności. Produkt może istnieć dłużej niż jego obecność w ofercie. Umowy na wycofany produkt nadal trzeba obsługiwać.
| Strategia | Co wymaga | Kiedy |
|---|---|---|
UNIQUE | numer seryjny; istnieje dokładnie jeden | dzieła sztuki, instrumenty kolekcjonerskie, nieruchomości |
INDIVIDUALLY_TRACKED | numer seryjny każdego egzemplarza | telefony (IMEI), auta (VIN), sprzęt na gwarancji |
BATCH_TRACKED | identyfikator partii | żywność, leki, chemia: wycofania i daty ważności |
INDIVIDUALLY_AND_BATCH_TRACKED | numer seryjny i partia | elektronika: gwarancja po numerze, wycofanie po partii komponentów |
IDENTICAL | nic; egzemplarze są zamienne, numer seryjny i partia są wręcz zabronione | śruby, materiały sypkie, kWh energii |
SCHEDULED, EXECUTING, COMPLETED, CANCELLED. Wizyta u lekarza, sesja ładowania i przewóz to egzemplarze usług.Cena nie jest atrybutem produktu. Kolumna price w tabeli produktów działa do pierwszej promocji, cennika dla firm, waluty albo zmiany cen od 1. dnia miesiąca. Produkt mówi, czym jest rzecz. To, ile kosztuje, zależy od kontekstu, czasu i reguł. Tym zajmuje się archetyp Pricing.
Apteka sprzedaje: lek na receptę (partia, data ważności, numer serii do weryfikacji autentyczności), syrop bez recepty, glukometr na gwarancji i usługę pomiaru ciśnienia. Dobierz strategie śledzenia.
Odpowiedź
Lek na receptę: partia i indywidualny identyfikator opakowania, czyli INDIVIDUALLY_AND_BATCH_TRACKED (w UE opakowania leków na receptę mają unikalny identyfikator do weryfikacji autentyczności). Syrop: BATCH_TRACKED. Glukometr: INDIVIDUALLY_TRACKED (gwarancja). Pomiar ciśnienia: usługa, egzemplarz to wykonanie ze statusem, bez śledzenia fizycznego.
- Typ (katalog) ≠ egzemplarz (ta rzecz, ta umowa, to wykonanie usługi).
- Cechy mają typy i ograniczenia na poziomie typu i wartości na poziomie egzemplarza.
- Strategia śledzenia decyduje, czy liczysz sztuki, partie, czy pojedyncze egzemplarze.
- Wpis w katalogu ma własny okres ważności. Cena nie jest polem produktu.
Pakiety, zestawy i relacje produktów
„wybierz dokładnie jeden, ale nie z tym”Pakiet to produkt złożony z nazwanych zestawów i reguł wyboru („dokładnie jeden z…”, „najwyżej dwa”, „jeśli A, to B”). Relacje produktów mówią, co jest następcą, zamiennikiem, ulepszeniem albo czym się nie łączy.
Operator komórkowy sprzedaje pakiet: abonament + telefon + starter z kartą SIM i akcesoriami. W scenariuszu repozytorium szkolenia obowiązuje reguła: flagowy telefon wymaga abonamentu premium. Starter musi mieć kartę SIM i może mieć najwyżej dwa akcesoria. Starter jest zagnieżdżony w pakiecie z telefonem. To jest archetyp Product w wersji z konfiguracją, a nie lista produktów w koszyku.
Szkielet z repozytorium: PackageType jest produktem (ma identyfikator, nazwę, strategię śledzenia, ograniczenie stosowalności), ale zamiast cech ma strukturę. Struktura to nazwane zbiory produktów (ProductSet) i reguły wyboru (SelectionRule):
| Reguła | Znaczenie | Przykład |
|---|---|---|
single(set) | dokładnie 1 z zestawu | jedna opcja śledzenia przesyłki |
optional(set) | 0 lub 1 | kanał powiadomień: SMS albo e-mail albo nic |
required(set) | co najmniej 1 | co najmniej jeden numer w ofercie rodzinnej |
isSubsetOf(set, min, max) | od min do max | do 2 dodatków |
and / or / not | złożenia reguł | ubezpieczenie standardowe albo rozszerzone, nie oba |
ifThen(warunek, wtedy) | reguła warunkowa | jeśli telefon flagowy, to abonament premium |
Relacje między produktami to druga połowa rozdziału. Repozytorium definiuje sześć typów: UPGRADABLE_TO (można przejść na lepszy), SUBSTITUTED_BY (zamiennik, gdy brak), REPLACED_BY (następca po wycofaniu), COMPLEMENTED_BY (pasuje do, czyli cross-sell), COMPATIBLE_WITH i INCOMPATIBLE_WITH. Tworzenie relacji przechodzi przez politykę, tak samo jak w Party.
- Stara taryfa „Smart 2019” dostaje relację
REPLACED_BY→ „Smart 2026”. Wpis w katalogu „Smart 2019” kończy ważność, ale typ produktu zostaje: obecni abonenci nadal go mają. - „Smart 2026” ma
UPGRADABLE_TO→ „Smart Max”. Aplikacja klienta pokazuje ścieżkę podwyższenia bez if-ów po nazwie taryfy. - Dodatek „Roaming UE+” ma
INCOMPATIBLE_WITH→ „Smart Junior”. Konfigurator nie pozwoli go dołożyć. - Cena obu taryf żyje w Pricing z wersjami. Zmiana ceny „Smart 2019” dla obecnych abonentów to nowa wersja komponentu, a nie edycja produktu.
🔬 Głębiej: ograniczenie stosowalności — produkt nie dla każdego
Repozytorium ma ApplicabilityConstraint: zamkniętą algebrę warunków (equalsTo, in, większe, mniejsze, pomiędzy, and, or, not, zawsze prawda). Warunki są sprawdzane na kontekście (ApplicabilityContext) z nazwanymi parametrami. Kredyt „Pierwsze mieszkanie” jest dostępny, gdy wiek between 18 and 45 and kraj = PL. Takie ograniczenie jest daną, nie kodem, więc dział produktowy może je zmienić bez wdrożenia. Ta sama algebra wraca w Pricing, gdzie decyduje, czy komponent ceny w ogóle się stosuje.
- Pakiet to produkt ze strukturą: nazwane zestawy + reguły wyboru, które można zagnieżdżać.
- Reguły: single, optional, required, isSubsetOf(min,max), and/or/not, ifThen.
- Relacje produktów (upgrade, zamiennik, następca, cross-sell, zgodność) zastępują if-y po nazwach.
- Ograniczenie stosowalności decyduje, komu produkt w ogóle wolno zaproponować.
Pricing: komponenty i kalkulatory
cena to drzewo, nie liczbaPricing liczy cenę jako drzewo składników (komponentów), a nie jedną liczbę. Każdy składnik ma nazwę i własny sposób liczenia (kalkulator), a wynik pokazuje, z czego składa się kwota.
cena w produkcie. Nie jest też silnikiem promocji: wyjątki typu „−10% dla VIP” to Rules, które nakładają się na cenę.
✅ Sięgnij, gdy
- cena ma kilka składników i klient chce widzieć każdy z nich;
- cena zależy od ilości (progi), czasu (minuty, dni) albo parametrów (kwota, okres);
- cenniki się zmieniają, a stare transakcje trzeba umieć przeliczyć „po staremu”;
- kod liczący cenę ma rosnącą listę if-ów po typie produktu lub klienta.
⛔ Odpuść, gdy
- każdy produkt ma jedną stałą cenę i zmienia się ona rzadko. Wystarczy cennik z datą obowiązywania;
- cenę ustala człowiek przy każdej transakcji (wycena indywidualna). Wtedy zapisz kwotę i powód.
Opcje i konfiguracje
Najpierw kalkulatory, czyli sposoby liczenia jednego składnika. Repozytorium szkolenia ma osiem rodzajów:
| Kalkulator | Co liczy | Przykład |
|---|---|---|
| Stała kwota | zawsze tę samą kwotę, niezależnie od parametrów | opłata za rozpoczęcie sesji ładowania |
| Odsetki roczne | roczną stopę procentową od kwoty bazowej, przeliczoną na okres | odsetki od kredytu |
| Funkcja progowa | cenę bazową z przyrostem co określoną liczbę jednostek | energia drożeje o 0,10 zł co 5 kWh |
| Punkty dyskretne | cenę z tabeli „ilość → cena” | pakiety 5, 10, 20 sztuk |
| Dzienny przyrost | cenę rosnącą o stałą kwotę każdego dnia od daty startu | cena biletu rośnie z każdym dniem bliżej wydarzenia |
| Liniowa w czasie | cenę przechodzącą płynnie od wartości A do B między dwiema chwilami | stopniowe wprowadzanie nowej stawki |
| Procent | procent od kwoty bazowej | VAT, ubezpieczenie 2% od kwoty kredytu |
| Złożony | wybiera inny kalkulator zależnie od zakresu parametru | opłata za konto zależna od wysokości wpływów |
Potem decyzje o strukturze ceny:
| Opcja | Co robi | Kiedy wybrać | Koszt / ryzyko |
|---|---|---|---|
| Komponent prosty | Nazwany składnik ceny z jednym kalkulatorem. | Każda pozycja, którą klient widzi na rachunku. | Niski. |
| Komponent złożony | Grupa komponentów z sumą i rozbiciem. | Cena z kilku składników: „opłaty bazowe”, „nadwyżki”, „podatki”. | Drzewo trzeba umieć pokazać klientowi. |
| Zależności między komponentami | Parametr jednego komponentu to wynik innego: wartość, suma, różnica albo iloczyn wyników. | VAT od sumy netto, ubezpieczenie od odsetek i prowizji. | Cykl zależności to błąd konfiguracji. Wykrywaj go przy zapisie. |
| Interpretacja: całkowita | Wynik to cena za całą ilość. | Rachunki, faktury. | Pomylenie interpretacji daje ceny wielokrotnie za duże lub za małe. |
| Interpretacja: jednostkowa | Wynik to średnia cena jednej jednostki. | Cenniki „za sztukę”, porównania ofert. | Jak wyżej. |
| Interpretacja: marginalna | Wynik to cena n-tej konkretnej jednostki. | Taryfy progowe, „każdy GB ponad limit”. | Jak wyżej. |
| Adaptery interpretacji | Sześć przeliczeń między interpretacjami, np. „suma cen marginalnych = cena całkowita”. | Gdy kalkulator liczy w jednej interpretacji, a dokument potrzebuje innej. | Niski, jeśli interpretacja jest zapisana przy kalkulatorze. |
| Wersje z ważnością | Komponent ma wersje „od–do”. Promocja to nakładka na krótszy okres. | Zmiany cenników, promocje czasowe, reklamacje sprzed miesięcy. | Każde liczenie potrzebuje daty, „na kiedy”. |
| Strategia dodawania wersji | Odrzuć identyczne okresy, odrzuć nachodzące albo pozwól na wszystko. | Ceny regulowane: odrzuć nachodzące. Korekty: pozwól na wszystko. | Zła strategia pozwala na dwie ceny tego samego dnia. |
| Ograniczenie stosowalności | Warunek, kiedy komponent w ogóle się liczy. | Dopłata tylko dla przesyłek zagranicznych, opłata tylko dla klientów bez abonamentu. | Warunki są danymi: potrzebują testów. |
- Dzień pierwszy: jeden komponent na pozycję rachunku, kalkulator stały albo procentowy, wynik z rozbiciem.
- Sygnał „cena zależy od ilości”: kalkulator progowy albo tabela punktów i jawna interpretacja.
- Sygnał „VAT od sumy”, „opłata od odsetek”: komponent złożony z zależnościami.
- Sygnał „od przyszłego miesiąca drożej”, „promocja w lutym”: wersje z ważnością.
- Jedna metoda
liczCene()z if-ami po typie produktu. Skutek: każdy nowy produkt to zmiana kodu. - Wynik bez rozbicia. Skutek: reklamacja „dlaczego 81 zł?” wymaga programisty.
- Nadpisanie ceny w cenniku zamiast nowej wersji. Skutek: nie da się przeliczyć zamówienia sprzed zmiany.
W praktyce i w repozytorium
Sesja ładowania auta w scenariuszu e-mobility z repozytorium szkolenia kosztuje: energię hurtową w progach (0,60 zł/kWh za pierwsze 5 kWh, każdy kolejny próg 5 kWh droższy o 0,10 zł), opłatę sieciową 0,15 zł/kWh, opłatę operatora ładowarki 1,50 zł za sesję plus 0,25 zł/kWh i 0,10 zł/min oraz marżę dostawcy usługi 0,10 zł/kWh. Cena jest drzewem komponentów, a każdy komponent liczy inny kalkulator.
Archetyp Pricing w repozytorium ma trzy piętra:
- Kalkulator: czysta funkcja „parametry → kwota”. Typy: stała kwota, odsetki roczne, funkcja progowa (cena bazowa + przyrost co N jednostek), punkty dyskretne (tabela), dzienny przyrost, liniowa interpolacja w czasie, procent od bazy oraz złożony, który deleguje do innych kalkulatorów według zakresów parametru.
- Komponent: nazwany element ceny („opłata za sesję”, „VAT”). Prosty komponent używa kalkulatora i mapuje nazwy parametrów. Złożony komponent ma dzieci i zależności: parametr dziecka może być wynikiem innego dziecka (
ValueOf,SumOf,DifferenceOf,ProductOf). Tak VAT dostaje kwotę netto. - Rozbicie (
ComponentBreakdown): wynik to nie jedna liczba, tylko drzewo kwot. Klient widzi „za co płaci”, a reklamacja ma na czym pracować.
Najmniej oczywisty element to interpretacja (Interpretation). TOTAL to cena za całą ilość. UNIT to średnia cena jednostki. MARGINAL to cena n-tej konkretnej jednostki. Repozytorium ma adaptery między nimi, np. „marginalna → całkowita = suma marginalnych od 1 do n” albo „całkowita → marginalna = total(n) − total(n−1)”. To nie jest akademickie: taryfy progowe energii, rabaty ilościowe i cenniki „pierwsze 5 GB w abonamencie, potem 2 zł za GB” różnią się dokładnie interpretacją.
- v1: if-y w serwisie wybierają kalkulator („jeśli express, to mnożnik 1,5”).
- v2: jeden „mądry” kalkulator dostaje wszystkie parametry i ma if-y w środku. Problem się tylko przeniósł.
- v4: każda opcja (basic, express, SMS, pobranie) to produkt, a kombinacja to nazwany
ProductSet. Wybór kalkulatora to wyszukanie w mapieProductSet → CalculatorId. If-y znikają, a nowa kombinacja to nowy wpis. - Ten sam wzorzec showcase powtarza dla banku (kredyt konsumpcyjny, hipoteka, karta debetowa; cztery wersje) i dla telekomunikacji (od razu w wersji z
ProductSet). Logika jest identyczna, zmienia się tylko kostium.
W scenariuszu bankowym z repozytorium kredyt 100 000 zł na rok to: odsetki 5 500 zł (5,5%), prowizja 500 zł, czyli „baza kredytu” 6 000 zł. Ubezpieczenie liczy się jako 2% od tej bazy, więc 120 zł. Razem 6 120 zł. Ubezpieczenie zależy od wyniku dwóch innych komponentów. Zależności tworzą graf skierowany. Cykl w nim (VAT od kwoty brutto, która zawiera VAT) to błąd konfiguracji, który warto wykrywać przy zapisie, np. sortowaniem topologicznym z części o grafach. Moduł pricing w repozytorium nie robi tego jawnie.
Abonament telco: 45 zł opłat bazowych (dwa komponenty: 25 zł i 20 zł), w cenie 5 GB danych i 30 minut roamingu, każdy GB ponad limit po 2 zł, roaming ponad 30 minut po 1,50 zł/min, a VAT od sumy netto. Narysuj drzewo komponentów. Ile kosztuje miesiąc z 8 GB i 50 minutami roamingu (netto)?
Odpowiedź
Drzewo: Rachunek = [Bazowa A (25) + Bazowa B (20) + Nadwyżka danych (progowo, 2 zł × GB ponad 5) + Nadwyżka roamingu (1,50 zł × min ponad 30)], a VAT jest dzieckiem zależnym od sumy netto. Netto: 45 + 3 × 2 + 20 × 1,50 = 45 + 6 + 30 = 81 zł. Kwoty składowe odpowiadają scenariuszom telco z repozytorium szkolenia (tam bazowo 45 zł, nadwyżka danych 6 zł, nadwyżka roamingu 30 zł).
- Cena to drzewo komponentów z rozbiciem, a nie jedna liczba.
- Kalkulator to czysta funkcja. Komponent go nazywa i łączy z zależnościami.
- Interpretacje TOTAL, UNIT i MARGINAL to trzy różne odpowiedzi na „ile to kosztuje”.
- Wybór wariantu to indeks (ProductSet → kalkulator), a nie if-y.
Cena w czasie: wersje i ważność
„ile kosztowało 14 lutego?”Scenariusz z repozytorium: ładowanie kosztuje 2,50 zł/kWh netto + 23% VAT. Sesja 20 kWh w styczniu to 50,00 zł + VAT = 61,50 zł. W lutym jest promocja walentynkowa, a od maja dochodzi opłata parkingowa 5 zł. Klient reklamuje sesję z 14 lutego w czerwcu. System musi policzyć cenę tak, jak obowiązywała 14 lutego, a nie dzisiejszą.
Rozwiązanie z repozytorium: komponent ma listę wersji, a każda wersja ma kalkulator, okres ważności (validFrom, validTo) i chwilę zdefiniowania (definedAt). Przy liczeniu na chwilę t:
- bierze się wersje ważne w t,
- wygrywa ta z najmłodszym
validFrom, czyli najbardziej szczegółowa nakładka, - przy równym
validFromwygrywa później zdefiniowana (definedAt), - brak ważnej wersji to jawny błąd, a nie cicha cena zero.
Promocja nie nadpisuje ceny bazowej. Jest nakładką: wersja „od 1 lutego do 28 lutego” przykrywa wersję „od 1 stycznia bezterminowo”. 1 marca baza znów wygrywa i nikt nie musi pamiętać o „przywróceniu ceny”. Test z repozytorium sprawdza właśnie to: 100 zł w styczniu, 80 zł w lutym, 100 zł w marcu.
| Strategia dodawania wersji | Co odrzuca | Kiedy |
|---|---|---|
REJECT_IDENTICAL | wersję z identycznym okresem ważności | domyślnie: nakładki tak, duplikaty nie |
REJECT_OVERLAPPING | każdą wersję nachodzącą na istniejącą | regulowane cenniki, gdzie w danym dniu może obowiązywać tylko jedna cena |
ALLOW_ALL | nic; przy remisie wygrywa nowsza (definedAt) | korekty: „ta sama ważność, ale poprawiona wartość” |
🔬 Głębiej: dwa czasy — kiedy obowiązuje i kiedy się dowiedzieliśmy
validFrom/validTo to czas obowiązywania (Fowler: actual time, w bazach danych: valid time). definedAt to czas zapisu (Fowler: record time, w bazach: transaction time). Oba razem to model bitemporalny. Dzięki niemu odpowiesz na dwa różne pytania: „ile kosztowało 14 lutego?” i „ile myśleliśmy 15 lutego, że kosztowało 14 lutego?”. To drugie zadaje audytor, gdy po korekcie wstecz klient ma fakturę z inną kwotą niż dzisiejsze wyliczenie. Pełne odtworzenie stanu wiedzy wymaga filtrowania także po definedAt ≤ chwila_pytania. Mechanizm z repozytorium używa definedAt tylko do rozstrzygania remisów. Więcej o dwóch czasach jest w rozdziale o czasie w księgowości.
Zamówienie nie przelicza ceny przy każdym odczycie. Po zatwierdzeniu linia ma wycenę z rozbiciem, czyli migawkę. Wersje cen służą do wyceny nowych zamówień, symulacji „co by było” i reklamacji. Nie służą do cichej zmiany kwot na wystawionych dokumentach.
- Komponent ma wersje z okresem ważności. Promocja to nakładka, a nie nadpisanie.
- Wygrywa najmłodszy validFrom, przy remisie później zdefiniowana wersja.
- Strategie: odrzuć identyczne, odrzuć nachodzące, pozwól na wszystko.
- Ważność + chwila zapisu = model bitemporalny dla reklamacji i audytu.
Rules: predykat, aplikator, strażnik
kolejność rabatów to decyzja biznesowaSklep ma trzy promocje: −10% dla VIP, −20% na kategorię „ogród” i −15 zł przy koszyku powyżej 200 zł. Cena bazowa 100 zł. Ile płaci VIP za grill? 100 → 90 → 72 → 57? A może −10% i −20% liczone od bazy, czyli 70 zł? A może promocje się nie łączą? Każda z tych odpowiedzi jest gdzieś na świecie poprawna. Arlow i Neustadt mają osobny archetyp Rule, a repozytorium szkolenia moduł rules. Oba z tego samego powodu: reguły zmieniają się szybciej niż reszta modelu i muszą być danymi z jawną semantyką.
Rules to wyjątki i promocje zapisane jako osobne, nazwane reguły. Każda reguła mówi: kiedy działa (warunek), co zmienia (np. −10%) i czego nie wolno (np. zejść poniżej marży).
✅ Sięgnij, gdy
- w wymaganiach są zdania „chyba że”, „nie łączy się z”, „tylko dla”;
- dział marketingu chce dodawać promocje bez wdrożeń;
- trzeba pokazać klientowi, która reguła dała ile;
- istnieje granica, której żadna promocja nie może przekroczyć (marża, cena minimalna).
⛔ Odpuść, gdy
- jest jeden rabat, który nigdy się nie zmienia. Wystarczy komponent ceny;
- „reguła” to w istocie proces z krokami i decyzjami ludzi. Wtedy modeluj proces, a nie regułę.
Opcje i konfiguracje
| Opcja | Co robi | Kiedy wybrać | Koszt / ryzyko |
|---|---|---|---|
| Warunek na pozycji | Sprawdza pozycję: który produkt, czy droższa niż X. Warunki łączy się przez i, lub, nie. | Promocje na kategorie, produkty, progi cenowe. | W repozytorium warunek na ilości jest tylko szkicem. Trzeba go dopisać. |
| Warunek na kliencie | Osobny warunek mówi, którzy klienci dostają regułę: status (np. VIP), staż, suma wydatków. | Programy lojalnościowe, segmenty klientów. | Dane o kliencie muszą być aktualne w chwili liczenia. |
| Zmiana: procent od bazy | Liczy procent od ceny bazowej, niezależnie od innych reguł. | Gdy rabaty mają się sumować „od ceny katalogowej”. | Kilka rabatów może dać cenę bliską zeru. Dodaj strażnika. |
| Zmiana: procent od wyniku | Liczy procent od ceny po poprzednich regułach. | Gdy rabaty mają się „składać” (−10%, potem −20% od tego). | Wynik zależy od kolejności reguł. |
| Zmiana: kwota | Odejmuje stałą kwotę od bieżącej ceny. | „−15 zł przy koszyku powyżej 200 zł”. | Kolejność względem procentów zmienia wynik. |
| Zmiana: cena stała | Ustawia cenę na podaną kwotę. | „Wszystko po 9,99 zł”. | Unieważnia wcześniejsze reguły w łańcuchu. |
| Strażnik | Odrzuca zmianę, gdy wynik jest niedopuszczalny, np. poniżej 75% ceny bazowej. Pozycja zostaje bez zmian. | Ochrona marży, ceny minimalne z umów. | Klient może nie rozumieć, czemu rabat „nie zadziałał”. Pokazuj listę zmian. |
| Łańcuch i kolejność | Reguły działają po kolei. Każda zapisuje w pozycji nazwaną zmianę. | Zawsze, gdy reguł jest więcej niż jedna. | Kolejność to decyzja biznesowa. Zapisz ją jawnie. |
| Źródło konfiguracji: kod | Reguły wpisane na stałe w klasie konfiguracji. | Mało reguł, rzadkie zmiany. | Każda zmiana to wdrożenie. |
| Źródło konfiguracji: wyliczane | Reguły tworzone z danych, np. rabat na produkty, których jest za dużo w magazynie. | Promocje sterowane stanem firmy. | Trzeba testować wynik dla różnych stanów danych. |
| Źródło konfiguracji: baza | Reguły i ich parametry zapisane jako wiersze w bazie i składane w obiekty. | Marketing zmienia promocje sam. | Potrzebne wersje i podgląd skutków przed publikacją. |
| Algebry interpretacji | To samo wyrażenie reguły daje odpowiedź „tak/nie”, „jak bardzo”, „ile punktów” albo „dlaczego”. | Lojalność, scoring, wyjaśnienia dla obsługi klienta. | Wyższy próg wejścia. Opisane na poziomie 3. |
- Dzień pierwszy: jedna reguła = warunek + zmiana + nazwa. Każda zastosowana zmiana jest zapisana w pozycji.
- Sygnał „promocje się łączą”: łańcuch z jawną kolejnością i decyzją „od bazy” albo „od wyniku”.
- Sygnał „nie poniżej marży”: strażnik.
- Sygnał „marketing chce sam”: konfiguracja z bazy, z wersjami i podglądem.
- Rabaty jako if-y w metodzie liczącej cenę. Skutek: nikt nie wie, w jakiej kolejności działają.
- Brak decyzji „od bazy czy od wyniku”. Skutek: ta sama promocja daje inne kwoty w sklepie i w aplikacji.
- Brak listy zastosowanych zmian. Skutek: reklamacja „gdzie mój rabat?” wymaga przeglądania logów.
W praktyce i w repozytorium
Szkielet modyfikatora oferty w repozytorium (ConfigurableItemModifier) ma trzy części:
- Predykat: czy reguła dotyczy tej pozycji (kategoria, status klienta, ilość, „droższe niż”). Predykaty składają się przez
and,orinot. - Aplikator: jak zmienia cenę.
PercentageFromBaseliczy procent od ceny bazowej, aPercentageAccumulatedod ceny już zmienionej przez poprzednie reguły. Jest też stała cena. - Strażnik (guardian): czy wynik jest dopuszczalny.
MarginGuardianodrzuca zmianę, jeśli cena końcowa spadłaby poniżej zadanego procentu ceny bazowej. Wtedy pozycja zostaje niezmieniona.
Modyfikatory łączy się w łańcuch (ChainOfferItemModifier). Każda zastosowana zmiana zapisuje się w pozycji jako nazwana modyfikacja, więc klient i dział reklamacji widzą, która reguła ile dała.
- Reguła = predykat (czy dotyczy) + aplikator (jak zmienia) + strażnik (czy wynik dopuszczalny).
- „Procent od bazy” i „procent od wyniku” dają różne ceny. To decyzja biznesowa, a nie szczegół.
- Kolejność w łańcuchu ma znaczenie, gdy mieszasz kwoty stałe i procenty.
- Każda zastosowana modyfikacja jest nazwana i widoczna.
Algebra reguł: jedno wyrażenie, wiele odpowiedzi
„czy?”, „jak pewnie?”, „dlaczego?”Program lojalnościowy ma regułę: „klient jest aktywny, jeśli w ostatnich 90 dniach wydał ponad 500 zł i (zrobił ponad 5 zakupów lub ma status VIP)”. Różne części firmy zadają o nią różne pytania. Sklep pyta: czy klient spełnia regułę? Marketing pyta: jak pewnie ją spełnia? Ktoś, kto ledwo przekroczył próg, łatwo straci status i jest dobrym celem kampanii utrzymaniowej. Obsługa klienta pyta: dlaczego klient nie dostał statusu?
Repozytorium szkolenia rozwiązuje to algebrą: wyrażenie reguły jest drzewem (and, or, not, porównanie metryki w oknie czasowym, stała), a interpretacja jest wymienna. Interfejs Algebra<R> definiuje operacje and, or, not, metricCmp i constScore (oraz sum, ifThenElse i label) dla dowolnego typu wyniku R. Implementacje:
- logiczna: prawda albo fałsz (w repozytorium to np. algebra rozmyta z zerowym marginesem, która zwraca tylko 0 albo 1);
- rozmyta (
FuzzyAlgebra): stopień spełnienia 0–1, gdzieand= minimum,or= maksimum,not= 1 − x, a porównanie „większe niż próg” ma margines: na progu stopień wynosi 0, a rośnie liniowo do 1 przy progu + margines; - punktowa (
ScoreAlgebra): warunki dają 0 albo 1, stałe dają punkty, a suma składa wynik, np. punkty lojalnościowe; - wyjaśniająca (
ExplainableAlgebra, wynikExplainedScore): wynik plus lista wkładów („+40 za wydatki, +30 za VIP”; wkłady równe zero są pomijane).
FuzzyAlgebra. Operatory rozmyte min, max i 1−x odpowiadają implementacji z repozytorium.Wyrażenie nie wie, jak będzie interpretowane. Repozytorium pokazuje dwa sposoby. Pierwszy to klasyczny wzorzec Visitor (ExpressionVisitor). Drugi to interfejs algebry z parametrem typu wyniku (w programowaniu funkcyjnym znany jako tagless final). Zysk biznesowy: jedna definicja reguły zasila decyzję, kampanię i wyjaśnienie. Nie ma trzech kopii logiki, które rozjadą się przy pierwszej zmianie progu.
- Regułę zapisz raz jako drzewo wyrażenia, a interpretacje wymieniaj.
- Logika odpowiada „czy”, rozmyta „jak pewnie”, punktowa „ile punktów”, wyjaśniająca „dlaczego”.
- Rozmyte and/or/not: minimum, maksimum, 1 − x.
Zasoby i zamówienia
Co jest dostępne, kto to blokuje i na jak długo, i jak zamówienie prowadzi wszystkie archetypy przez swój cykl życia.
Inventory: trzy rodzaje dostępności
rezonans, zbiornik i pokój hotelowyScenariusze repozytorium szkolenia pokazują trzy zupełnie różne „czy jest wolne?”. Radiologia rezerwuje rezonans magnetyczny: jest jeden, albo wolny, albo zajęty. Firmy flotowe rezerwują paliwo ze zbiornika 10 000 litrów: każda bierze ile chce, dopóki starcza. Gość rezerwuje pokój 101 na noc 15 czerwca: ten sam pokój jest wolny 14 i 16 czerwca. Trzy modele dostępności, jeden archetyp.
Inventory odpowiada na pytanie „czy jest wolne?”. Wie, jakie zasoby istnieją, ile ich jest i kto, na ile i na jak długo je zablokował.
✅ Sięgnij, gdy
- dwie osoby mogą chcieć tego samego naraz (miejsce, termin, urządzenie, towar);
- coś trzeba „odłożyć” na chwilę: koszyk, rezerwacja wstępna, przedsprzedaż;
- zasób jest dostępny w czasie: pokój na noc, gabinet na godzinę, auto na dzień;
- kilka zasobów trzeba zarezerwować razem albo wcale.
⛔ Odpuść, gdy
- zasób jest praktycznie nieograniczony (pliki do pobrania, licencje bez limitu);
- jedyne pytanie to „ile mamy na stanie?” bez rezerwacji i bez konkurencji o zasób. Wystarczy saldo ilości.
Opcje i konfiguracje
| Opcja | Co robi | Kiedy wybrać | Koszt / ryzyko |
|---|---|---|---|
| Dostępność indywidualna | Jeden konkretny zasób: wolny albo zajęty w całości. | Rezonans, auto o numerze VIN, laptop z wypożyczalni. | Niski. |
| Pula | Zasób o pojemności (ilość). Każdy bierze część, dopóki starcza. | Paliwo w zbiorniku, miejsca bez numerów, limit wejściówek. | Nie wiadomo, „która” część jest czyja. Gdy to ważne, wybierz indywidualną. |
| Dostępność w czasie | Zasób w przedziale czasu (slocie). Ten sam pokój jest wolny 14 i zajęty 15 czerwca. | Hotele, wizyty, sale, sprzęt na godziny. | Trzeba ustalić długość slotów i strefę czasową. |
| Grupa slotów | Rezerwacja kilku slotów naraz: wszystkie albo żaden. | Pobyt na kilka nocy, cykl zabiegów. | Większa szansa odmowy. Warto podpowiadać inne terminy. |
| Zasób złożony | Kilka różnych zasobów blokowanych razem. Gdy jeden się nie uda, reszta jest zwalniana. | Sala operacyjna z anestezjologiem i aparatem. | Trudniej znaleźć termin wspólny dla wszystkich składników. |
| Blokada bezterminowa | Zajęcie trwa, dopóki ktoś go nie zwolni. | Ostateczny przydział po opłaceniu. | Zapomniana blokada to zasób stracony na zawsze. |
| Blokada czasowa | Zajęcie wygasa samo po zadanym czasie. | Koszyk, rezerwacja wstępna, „trzymamy dla Ciebie 15 minut”. | Ktoś musi regularnie zwalniać wygasłe blokady. |
| Cel rezerwacji | Rezerwacja (BOOKING), przydział (ALLOCATION), odłożenie (HOLD), blokada chwilowa (TEMPORARY_LOCK). | Gdy różne cele mają różne reguły i raporty. | Niski. |
| Status rezerwacji | Oczekująca, potwierdzona, anulowana, wygasła, zrealizowana. | Każda rezerwacja z cyklem życia. | Przejścia między statusami trzeba pilnować. |
| Lista oczekujących | Kolejka chętnych z pojemnością i polityką: kolejność zgłoszeń, priorytet, kwoty dla grup, „kogo da się obsłużyć”. | Przedsprzedaż, zapisy, szczepienia, miejsca w przedszkolu. | Polityka bywa regulowana prawem. Zapisz ją w modelu. |
- Dzień pierwszy: jeden model dostępności (indywidualna, pula albo czas), blokada z właścicielem, operacje zablokuj i zwolnij.
- Sygnał „koszyk”, „trzymamy przez 15 minut”: blokady czasowe i regularne zwalnianie wygasłych.
- Sygnał „kilka nocy”, „razem z zespołem”: grupy slotów i zasoby złożone.
- Sygnał „zapisz mnie, jak się zwolni”: lista oczekujących z polityką.
- Kolumna
zajety = true. Skutek: nie wiadomo, kto zajął, do kiedy i czy to jeszcze aktualne. - Sprawdzenie „czy wolne” i zapis rezerwacji w dwóch krokach bez blokady. Skutek: dwie osoby dostają to samo miejsce.
- Rezerwacja wielu nocy jako osobne rezerwacje. Skutek: klient dostaje dwie noce z trzech.
W praktyce i w repozytorium
W repozytorium wszystkie trzy implementują wspólny interfejs ResourceAvailability: lock, unlock, isAvailable, availableQuantity i releaseExpired. Wpis magazynowy (InventoryEntry) łączy produkt z jego egzemplarzami, a egzemplarze z zasobami, których dostępność się śledzi. Inventory nie trzyma zamówień i cen. Wie tylko, co, ile i kiedy jest zablokowane i przez kogo.
TemporalResourceGroupedAvailability): rezerwacja trzech nocy blokuje wszystkie trzy albo żadną.CompositeResourceAvailability najpierw sprawdza dostępność wszystkich składników, potem blokuje każdy. Gdy któraś blokada się nie uda, wycofuje już założone. Albo cały zespół, albo nic.Lotnisko: miejsca w samolocie z numerami, bagaż rejestrowany do limitu wagi samolotu, rękawy do przylotów w oknach 30-minutowych, wózek dla osoby z niepełnosprawnością. Dobierz modele dostępności.
Odpowiedź
Miejsce z numerem: Individual w obrębie lotu (albo Temporal, jeśli modelujesz fotel w czasie, ale lot i tak jest jednorazowy). Bagaż: Pool w kilogramach. Rękaw: Temporal (slot 30 minut). Wózek z obsługą: zasób złożony (wózek Individual + asystent Temporal), żeby nie zarezerwować wózka bez osoby, która go pcha.
- Individual: egzemplarz. Pool: ilość z pojemności. Temporal: zasób w slocie czasu.
- Wszystkie mają lock/unlock/availableQuantity/releaseExpired.
- Wiele slotów i zasoby złożone blokuje się atomowo: wszystko albo nic.
- Inventory wie, co i przez kogo jest zablokowane. Ceny i zamówienia zostają poza nim.
Blokady, wygasanie i lista oczekujących
kto dostaje zwolnione miejsce?Blokada to zajęcie zasobu przez konkretnego właściciela, na zawsze albo na określony czas. Rezerwacja grupuje blokady i ma cel oraz status. Lista oczekujących decyduje, kto dostaje zwolnione miejsce.
Szczepienia w 2021 roku, przedsprzedaż biletów na koncert, wolne miejsca w przedszkolu: zasób się zwalnia, a chętnych jest wielu. „Kto pierwszy, ten lepszy” to tylko jedna z polityk. Repozytorium szkolenia rozbiera ten problem na części:
- Blokada (
Blockade) ma właściciela (OwnerId), chwilę założenia i czas trwania (LockDuration): bezterminowy albo czasowy. Blokada czasowa sama wygasa, areleaseExpired()zwalnia przeterminowane. - Rezerwacja grupuje blokady, ma cel (
ReservationPurpose:BOOKING,ALLOCATION,HOLD,TEMPORARY_LOCK) i status (PENDING,CONFIRMED,CANCELLED,EXPIRED,FULFILLED). - Lista oczekujących (
WaitList) ma pojemność i politykę wyboru następnego chętnego.
| Polityka | Kto dostaje miejsce | Kiedy |
|---|---|---|
FifoSelectionPolicy | kto pierwszy się zapisał | sprawiedliwość proceduralna, prosta do wyjaśnienia |
PrioritySelectionPolicy | najwyższy priorytet | triaż medyczny, klienci z SLA premium |
QuotaSelectionPolicy | pierwszy z segmentu, który nie wyczerpał kwoty | pule dla grup (np. miejsca dla mieszkańców i dla przyjezdnych) |
CriteriaSelectionPolicy | pierwszy, którego da się obsłużyć tym, co się zwolniło | zwolniło się 2 miejsca, a pierwsza grupa w kolejce liczy 4 osoby |
Blokada bez terminu to wyciek zasobu. Klient wkłada bilet do koszyka i zamyka kartę. Bez czasu trwania bilet jest „zajęty” na zawsze, a kolejka stoi. Każda blokada, która nie jest ostateczną alokacją, powinna mieć czas trwania (HOLD, TEMPORARY_LOCK). Trzeba też ustalić, kto i kiedy woła releaseExpired(): zadanie cykliczne czy sprawdzenie przy każdym odczycie.
- Blokada ma właściciela i czas trwania. Czasowe wygasają same.
- Rezerwacja grupuje blokady, ma cel i cykl życia.
- Lista oczekujących to pojemność + polityka: FIFO, priorytet, kwota, kryterium.
- Wybór polityki to decyzja biznesowa, często regulowana. Zapisz ją w modelu.
Ordering: cykl życia i role w zamówieniu
kto zamawia, kto płaci, kto odbieraZamówienie korporacyjne: dział zakupów centrali zamawia, księgowość spółki zależnej płaci, a towar trafia do trzech oddziałów, każdy z innym odbiorcą i inną osobą do kontaktu przy dostawie. Jedna linia jest do odbioru osobistego przez upoważnionego kierowcę. Model „zamówienie ma klienta i adres” tego nie udźwignie. Scenariusze repozytorium szkolenia (zamówienia korporacyjne, różni odbiorcy na liniach) testują dokładnie takie przypadki.
Ordering modeluje zlecenie: kto zamawia, płaci, odbiera i wykonuje, co jest zamówione (linie), za ile (wycena każdej linii) i w jakim stanie jest całość.
✅ Sięgnij, gdy
- zamawia ktoś inny niż płaci albo odbiera;
- zamówienie ma stany i reguły, co wolno zmienić w którym stanie;
- linie mają różnych odbiorców, terminy lub sposoby realizacji;
- zatwierdzenie uruchamia kilka kroków: rezerwację, płatność, realizację.
⛔ Odpuść, gdy
- „zamówienie” to natychmiastowa sprzedaż przy kasie bez stanów pośrednich. Wystarczy paragon i zapis w Accounting;
- zamówieniami zarządza zewnętrzna platforma, a Ty dostajesz tylko gotowe zlecenia do realizacji.
Opcje i konfiguracje
| Opcja | Co robi | Kiedy wybrać | Koszt / ryzyko |
|---|---|---|---|
| Role w zamówieniu | Sześć ról: zamawiający, płatnik, odbiorca, wykonawca, kontakt przy dostawie, osoba upoważniona do odbioru. | Zamówienia firmowe, dostawy do wielu miejsc, odbiór osobisty. | Każda rola to migawka danych strony, którą trzeba aktualizować świadomie. |
| Polityka ról zamówienia | Ilu może być zamawiających, płatników i odbiorców na całe zamówienie. | Zawsze. W repozytorium: jeden zamawiający, jeden wykonawca, najwyżej jeden płatnik. | Płatność „po równo przez kilku” wymaga zmiany polityki albo osobnych zamówień. |
| Polityka ról linii | Które role wolno przypiąć do pojedynczej linii. | Różni odbiorcy i osoby kontaktowe per linia. | Reguły na dwóch poziomach trzeba testować razem. |
| Migawki stron | Zamówienie zapisuje identyfikator i kopię danych strony z chwili złożenia. | Zawsze. Dokument ma pokazywać dane z dnia złożenia. | Migawki trzeba objąć polityką retencji danych osobowych. |
| Wycena linii: brak | Linia jeszcze nie ma ceny. | Szkic zamówienia, zapytanie ofertowe. | Nie wolno zatwierdzić bez ceny ostatecznej. |
| Wycena linii: wstępna | Cena orientacyjna, nieostateczna. | B2B, kursy walut, dostępność do potwierdzenia. | Klient może traktować ją jak obietnicę. |
| Wycena linii: wyliczona | Cena z kalkulatora z rozbiciem. Ostateczna. | Standardowa sprzedaż. | Niski. |
| Wycena linii: ręczna | Cena wpisana przez człowieka, z polem na powód. Ostateczna. | Negocjacje, wyjątki handlowe. | Powód trzeba wymusić. Repozytorium go nie waliduje. |
| Stany zamówienia | Szkic, zatwierdzone, oczekujące na alokację, w realizacji, zrealizowane, zamknięte, anulowane. W repozytorium dwa z nich (oczekujące na alokację i zamknięte) są w słowniku stanów, ale zamówienie jeszcze do nich nie przechodzi. | Zawsze. | Każde przejście potrzebuje reguły, co wolno w danym stanie. |
| Porty do innych modułów | Magazyn, płatności, realizacja, wycena, fakturowanie jako interfejsy. | Gdy zatwierdzenie dotyka innych archetypów. | Porażka w połowie wymaga kompensacji. |
| Kompensacja albo blokady czasowe | Cofnięcie wcześniejszych kroków, gdy późniejszy się nie uda, albo blokady, które same wygasną. | Płatność kartą po rezerwacji towaru. | Bez tego odrzucone płatności „zjadają” stan magazynu. |
- Dzień pierwszy: zamawiający jako migawka, linie z produktem i ilością, wycena wyliczona, stany szkic → zatwierdzone → zrealizowane.
- Sygnał „płaci kto inny”, „dostawa do oddziałów”: role na zamówieniu i liniach z politykami.
- Sygnał „cena do negocjacji”: wyceny wstępne i ręczne z powodem.
- Sygnał „płatność się nie udała”: kompensacja albo blokady czasowe w Inventory.
- Referencja do klienta zamiast migawki. Skutek: stare zamówienie nagle pokazuje nowy adres.
- Status jako dowolny tekst. Skutek: „wysłane”, „Wysłane” i „w drodze” w jednym raporcie.
- Faktury, płatności i wysyłki jako pola zamówienia. Skutek: druga rata albo druga paczka wymaga przebudowy.
W praktyce i w repozytorium
Szkielet z repozytorium:
- Strony w zamówieniu (
PartyInOrder): migawka Party (identyfikator, nazwa, kontakt) + rola w zamówieniu:ORDERER,PAYER,RECEIVER,EXECUTOR,DELIVERY_CONTACT,PICKUP_AUTHORIZED. - Polityki ról na dwóch poziomach. Na poziomie zamówienia: dokładnie jeden
ORDERER, dokładnie jedenEXECUTOR, najwyżej jedenPAYER, dowolnie wieluRECEIVER. Kontakt dostawy i osoba upoważniona do odbioru są tylko na liniach. Na liniach zamawiający, wykonawca i płacący są zabronieni. - Linie z produktem, ilością, specyfikacją i stanem wyceny:
NotPricedYet,EstimatedPricing(wstępna),CalculatedPricing(z rozbiciem),ArbitraryPricing(ręczna, z polem powodu). - Stany:
DRAFT→CONFIRMED→PROCESSING→FULFILLED→CLOSED, plusCANCELLEDiPENDING_ALLOCATION. Linie dodaje się tylko wDRAFT, a modyfikuje wDRAFTiCONFIRMED. Zmiana po zatwierdzeniu wymaga akceptacji.
Jeśli płatność się nie uda po alokacji towaru, zamówienie zostaje w DRAFT. Ale alokacje już istnieją. Uproszczony kod demonstracyjny repozytorium kończy się w tym miejscu wyjątkiem. W systemie produkcyjnym trzeba je zwolnić (kompensacja w stylu sagi) albo zakładać je jako blokady czasowe (HOLD), które wygasną same. Inaczej każda odrzucona karta „zjada” stan magazynu.
B2B często zaczyna od wyceny wstępnej (EstimatedPricing): „około 12 000 zł, zależnie od kursu i dostępności”. Przed zatwierdzeniem przychodzi wycena wyliczona z rozbiciem. Handlowiec może nadpisać cenę, ale tylko jako ArbitraryPricing z powodem (repozytorium ma na niego pole, ale go nie waliduje, więc wymuś niepusty powód) („negocjacje, zgoda dyrektora 14.03”). Tylko wyliczona i ręczna są ostateczne (isDefinitive). Raport „ile sprzedaliśmy poniżej cennika i dlaczego” to wtedy proste zapytanie, a nie śledztwo.
🔬 Głębiej: Order ≠ faktura ≠ płatność ≠ wysyłka
Arlow i Neustadt opisują Order jako osobny wzorzec, a płatność (Payment) jako osobny archetyp z w większości opcjonalnymi atrybutami. Jedno zamówienie może mieć trzy wysyłki, dwie faktury i pięć wpłat (zaliczka, raty, dopłata). Repozytorium szkolenia oddziela je przez porty: InventoryService, PaymentService, FulfillmentService, PricingService i BillingService. Zamówienie zna tylko wynik (zaalokowano, pobrano, status realizacji), a realizacja raportuje postęp zdarzeniem FulfillmentUpdated. Status realizacji (NOT_STARTED, IN_PROGRESS, PARTIALLY_COMPLETED, COMPLETED, FAILED) przesuwa zamówienie do PROCESSING albo FULFILLED. Kiedy wrzucisz wysyłki, faktury i wpłaty do encji zamówienia, dostaniesz boski obiekt z rozdziału o mapie archetypów.
Firma cateringowa: szkoła zamawia obiady dla 4 klas, rodzice płacą indywidualnie za swoje dzieci, kuchnia centralna przygotowuje posiłki, a woźna w każdej szkole odbiera dostawę. Rozpisz role na poziomie zamówienia i linii.
Odpowiedź
Zamówienie: ORDERER = szkoła, EXECUTOR = kuchnia centralna. Linie na dziecko (albo na klasę) mają RECEIVER i DELIVERY_CONTACT = woźna. PAYER na liniach jest w repozytorium zabroniony, a na poziomie zamówienia może być najwyżej jeden. Płatności per rodzic wymagają więc osobnych zamówień rozliczeniowych (po jednym na płacącego) albo rozszerzenia polityki ról. Warto o to zapytać biznes, zanim napiszesz kod.
- Strony w zamówieniu to migawki Party z rolą: zamawia, płaci, odbiera, wykonuje, kontakt, odbiór.
- Polityki ról działają osobno dla zamówienia i dla linii.
- Zatwierdzenie: alokacja → płatność → realizacja. Każda porażka zostawia DRAFT.
- Wycena linii ma stany, a cena ręczna niesie powód (wymuś, żeby nie był pusty).
Pieniądze i salda
Saldo to wynik, nie pole. Zapisy, transakcje, reguły księgowania i dwa zegary, które musi znać każdy system z pieniędzmi, punktami albo limitami.
Accounting: konta, zapisy, transakcje
saldo się liczy, nie zapisujeLuca Pacioli opisał podwójny zapis w 1494 roku. Od tamtej pory działa ta sama zasada: nie nadpisujesz salda, tylko dopisujesz zapisy, a każda operacja ma dwie strony, które się równoważą. Ten archetyp nie dotyczy tylko działu księgowości. Działa wszędzie, gdzie jest saldo: punkty lojalnościowe, minuty w abonamencie, limit karty flotowej, portfel w aplikacji, kaucje, środki pobrania u kuriera. Fowler w Analysis Patterns łączy go z magazynem w jednym rozdziale („Inventory and Accounting”), bo konto może trzymać ilość czegokolwiek, nie tylko pieniądze.
Accounting modeluje wszystko, co ma saldo. Saldo nie jest polem, które się nadpisuje. To suma niezmiennych zapisów na koncie, a każda operacja (transakcja) przenosi wartość między kontami tak, że nic nie ginie i nic nie powstaje z niczego.
✅ Sięgnij, gdy
- w wymaganiach jest „saldo”, „limit”, „punkty”, „portfel”, „do wykorzystania”;
- trzeba udowodnić, skąd się wzięła kwota (spory, audyt, reklamacje);
- wartości wygasają albo mają datę obowiązywania;
- jedna operacja zmienia kilka sald naraz (wpłata dzielona na kapitał, odsetki i opłaty).
⛔ Odpuść, gdy
- liczba to tylko licznik bez znaczenia finansowego i bez sporów (np. liczba wyświetleń);
- salda prowadzi zewnętrzny system (bank, ERP), a Ty tylko je wyświetlasz.
Opcje i konfiguracje
| Opcja | Co robi | Kiedy wybrać | Koszt / ryzyko |
|---|---|---|---|
| Konta bilansowe | Aktywa, zobowiązania, przychody, koszty. Transakcja na nich zawsze sumuje się do zera. | Pieniądze firmy i klientów. | Trzeba dobrać typ konta. Pieniądze klienta to zobowiązanie, a nie przychód. |
| Konta pozabilansowe | Konta poza zasadą „suma zero”. | Limity, bonusy, punkty, ewidencje pomocnicze. | Łatwo pomylić z bilansowymi. Nazwij je jasno. |
| Typy transakcji | Otwarcie, przeniesienie, odwrócenie, przealokowanie, kompensacja wygaśnięcia albo własny typ. | Zawsze. Typ odpowiada na pytanie „co to była za operacja?”. | Niski. |
| Dwie daty zapisu | Kiedy zapis zarejestrowano i od kiedy obowiązuje. | Wpłaty z datą wsteczną, operacje z przyszłą datą, salda „na dzień”. | Każde pytanie o saldo musi mówić „na kiedy”. |
| Ważność zapisu | Zapis obowiązuje do daty. Po niej niewykorzystana reszta jest jawnie przenoszona transakcją kompensującą. | Bonusy, punkty, vouchery, limity okresowe. | Ktoś musi regularnie uruchamiać wygaszanie. |
| Kolejność zużycia | Najstarsze najpierw (FIFO), najnowsze najpierw (LIFO) albo wskazane ręcznie. | Gdy zapisy mają różne daty ważności albo różne źródła. | Zmiana kolejności zmienia, co wygaśnie. |
| Reguły księgowania | Zapis na koncie automatycznie tworzy kolejne zapisy: podatek, prowizję, bonus. Reguły mają warunek, sposób liczenia i priorytet. | Powtarzalne skutki operacji, które biznes chce zmieniać bez wdrożeń. | Reguła może wywołać samą siebie. Sprawdzaj cykle. |
| Konta-projekcje | Konto „wirtualne” z filtrem na zapisach, bez własnych zapisów. | Raporty przekrojowe: przychody z jednego regionu, opłaty jednego segmentu. | Wydajność filtra przy dużej liczbie zapisów. |
| Korekty | Odwrócenie, czyli transakcja typu reversal z repozytorium, a w razie potrzeby po nim nowa, poprawna transakcja. Poza repozytorium: korekta różnicowa (Fowler) oraz storno czerwone lub czarne (polska praktyka księgowa). | Każdy błąd w zaksięgowanej operacji. | Nigdy edycja zapisu. Wybór rodzaju korekty bywa wymogiem prawa. |
| Migawka salda | Saldo zapamiętane na dzień i dalej liczone od migawki. To opcja projektowa spoza repozytorium. | Miliony zapisów na koncie. | Migawka to pamięć podręczna. Źródłem prawdy są zapisy. |
- Dzień pierwszy: konta z typem, niezmienne zapisy, transakcja sumująca się do zera, saldo liczone z zapisów, korekta przez odwrócenie.
- Sygnał „limit”, „bonus”: konta pozabilansowe.
- Sygnał „wygasa”, „na dzień”: dwie daty, ważność zapisu i kompensacja wygaśnięcia.
- Sygnał „zawsze, gdy wpłynie…, nalicz…”: reguły księgowania.
- Kolumna
saldoaktualizowana przy każdej operacji. Skutek: przy pierwszym sporze nie da się pokazać, skąd się wzięła kwota. - Edycja błędnego zapisu. Skutek: raport z wczoraj i raport z dziś pokazują różne liczby bez śladu dlaczego.
- Pieniądze klienta (pobranie, kaucja) na koncie przychodu. Skutek: zawyżony przychód i podatek od cudzych pieniędzy.
W praktyce i w repozytorium
Szkielet z repozytorium szkolenia:
- Konto (
Account) ma typ:ASSET,LIABILITY,REVENUE,EXPENSE(bilansowe, w podwójnym zapisie) alboOFF_BALANCE(pozabilansowe, poza podwójnym zapisem: bonusy, limity, ewidencje pomocnicze). - Zapis (
Entry) to uznanie (AccountCredited) albo obciążenie (AccountDebited) z kwotą, dwiema datami (zaistnienia i zastosowania), opcjonalnym okresem ważności i opcjonalnym wskazaniem zapisu, którego dotyczy (appliedTo). W konwencji repozytorium uznanie zwiększa saldo konta, a obciążenie je zmniejsza. - Transakcja grupuje zapisy, ma typ (
initialization,transfer,reversal,reallocation,expiration_compensationalbo własny) i jeden niezmiennik: suma zapisów na kontach bilansowych wynosi zero. Konta pozabilansowe są z tego wyłączone.
Firma kurierska pobiera od odbiorcy 500 zł za pobraniem, a po tygodniu przelewa je nadawcy, potrącając 5 zł prowizji. Jakie konta i jakie transakcje?
Odpowiedź
Konta: kasa/rachunek kuriera (aktywo), „pobrania do wypłaty – nadawca X” (zobowiązanie, bo to nie są pieniądze kuriera), przychód z prowizji. Transakcja 1 (doręczenie): kasa rośnie o 500, zobowiązanie wobec nadawcy rośnie o 500. Transakcja 2 (wypłata): zobowiązanie maleje o 500, kasa maleje o 495, przychód z prowizji rośnie o 5. To zmiany sald; w zapisie księgowym każda transakcja i tak sumuje się do zera. Klasyczny błąd to księgowanie pobrania jako przychodu kuriera.
- Saldo to suma zapisów. Zapisy są niezmienne, a korekta to nowa transakcja.
- Transakcja na kontach bilansowych sumuje się do zera.
- Konta pozabilansowe trzymają limity, bonusy i ewidencje bez psucia bilansu.
- Archetyp działa wszędzie, gdzie jest saldo: punkty, minuty, limity, portfele.
Reguły księgowania i konta-projekcje
zapis wywołuje zapisyFowler w Analysis Patterns opisuje regułę księgowania (posting rule): gdy na koncie pojawia się zapis, reguła z poziomu wiedzy tworzy kolejne zapisy na innych kontach. Wpływ na należności odprowadza podatek. Sprzedaż nalicza prowizję handlowcowi. Doładowanie powyżej 100 zł daje bonus. Reguła jest daną, więc nową prowizję wprowadza się konfiguracją.
W repozytorium szkolenia reguła (PostingRule) ma nazwę, warunek kwalifikacji (EligibilityCondition: konto równe X, typ zapisu, typ konta albo własny predykat, łączone przez and), kalkulator (np. stała kwota, procent), konta docelowe i priorytet (domyślnie 100). Mniejsza liczba wykonuje się wcześniej. Reguły uruchamia obsługa zdarzeń o nowych zapisach (PostingRulesEventHandler).
- Sprzedaż: 123 zł brutto = 100 zł netto (przychód) + 23 zł VAT (zobowiązanie podatkowe).
- Pełny zwrot to transakcja, która odwraca obie części: przychód −100 i VAT −23. Zwrot „123 zł z przychodu” zawyża dochód i zaniża podatek należny.
- Zwrot częściowy 123 zł z zamówienia 246 zł (200 + 46) dzieli się proporcjonalnie: −100 netto i −23 VAT.
- Reguła księgowania „zwrot → podział netto/VAT według stawki z oryginalnej sprzedaży” jest daną. Gdy zmieni się stawka VAT, stare zwroty nadal liczą się po starej, bo biorą ją z zapisu sprzedaży.
Repozytorium ma też ProjectionAccount: konto wirtualne, zdefiniowane filtrem na zapisach. Nie ma typu i nie przyjmuje zapisów. Pokazuje tylko to, co pasuje do filtra, np. „wszystkie przychody z e-mobility w województwie śląskim” albo „wszystkie opłaty naliczone klientom flotowym”. Dzięki temu raporty przekrojowe nie wymagają dodatkowych kont i podwójnego księgowania.
Reguły reagują na zapisy, a same tworzą zapisy. Reguła, której warunek obejmuje jej własne konto docelowe, wywołuje samą siebie. Zabezpieczenia: warunek wykluczający transakcje utworzone przez regułę (np. po typie lub metadanych), test konfiguracji szukający cykli w grafie „konto → reguła → konto” i limit głębokości kaskady.
- Reguła księgowania: warunek + kalkulator + konta docelowe + priorytet.
- Kolejność reguł zmienia wynik, gdy warunek jednej zależy od salda zmienianego przez drugą.
- Konta-projekcje to filtry na zapisach do raportów przekrojowych.
- Sprawdzaj konfigurację reguł pod kątem cykli.
Czas w księgowości: dwa zegary i wygasanie
„saldo na poniedziałek według wiedzy ze środy”Każdy zapis w repozytorium ma dwie daty: occurredAt (kiedy go zarejestrowano) i appliesAt (od kiedy obowiązuje). Scenariusze bitemporalne z repozytorium pokazują oba kierunki. Wpłatę zarejestrowaną w środę, ale z datą poniedziałku, widać w saldzie na poniedziałek. Zapis z datą w przyszłości nie zmienia dzisiejszego salda, dopóki ta data nie nadejdzie. Saldo „na dzień” (balanceAsOf) liczy się po dacie zastosowania.
Drugi wymiar czasu to ważność zapisu. Bonus w scenariuszu telco: w poniedziałek klient dostaje 50 zł w minutach, ważne do środy 10:00. W czwartek osobna transakcja expiration_compensation przenosi niewykorzystaną kwotę na konto „Bonusy wygasłe”. Saldo bonusu spada do zera, a firma wie dokładnie, ile i kiedy wygasło. Kolejne scenariusze: bonus częściowo wykorzystany (kompensuje się tylko reszta) i wiele bonusów naraz zużywanych w kolejności FIFO, z których każdy wygasa osobno. Limity kart flotowych z okresem ważności działają tak samo.
FIFO, LIFO i MANUAL.| Korekta | Co robi | Kiedy |
|---|---|---|
Odwrócenie (reversal) | nowa transakcja z zapisami przeciwnymi do oryginału i odwołaniem do niego (refId) | błędna transakcja w całości |
| Odwrócenie + nowa transakcja | wycofaj błędną, zaksięguj poprawną | błąd kwoty lub konta, gdy audyt chce widzieć obie wersje |
| Korekta różnicowa | zaksięguj tylko różnicę | mała zmiana kwoty, gdy liczy się czytelność obrotów |
| Storno czerwone | zapis po tej samej stronie ze znakiem minus | polska praktyka: korekta, która nie zawyża obrotów konta |
| Storno czarne | zapis po przeciwnej stronie | polska praktyka: korekta widoczna jako osobny obrót |
🔬 Głębiej: nazwy u Fowlera i pytanie audytora
Fowler w swoich materiałach o wzorcach księgowych opisuje trzy rodzaje korekt: Reversal Adjustment (odwróć i zaksięguj ponownie), Difference Adjustment (zaksięguj różnicę) i Replacement Adjustment (zastąp oryginał). Ta ostatnia jest wygodna, ale niszczy historię. Dopuszczaj ją tylko przed zamknięciem okresu.
Audytor zadaje pytanie bitemporalne: „jakie było saldo 31 marca według stanu wiedzy z 2 kwietnia?”. Żeby odpowiedzieć, filtrujesz zapisy po appliesAt ≤ 31.03 i occurredAt ≤ 2.04. Zapis wsteczny dodany 10 kwietnia zmienia saldo na 31 marca, ale nie zmienia tego, co raportowałeś 2 kwietnia. Dlatego zamknięcie okresu w praktyce oznacza „od teraz korekty idą z appliesAt w bieżącym okresie”.
- Dwa zegary: kiedy zarejestrowano (occurredAt) i od kiedy obowiązuje (appliesAt).
- Saldo „na dzień” liczy się po appliesAt. Pełny audyt filtruje po obu datach.
- Ważność zapisu + transakcja kompensująca = jawne wygasanie z historią.
- Korekty to nowe transakcje: odwrócenie, różnica, storno. Nigdy edycja zapisu.
Czas, zależności i plan
Pod harmonogramem zawsze jest graf. Pod raportem „plan kontra wykonanie” zawsze jest plan, który musi istnieć jako byt, a nie jako zapytanie.
Scheduling: pod spodem zawsze graf
kolejność, cykle, ścieżka krytycznaScheduling układa kroki w czasie na podstawie zależności między nimi („tynki po instalacjach”). Zależności tworzą graf, a daty startu i końca są wynikiem liczenia, a nie ręcznie wpisanymi polami.
findFirstCycle). Czasy trwania, daty, typy SS/FF/SF, zwłoki i ścieżkę krytyczną (klasyczna metoda CPM) dopisujesz sam.✅ Sięgnij, gdy
- w wymaganiach jest „nie wcześniej niż”, „po zakończeniu”, „równolegle z”;
- opóźnienie jednego kroku ma przesuwać kolejne;
- trzeba wiedzieć, które kroki są krytyczne, a które mają zapas;
- kroki się wykluczają (ta sama sala, ta sama ekipa) albo na siebie wpływają.
⛔ Odpuść, gdy
- kroki nie zależą od siebie, liczy się tylko termin każdego z nich;
- kolejność jest zawsze ta sama i zapisana w procesie (np. stałe etapy obsługi zgłoszenia).
Opcje i konfiguracje
| Opcja | Co robi | Kiedy wybrać | Koszt / ryzyko |
|---|---|---|---|
| Graf zależności | Kroki to wierzchołki, zależności to krawędzie. Kolejność wynika z porządku topologicznego. | Zawsze, gdy kroki zależą od siebie. | Niski. |
| Typ zależności: koniec–start (FS) | B zaczyna się po końcu A. | Najczęstszy przypadek. | Niski. |
| Typy SS, FF, SF (poza repozytorium) | Start–start, koniec–koniec, start–koniec. | Prace równoległe z przesunięciem, odbiory, zmiany wart. | Trudniejsze do wyjaśnienia użytkownikom. |
| Zwłoka, lag (poza repozytorium) | Wymagany odstęp na zależności, np. 28 dni dojrzewania betonu. | Czasy technologiczne, okresy oczekiwania. | Trzeba ustalić, czy zwłoka liczy się w dniach kalendarzowych, czy roboczych. |
| Wykrywanie cykli | Odrzuca zależność, która tworzy pętlę. | Zawsze, gdy zależności wpisują ludzie lub integracje. | Sprawdzaj przy zapisie, a nie przy liczeniu. |
| Ścieżka krytyczna i zapas | Najdłuższa ścieżka wyznacza koniec. Zapas mówi, o ile krok może się spóźnić. | Projekty, budowy, wdrożenia. | Wymaga czasów trwania kroków. |
| Kolorowanie konfliktów | Kroki, które się wykluczają, dostają różne „kolory” (sale, ekipy, środowiska). | Planowanie egzaminów, środowisk testowych. | Szybki algorytm daje górną granicę, a nie zawsze minimum. |
| Składowe i punkty artykulacji | Grupy elementów, które na siebie wpływają, i elementy, które je łączą. | Analiza wpływu zmian w rezerwacjach. | Poziom 3. |
| Cykl zamian | Wykrywa łańcuch „A chce slotu B, B slotu C, C slotu A” i wykonuje go paczką. | Zamiany terminów, wymiany. | Cała paczka musi być jedną transakcją. |
- Dzień pierwszy: kroki z czasem trwania, zależności koniec–start, wykrywanie cykli przy zapisie, daty liczone z grafu.
- Sygnał „równolegle, ale z przesunięciem”: typy SS i FF oraz zwłoka.
- Sygnał „co nam opóźni koniec?”: ścieżka krytyczna i zapas.
- Sygnał „nie mogą iść naraz”: graf konfliktów i kolorowanie.
- Daty startu i końca jako jedyne dane. Skutek: każde opóźnienie to ręczne przesuwanie wszystkiego.
- Brak sprawdzania cykli. Skutek: harmonogram „liczy się w nieskończoność” albo pokazuje bzdury.
- Mylenie harmonogramu z dostępnością. Skutek: plan zakłada salę, która jest zajęta.
W praktyce i w repozytorium
Strona szkolenia: „Tworzysz złożony harmonogram. […] Pod spodem to zawsze graf zależności”. Przykłady stamtąd to planowanie zadań na budowie i ścieżka nauki nowej technologii, a domeny to logistyka, edukacja i finanse. Wierzchołki to kroki, krawędzie to zależności, a harmonogram to porządek topologiczny z czasami.
Ten aparat ma długą historię. Metodę ścieżki krytycznej (CPM) opracowali pod koniec lat 50. James Kelley z Remington Rand i Morgan Walker z DuPont. Równolegle marynarka wojenna USA stworzyła PERT dla programu rakiet Polaris. Współczesne narzędzia do harmonogramów używają metody diagramów następstw (PDM) z czterema typami zależności:
| Typ | Znaczenie | Przykład z budowy |
|---|---|---|
| FS finish-to-start | B zaczyna się po końcu A | tynki po instalacjach |
| SS start-to-start | B zaczyna się po starcie A (z opóźnieniem lub bez) | hydraulika rusza 2 dni po elektryce, potem idą równolegle |
| FF finish-to-finish | B kończy się po końcu A | odbiór instalacji kończy się po ostatnim podłączeniu |
| SF start-to-finish | B kończy się po starcie A | stara ochrona obiektu kończy, gdy nowa zaczyna |
Do tego dochodzi zwłoka (lag). Beton fundamentów potrzebuje czasu na dojrzewanie. Jego wytrzymałość projektową określa się zwykle po 28 dniach. Moduł graphs w repozytorium szkolenia ma typ zależności z dowolnymi cechami (DependencyType z gotowym finishToStart), wykrywanie cykli przeszukiwaniem w głąb (findFirstCycle) oraz testy harmonogramów: liniowy, złożony i „diament” (dwie równoległe gałęzie, które się łączą).
Wdrożenie nowego pracownika: konto w AD, laptop, szkolenie BHP, dostęp do repozytorium (wymaga konta), szkolenie z produktu (wymaga laptopa i dostępu), pierwszy ticket (wymaga obu szkoleń). Które kroki mogą iść równolegle i co jest na ścieżce krytycznej, jeśli laptop dociera 5 dni, a konto zakłada się 1 dzień?
Odpowiedź
Równolegle: konto, laptop i BHP od dnia 0. Dostęp do repozytorium po koncie (dzień 1+). Szkolenie produktowe czeka na laptopa (dzień 5), więc ścieżka krytyczna to laptop → szkolenie produktowe → pierwszy ticket. Zakładamy, że nadanie dostępu do repozytorium zajmuje mniej niż 4 dni. Wtedy przyspieszanie zakładania konta niczego nie zmieni. Zamów laptop wcześniej.
- Harmonogram = graf zależności + porządek topologiczny + czasy.
- Typy zależności: FS, SS, FF, SF, z opóźnieniem.
- Ścieżka krytyczna to najdłuższa ścieżka. Opóźnienie poza nią zjada zapas.
- Cykle wykrywaj przy zapisie zależności.
Algorytmy grafowe w biznesie
kolorowanie, składowe, punkty artykulacji i cykle zamianModuł graphs repozytorium szkolenia pokazuje, że „graf” to nie tylko harmonogram. Te same algorytmy rozwiązują problemy, które w biznesie brzmią zupełnie inaczej:
| Pytanie biznesowe | Graf | Algorytm | W repozytorium |
|---|---|---|---|
| Ilu środowisk testowych (sal, ekip) potrzebujemy, skoro część kroków się wyklucza? | graf konfliktów | kolorowanie wierzchołków | Concurrency (zachłanne kolorowanie z JGraphT) |
| Które rezerwacje muszą negocjować razem, bo na siebie wpływają? | graf wpływów | spójne składowe | InfluanceAnalyzer, InfluenceZone |
| Które laboratoria wpływają na siebie przez sąsiedztwo i rodzaj procesu (np. drgania)? | sąsiedztwo × procesy | iloczyn grafów (procesy × sąsiedztwo) | PhysicsInfluence, LaboratoryAdjacency |
| Której rezerwacji nie wolno ruszyć, bo łączy dwie grupy? | graf wpływów | punkty artykulacji | BridgingReservations |
| A chce slotu B, B chce slotu C, C chce slotu A. Jak to zrobić? | graf „kto czyj slot chce” | wykrycie cyklu + wykonanie paczką | BatchReservationUseCase |
| Jak klient może dojść do rabatu? Najtaniej czy najszybciej? | stany i warunki | ścieżki, ścieżki ważone | CustomerPath, testy WaysToAchieve, WeightedPaths |
Najbardziej zawiłym przypadkiem są zamiany w cyklu. Każda pojedyncza zmiana jest niemożliwa, bo docelowy slot jest zajęty. Cała paczka jest możliwa. Ten sam kształt ma wymiana nerek między parami dawca–biorca. Za prace o projektowaniu takich rynków Alvin Roth i Lloyd Shapley dostali w 2012 roku Nagrodę Nobla z ekonomii. W repozytorium przypadek użycia buduje graf próśb o zmianę, znajduje prośby zależne, najpierw zwalnia wszystkie sloty źródłowe, a potem przydziela docelowe.
BatchReservationUseCase z repozytorium. W prawdziwym systemie cała paczka musi być jedną transakcją.Minimalna liczba kolorów grafu (liczba chromatyczna) to problem NP-trudny. Zachłanne kolorowanie z repozytorium daje dobrą, szybką górną granicę: „wystarczy najwyżej tyle środowisk”, ale nie zawsze „mniej się nie da”. Kolejność odwiedzania wierzchołków zmienia wynik. Dla planowania sal egzaminacyjnych albo stanowisk testowych to zwykle wystarcza. Raport powinien jednak mówić „potrzeba co najwyżej N”, a nie „potrzeba dokładnie N”.
- Konflikty → kolorowanie. Wpływy → składowe. Krytyczne powiązania → punkty artykulacji.
- Zamiany w cyklu wykonuje się paczką: najpierw zwolnij wszystkie źródła, potem przydziel cele, w jednej transakcji.
- Ścieżki w grafie stanów odpowiadają na pytanie „jak klient może dojść do X”.
Plan vs Execution: plan musi istnieć
„jaki był plan wczoraj?”Plan vs Execution trzyma plan jako osobny, zapisany byt (najlepiej z wersjami), a wykonanie jako fakty. Porównanie obu daje deltę według jawnej reguły tolerancji: co zgodne, co spóźnione, czego brakuje, co ponad plan.
✅ Sięgnij, gdy
- w wymaganiach jest „planowaliśmy, a wyszło”, „harmonogram”, „odchylenie”, „zaległość”;
- trzeba odtworzyć, jaki plan obowiązywał w danym dniu;
- od wyniku porównania zależą pieniądze lub prawo (odsetki, kary, monity, premie);
- biznes chce sprawdzać scenariusze „co, jeśli zmienimy plan”.
⛔ Odpuść, gdy
- nikt nie pyta o przeszłe plany, a porównanie jest tylko informacyjne;
- plan nie zmienia się w trakcie, a wykonanie jest zawsze „tak albo nie” (np. lista kontrolna).
Opcje i konfiguracje
| Opcja | Co robi | Kiedy wybrać | Koszt / ryzyko |
|---|---|---|---|
| Plan jako byt z wersjami | Plan jest zapisany. Zmiana planu tworzy nową wersję z datą i powodem. Repozytorium trzyma tylko bieżący plan: wersje to zalecane rozszerzenie. | Zawsze, gdy ktoś zapyta o plan z przeszłości. | Trzeba zdecydować, kto może zatwierdzić nową wersję. |
| Tolerancja dokładna | Zgodne tylko identyczne kwoty i daty. | Rzadko. Pokazuje, ile „szumu” jest w danych. | Prawie wszystko wygląda na odchylenie. |
| Tolerancja kwoty | Zgodne, gdy różnica kwot nie przekracza progu (np. 5 gr). | Wpłaty z zaokrągleniami, prowizje banków. | Próg to decyzja biznesowa z konsekwencjami. |
| Tolerancja daty | Zgodne, gdy różnica dat nie przekracza N dni. | Karencja, weekendy, sesje rozliczeniowe. | Jak wyżej. |
| Tolerancja ilości lub procentu | Zgodne, gdy różnica ilości mieści się w sztukach albo procentach. | Produkcja, dostawy, zużycie energii. | Jak wyżej. |
| Tolerancja łączona | Wszystkie warunki naraz, np. „do 5 gr i do 3 dni”. | Harmonogramy płatności. | Trudniej wyjaśnić, który warunek nie przeszedł. |
| Wpłaty częściowe | Suma kilku wpłat może pokryć jedną ratę. | Klienci płacący ratę w częściach. | Trzeba ustalić, której racie przypisać nadwyżkę. |
| Wynik porównania (delta) | Dopasowane pary, pozycje planu bez wykonania, wykonania spoza planu i statystyki. | Zawsze. | Niski. |
| Rozdzielczość porównania | Wykonanie sumuje się do szczegółowości planu (np. dni do miesiąca). | Plan miesięczny, wykonanie dzienne. | Trzeba ustalić, co się liczy (np. poprawki tak, braki nie). |
| Symulacje i modyfikatory | Modyfikator dostaje plan i deltę, a zwraca nowy plan: bufor, rozłożenie reszty, usunięcie raty. W repozytorium nowy plan zastępuje aktywny. Symulację na kopii dopisujesz sam. | „Co, jeśli zaplanujemy więcej?”, restrukturyzacja. | Symulacja nie może nadpisać planu. Zatwierdzona to nowa wersja. |
- Dzień pierwszy: plan zapisany jako byt, wykonanie jako fakty, jedna tolerancja (kwoty albo daty), wynik z dopasowaniami i brakami.
- Sygnał „plan się zmienia”: wersje planu z datą i powodem.
- Sygnał „płacą w częściach”, „do 3 dni to nie spóźnienie”: tolerancje łączone i wpłaty częściowe.
- Sygnał „plan miesięczny, dane dzienne”, „co, jeśli”: agregacja do rozdzielczości planu i symulacje.
- Plan liczony zapytaniem z bieżących ustawień. Skutek: zmiana SLA zmienia wstecz plan wszystkich otwartych spraw.
- Tolerancja wpisana w kod raportu. Skutek: wczorajszy i dzisiejszy raport różnią się bez wyjaśnienia.
- Porównywanie dnia z dniem, gdy plan jest miesięczny. Skutek: same „odchylenia”, choć miesiąc się zgadza.
W praktyce i w repozytorium
Repozytorium szkolenia zaczyna ten moduł od antywzorca. Serwis „liczy” planowaną datę dostawy z SLA klienta, pojemności magazynu, kalendarza dni roboczych i dostępności kierowców. Plan nie jest bytem, tylko wnioskiem z zapytania. Gdy ktoś zmieni SLA klienta z 3 na 5 dni, plan wszystkich otwartych dostaw zmienia się wstecz. Nie da się odpowiedzieć na pytania: jaki był plan wczoraj, dlaczego się zmienił, czy to była decyzja biznesowa, czy poprawka błędu. Nie da się też porównać dzisiejszego wykonania z wczorajszym planem.
Fowler w Analysis Patterns poświęca planowaniu cały rozdział i oddziela działanie zaproponowane (proposed action) od zrealizowanego (implemented action). Repozytorium szkolenia robi to samo dla harmonogramów płatności i produkcji. Plan to osobny byt z wersjami. Wykonanie to fakty: wpłaty, wyprodukowane partie. Delta to wynik porównania według jawnej strategii tolerancji.
| Tolerancja | Dopasowuje, gdy… | Kiedy |
|---|---|---|
ExactMatch | kwota i data są identyczne | rzadko: pokazuje, ile „szumu” jest w danych |
MoneyTolerance | różnica kwoty ≤ X (np. 5 gr) | wpłaty z zaokrągleniami, prowizje banków |
DateTolerance | różnica dat ≤ N dni | okres karencji, weekendy, sesje rozliczeniowe |
QuantityTolerance, PercentageTolerance | różnica ilości w sztukach lub procentach | produkcja, dostawy, zużycie energii |
CombinedTolerance / and | wszystkie warunki naraz | „do 5 gr i do 3 dni” |
PartialPaymentsStrategy | suma wpłat częściowych pokrywa ratę | klient płaci ratę w dwóch przelewach |
Moduły analizy w repozytorium zwracają DeltaResult: dopasowane pary plan–wykonanie, pozycje planu bez wykonania, wykonania spoza planu i statystyki (np. kwoty niedopłat i nadpłat, liczba wpłat spóźnionych). Moduł z antywzorcem ma dodatkowo enum DeltaType, który dobrze nazywa możliwe wyniki porównania: PERFECT_MATCH, LATE, EARLY, UNDER_DELIVERED, OVER_DELIVERED, DEVIATION, NO_EXECUTION. Tych nazw używa diagram poniżej.
Tolerancja to decyzja biznesowa z konsekwencjami prawnymi. Czy wpłata 2 dni po terminie to opóźnienie, od którego liczysz odsetki? Czy niedopłata 3 grosze to zaległość, która uruchamia monit? Zapisz tolerancję jako konfigurację z wersją. Inaczej po zmianie progu nie wytłumaczysz, dlaczego wczorajszy raport różni się od dzisiejszego.
- Plan jest bytem z wersjami, a nie wynikiem zapytania po bieżących ustawieniach.
- Wykonanie to fakty. Delta to porównanie według jawnej strategii tolerancji.
- Wynik porównania: dopasowania, braki wykonania, wykonania spoza planu i statystyki. Nazwy rodzajów delty: idealnie, spóźnione, przedwczesne, za mało, za dużo, odchylenie, brak wykonania.
- Tolerancja to decyzja biznesowa. Wersjonuj ją.
Rozdzielczość planu i symulacje „co jeśli”
plan miesięczny, wykonanie dzienneKomentarz z repozytorium szkolenia streszcza problem jednym zdaniem. Plan jest „uproszczony, z góry”: 300 sztuk w miesiącu. Wykonanie jest „szczegółowe, z dołu”: 270 + 12 braków + 18 poprawek w dniach 2, 4, 7, 12. Porównanie dnia z dniem nie ma sensu, bo plan nie ma dni. Porównanie miesiąca z miesiącem wymaga zagregowania wykonania do rozdzielczości planu i ustalenia, co się liczy: czy poprawki to produkcja? Czy braki odejmujesz?
Druga połowa modułu to symulacje. Modyfikator harmonogramu przyjmuje bieżący plan i wynik delty, a zwraca nowy plan. Rzeczywistości nie zmienia. Repozytorium ma m.in.:
IncreaseBufferModifier: „co, jeśli zaplanujemy o X% więcej, żeby nadrobić niedobór?”;SpreadRemainingAmountModifier: rozłóż pozostałą kwotę na N rat, zachowując sumę (w scenariuszu: spóźniona pierwsza rata z 5 po 100 zł → pozostałe 400 zł na 3 raty, suma nadal 500 zł);RemoveInstallmentModifier: usuń ratę, np. jako nagrodę za terminowość;- reguły modyfikacji z warunkiem (spóźniona płatność, płatność na czas, niedobór produkcji), stosowane tylko raz.
- Porównuj w rozdzielczości planu: agreguj wykonanie i ustal, co się liczy.
- Modyfikator dostaje plan i deltę, a zwraca nowy plan. Rzeczywistość zostaje nietknięta.
- Zatwierdzona symulacja to nowa wersja planu, a nie nadpisanie starej.
Studia przypadków
Cztery zawiłe biznesy rozebrane na archetypy: zdanie z wymagań → archetyp → konfiguracja → pułapka. W każdym rozdziale przycisk 💥 pokazuje, jak wyglądałby model „z rzeczowników”.
Leasing floty aut
kto prowadził auto 12 marca o 14:05?Leasingodawca finansuje 120 aut dla firmy dystrybucyjnej. Podpisuje umowę ramową, a pod nią umowy wykonawcze na każde auto. Auta jeżdżą z pracownikami klienta, którzy się zmieniają. Do tego dochodzą karty paliwowe z limitami, serwisy, opony sezonowe, auta zastępcze, rozliczenie przebiegu po zwrocie i zdarzenia „spoza umowy”: mandaty, szkody, wcześniejsze zakończenie. Biznes wygląda jak jeden produkt. W rzeczywistości dotyka prawie każdego archetypu.
- Kierowca jako pole auta. Kolumna
auto.kierowcaodpowiada tylko na pytanie „kto jeździ dziś”. Wezwanie po mandacie pyta o dzień i godzinę sprzed miesięcy. Potrzebna jest relacja „użytkuje” z okresem ważności. - Rata jako liczba w umowie. Rata jest wynikiem kalkulacji z parametrów. Bez rozbicia (finansowanie, serwis, opony, ubezpieczenie) nie przeliczysz jej przy aneksie, gdy klient zmieni limit kilometrów.
- Limit karty jako kolumna. „Nie przechodzi na kolejny miesiąc” wymaga zapisu z ważnością i kompensacji. Inaczej nie odróżnisz kierowcy, który oszczędzał, od kierowcy, któremu limit wygasł.
- Party z relacjami i ważnością. To fundament mandatów, kart i uprawnień fleet managera.
- Product: typ umowy wykonawczej jako pakiet (finansowanie + usługi), auto jako egzemplarz po VIN.
- Pricing: komponenty raty z zależnościami. Nadprzebieg jako cena marginalna za km.
- Accounting + Plan vs Execution: harmonogram rat, wpłaty, limity kart.
- Inventory aut zastępczych na końcu. To dobrze odizolowany moduł.
Telco: oferta rodzinna i migracja taryf
jeden płaci, pięciu dzwoni, taryfa znika z ofertyOperator sprzedaje ofertę rodzinną: do pięciu numerów na jednym koncie. Właściciel konta płaci, a członkowie rodziny korzystają. Do numeru można dokupić telefon na raty, ale flagowy model tylko z abonamentem premium. Za rok operator wycofuje taryfę „Smart 2019” i proponuje „Smart 2026”. Część klientów przechodzi w środku okresu rozliczeniowego, część zostaje na starej taryfie z nową ceną od 1. dnia kolejnego miesiąca. Do tego bonusy z datą ważności, roaming z limitem i przeniesienie numeru do innego operatora w zaplanowanym oknie.
- „Abonent” jako jedna osoba. Właściciel umowy, płatnik i użytkownik numeru to trzy role. Dziecko korzysta z numeru, a rodzic za nie płaci.
- Edycja taryfy zamiast nowej wersji. Zmiana ceny „Smart 2019” to nowa wersja komponentu od daty. Edycja w miejscu przelicza zamknięte okresy rozliczeniowe.
- Migracja jako UPDATE. Przejście na nową taryfę to nowy egzemplarz produktu od daty i zakończenie starego. Proporcjonalne naliczenie wynika wtedy z dwóch okresów ważności, a nie z if-a w fakturowaniu.
Szpital: zabieg planowy
sala, zespół, sprzęt, krew, łóżko — wszystko albo nicZabieg planowy wymaga naraz: sali operacyjnej w oknie czasowym, chirurga z odpowiednią specjalizacją, anestezjologa, konkretnego sprzętu, zarezerwowanych jednostek krwi danej grupy i łóżka na oddziale na kilka nocy po zabiegu. Wcześniej pacjent musi mieć badania, które są ważne tylko przez określony czas. Pacjenci czekają w kolejce z priorytetem medycznym, a szpital ma umowę z płatnikiem na określoną liczbę świadczeń w kwartale. W Polsce publiczne świadczenia szpitalne rozlicza się z NFZ w grupach JGP (Jednorodne Grupy Pacjentów), a prywatni pacjenci mają osobny cennik.
- Rezerwacje po kolei. Sala zarezerwowana, anestezjolog niedostępny, sala wisi zablokowana. Zespół i sprzęt to zasób złożony blokowany atomowo, z blokadą czasową na czas kompletowania.
- Krew jako licznik. „Mamy 12 jednostek A Rh+” nie wystarczy. Jednostki mają partie i daty ważności, a przy rezerwacji trzeba brać te, które wygasają najwcześniej.
- Kontrakt jako raport. Plan kwartalny wobec płatnika to byt z wersjami (aneksy), a wykonanie agreguje się do kwartału. Porównanie dzień do dnia nie ma sensu.
Budowa: harmonogram i odchylenia
dźwig, beton, deszcz i roboty dodatkoweGeneralny wykonawca stawia budynek biurowy dla inwestora. Ma kilkunastu podwykonawców, dźwig wieżowy dzielony między brygady, dostawy materiałów w oknach czasowych (centrum miasta, wąska ulica), kosztorys z przedmiarem, roboty dodatkowe zlecane w trakcie, płatności etapowe po odbiorach i zatrzymaną część wynagrodzenia jako zabezpieczenie. Inwestor co miesiąc pyta, o ile jesteśmy w plecy i co by było, gdyby padało jeszcze dwa tygodnie.
- Harmonogram w Excelu jako źródło prawdy. Daty bez grafu zależności nie przeliczą się po opóźnieniu, a „o ile jesteśmy w plecy” wymaga wersji planu bazowego.
- Robota dodatkowa jako edycja kosztorysu. Zmiana zakresu to nowa pozycja (zamówienie) z ceną ustaloną i powodem. Pierwotny kosztorys zostaje jako plan bazowy.
- Zabezpieczenie jako „pomniejszenie faktury”. Zatrzymana kwota to zobowiązanie z terminem zwrotu, a nie rabat. Ma swoje konto i swoją datę ważności.
Mistrzostwo
Kiedy archetyp szkodzi, jak wybrać właściwy w pięć pytań, słownik pojęć i mapa literatury.
Antywzorce i kiedy NIE stosować archetypów
objaw → diagnoza → terapiaArchetypy leczą konkretne choroby. Podane bez choroby szkodzą jak każdy lek. Poniżej są objawy, które widać w kodzie i w bazie, z diagnozą i terapią. Przycisk 💥 pokazuje typowe leczenie objawowe: poprawkę, która uspokaja dziś i pogarsza jutro.
Kiedy nie stosować
| Sytuacja | Rekomendacja (heurystyka) | Dlaczego |
|---|---|---|
| Prosta aplikacja CRUD: jedna rola, brak historii, brak wariantów | zwykłe encje | żaden sygnał z rozdziału o rozpoznawaniu nie występuje, więc archetyp to tylko koszt |
| MVP do sprawdzenia hipotezy | od razu tylko tanie elementy: identyfikatory zamiast obiektów, migawki w zamówieniach, kwoty z walutą | to niemal nic nie kosztuje dziś, a później trudno to dodać |
| Poddziedzina generyczna (np. księgowość finansowa firmy) | kup lub zintegruj gotowy system; archetyp służy do mapowania na granicy | Evans przy poddziedzinach generycznych zaleca rozważyć gotowe rozwiązanie, zamiast budować je od zera |
| Zespół nie rozumie archetypu, ale „tak było na szkoleniu” | najpierw rozbiór wymagań (jak w studiach przypadków), dopiero potem klasy | kopiowanie struktury bez zrozumienia tworzy martwe abstrakcje |
| Archetyp „na zapas” dla wariantu, którego nikt nie zamówił | zostaw szew (interfejs, identyfikator), bez implementacji | Arlow i Neustadt oznaczają części archetypu jako opcjonalne właśnie po to, żeby je pomijać |
Model „wszystko jest Entity z listą Attribute(name, value)” wygląda na maksymalnie elastyczny archetyp. Nie jest nim. Archetyp ma nazwane pojęcia z regułami (rola, relacja z ważnością, wersja ceny, blokada z właścicielem). EAV ma tylko worek wartości, a reguły uciekają do kodu, który ten worek interpretuje. Archetyp przenosi do danych parametry znanych mechanizmów. EAV przenosi do danych wszystko, łącznie z tym, czego nikt nie umie potem przeczytać.
- Archetyp leczy konkretne objawy: role w kolumnach, cenę w polu produktu, saldo w kolumnie, plan jako zapytanie.
- Bez objawów zwykła encja wygrywa.
- Tanie elementy (identyfikatory, migawki, Money) stosuj od początku. Drogie dopiero, gdy pojawi się sygnał.
- Archetyp to nazwane pojęcia z regułami, a nie generyczny worek atrybutów.
Który archetyp i jaka konfiguracja?
drzewo decyzyjne w kilku pytaniachTo pełna wersja drzewa. Prostsza, dla początkujących, jest w rozdziale Mapa decyzji na start. Drzewo zbiera heurystyki z całego kompendium. Zaczyna od pytania „co modelujesz?” i schodzi do konkretnej konfiguracji: strategii śledzenia, modelu dostępności, rodzaju korekty. Jedno przejście daje jeden archetyp. Prawdziwy system przechodzi drzewo wiele razy, raz dla każdego zdania z wymagań.
Nie musisz pamiętać drzewa. Pamiętaj trzy pytania, które otwierają większość gałęzi: „a co, jeśli to samo X jest jednocześnie Y?” (Party, role), „jak było 3 miesiące temu?” (wersje, ważność, dwa zegary) i „co, jeśli dwie osoby chcą tego samego naraz?” (Inventory, blokady).
Słownik pojęć i mapa literatury
PL ↔ EN, i gdzie czytać dalejPolskie terminy prowadzą do rozdziałów, w których pojęcie jest wyjaśnione od podstaw (blok 🔰 „Co to jest”). Najprostsze definicje z analogiami są w słowniczku startowym.
| Polski | Angielski (repozytorium / literatura) | Znaczenie |
|---|---|---|
| strona, podmiot | Party (Person, Organization) | identyfikowalna osoba lub organizacja |
| rola strony | Role, PartyRole | kapelusz, w którym strona występuje |
| relacja między stronami | PartyRelationship; Fowler: Accountability | nazwane powiązanie dwóch ról z okresem ważności |
| kompetencja, zakres działania | Capability, OperatingScope | co strona potrafi, gdzie, kiedy, ile, na jakim poziomie |
| typ produktu, egzemplarz | ProductType, ProductInstance | opis katalogowy a konkretna rzecz, umowa lub wykonanie usługi |
| strategia śledzenia | ProductTrackingStrategy | unikat, numer seryjny, partia, oba, zamienne |
| pakiet, zestaw, reguła wyboru | PackageType, ProductSet, SelectionRule | produkt złożony z nazwanych zestawów z regułami |
| komponent ceny, kalkulator | Component, Calculator | nazwany element ceny i funkcja, która go liczy |
| interpretacja ceny | Interpretation: TOTAL, UNIT, MARGINAL | cena całkowita, średnia jednostkowa, cena n-tej jednostki |
| ważność | Validity (validFrom, validTo) | okres, w którym coś obowiązuje |
| predykat, aplikator, strażnik | predicate, applier, guardian | czy reguła dotyczy, jak zmienia, czy wynik jest dopuszczalny |
| dostępność: indywidualna, pula, czasowa | Individual/Pool/TemporalResourceAvailability | egzemplarz, ilość z pojemności, zasób w slocie |
| blokada, lista oczekujących | Blockade, LockDuration, WaitList | zajęcie zasobu przez właściciela na czas i kolejka z polityką |
| role w zamówieniu | RoleInOrder: ORDERER, PAYER, RECEIVER, EXECUTOR… | kto zamawia, płaci, odbiera, wykonuje |
| migawka | snapshot, PartySnapshot | kopia danych z chwili zdarzenia |
| konto, zapis, transakcja | Account, Entry, Transaction | saldo jako suma niezmiennych zapisów |
| reguła księgowania | PostingRule | zapis wywołuje kolejne zapisy |
| czas zdarzenia / czas zapisu | appliesAt / occurredAt; Fowler: actual / record time | od kiedy obowiązuje / kiedy się dowiedzieliśmy |
| odwrócenie, storno | reversal | korekta przez nową transakcję przeciwną |
| ścieżka krytyczna | critical path (CPM) | najdłuższa ścieżka w grafie zadań |
| tolerancja, delta | ToleranceStrategy, DeltaResult | jak porównać plan z wykonaniem i jaki jest wynik |
| poziom wiedzy | knowledge level (Fowler, Evans) | typy i reguły, które definiują dozwolone fakty |
| wariant archetypu | pleomorph (Arlow i Neustadt) | dopasowana do biznesu odmiana wzorca archetypów |
Mapa literatury
| Źródło | Co daje | Czytaj, gdy… |
|---|---|---|
| Szkolenie i repozytoria Archetypy Oprogramowania (Słota, Pilimon, Sobótka) | 11 modułów kodu w Javie, scenariusze z wielu branż, ewolucja „od if-ów do konfiguracji” | chcesz zobaczyć działający kod i testy scenariuszowe |
| Arlow, Neustadt, Enterprise Patterns and MDA (2004) | definicje archetypu i wzorca archetypów, pleomorfizm, Party, PartyRelationship, CRM, Product, Inventory, Order, Quantity, Money, Rule | potrzebujesz pełnych modeli UML i języka do rozmowy o wariantach |
| Fowler, Analysis Patterns (1997) | Accountability, Observations and Measurements, Inventory and Accounting, Planning, Trading; poziom wiedzy | modelujesz organizacje, księgowanie, plany i pomiary |
| Fowler, martinfowler.com | wzorce księgowe (posting rules, korekty), historia bitemporalna, Money (w PoEAA) | projektujesz salda, korekty i dwa zegary |
| Coad, Lefebvre, De Luca, Java Modeling in Color with UML (1999) | cztery archetypy kolorowe: moment-interval, role, description, party/place/thing | chcesz szybko klasyfikować klasy na tablicy z biznesem |
| Evans, Domain-Driven Design (2003); Vernon, Implementing DDD (2013) | bounded contexts, język wszechobecny, knowledge level, specyfikacja | wyznaczasz granice, w których archetypy żyją |
| Silverston, The Data Model Resource Book | uniwersalne modele danych: Party, Party Role, Party Relationship, Contact Mechanism, Product | projektujesz schemat bazy, a nie tylko model obiektowy |
Egzamin i ściąga
sprawdź, co zostałoNajpierw pytania dla początkujących: po jednym na rozdział Części 0 i na każdy archetyp. Potem jedno pytanie na rozdział. Błędne odpowiedzi to nieporozumienia, które rozdziały próbowały rozbroić. Pytania oznaczone (L3) i (L4) dotyczą bloków eksperckich i studiów przypadków.
Ściąga
| Archetyp / element | W jednym zdaniu | Sygnał w wymaganiach | Konfiguracje i decyzje |
|---|---|---|---|
| Quantity / Money | liczba zawsze z jednostką, kwota zawsze z walutą | liczba z jednostką lub walutą | wartość + jednostka; brak cichej konwersji; alokacja zamiast dzielenia; reguła zaokrągleń |
| Party | osoba albo organizacja w wielu rolach | ta sama osoba/firma w wielu tabelach | Person/Organization(Company, Unit); role przez politykę; identyfikatory z polityką; adresy z użyciami |
| PartyRelationship | nazwane powiązanie dwóch ról z okresem ważności | „kto był … w marcu?” | relacja ról + nazwa + Validity; polityka relacji; udział lub zakres jako rozszerzenie (w repozytorium relacja ich nie ma) |
| Capability | co strona potrafi, gdzie, kiedy, ile i na jakim poziomie | uprawnienia, region, poziom, „kto może” | 7 rodzajów OperatingScope; RoleRequirements; ważność sprawdzana w chwili przydziału |
| Product | typ z katalogu i konkretny egzemplarz | numer seryjny, partia, wariant, katalog | typ vs egzemplarz; cechy z ograniczeniami; UNIQUE / INDIVIDUALLY / BATCH / BOTH / IDENTICAL |
| Package | produkt z zestawów i reguł wyboru | „dokładnie jeden”, „najwyżej dwa”, „tylko z…” | ProductSet + SelectionRule (single, optional, required, isSubsetOf, and/or/not, ifThen); relacje produktów |
| Pricing | cena jako drzewo nazwanych składników | „cena zależy od…” | drzewo komponentów; kalkulatory; zależności (ValueOf/SumOf…); TOTAL/UNIT/MARGINAL |
| Wersje cen | cena z okresem obowiązywania i nakładkami | „ile kosztowało wtedy?” | validFrom/validTo + definedAt; najmłodszy validFrom wygrywa; REJECT_IDENTICAL / REJECT_OVERLAPPING / ALLOW_ALL |
| Rules | wyjątek jako warunek, zmiana i strażnik | „chyba że”, promocje, wyjątki | predykat + aplikator (od bazy / od wyniku) + strażnik; łańcuch; algebry: logiczna, rozmyta, punktowa, wyjaśniająca |
| Inventory | co jest wolne i kto to zablokował | „czy jest wolne?”, rezerwacja | Individual / Pool / Temporal; grupowanie slotów; zasób złożony (wszystko albo nic) |
| Blokady i kolejka | zajęcie z właścicielem i czasem, kolejka z polityką | koszyk, przedsprzedaż, „kto dostanie zwolnione” | LockDuration (czasowa/bezterminowa); releaseExpired; WaitList: FIFO / priorytet / kwota / kryterium |
| Ordering | zlecenie ze stronami w rolach, liniami, wyceną i stanami | kto zamawia, płaci, odbiera; statusy | role na zamówieniu i liniach; migawki; DRAFT→CONFIRMED→(PENDING_ALLOCATION)→PROCESSING→FULFILLED→CLOSED, albo CANCELLED (w repozytorium PENDING_ALLOCATION i CLOSED są w enumie, ale Order nie wykonuje do nich przejść); stany wyceny linii |
| Accounting | saldo jako suma niezmiennych zapisów | saldo, limit, punkty, portfel | konta (ASSET, LIABILITY, REVENUE, EXPENSE, OFF_BALANCE); transakcja = 0 na bilansowych; korekty jako transakcje |
| Posting rules | zapis, który wywołuje kolejne zapisy | „gdy wpłynie, to nalicz…” | warunek + kalkulator + cel + priorytet; konta-projekcje; ochronę przed cyklami trzeba dodać samemu (repozytorium jej nie ma) |
| Czas w księgowości | kiedy zarejestrowano, od kiedy obowiązuje, do kiedy ważne | „na dzień”, „wstecz”, „wygasa” | occurredAt vs appliesAt; balanceAsOf; ważność zapisu + expiration_compensation; FIFO / LIFO / MANUAL |
| Scheduling | harmonogram jako graf zależności | „nie wcześniej niż…”, kolejność | graf + porządek topologiczny; FS/SS/FF/SF + lag (repozytorium ma gotowy tylko FS); cykle przy zapisie; CPM i zapas (do dopisania, repozytorium ich nie liczy) |
| Grafy w biznesie | konflikty, wpływy i zamiany jako problemy grafowe | konflikty, wpływy, zamiany | kolorowanie (górna granica); składowe; punkty artykulacji; cykl zamian wykonywany paczką |
| Plan vs Execution | plan jako byt porównywany z faktami jawną tolerancją | „planowaliśmy, a wyszło” | plan jako byt z wersjami; tolerancje (kwota, dni, ilość, %; and); delty; agregacja do rozdzielczości planu; symulacje na kopii |
Wróćmy do pytania z początku: kierowca kuriera tankuje kartą flotową firmy leasingowej, a koszt ostatecznie trafia do klienta kuriera. „Klientów” jest tu przynajmniej czterech: firma kurierska wobec leasingodawcy, leasingodawca wobec stacji (jako wydawca kart), klient kuriera wobec kuriera i kierowca jako użytkownik karty. Każdy jest klientem w innej relacji. Model danych potrzebny do tego jest jeden: Party z rolami i relacjami z okresem ważności. Do tego Accounting dla limitu karty i refaktur, Pricing dla doliczenia paliwa do usługi, a cała reszta to konfiguracja. Jeśli Twoja odpowiedź na początku brzmiała „cztery tabele klientów”, to właśnie przeszedłeś drogę, którą to kompendium miało pokazać.
Co dalej: weź jedną funkcję z własnego projektu, wypisz jej wymagania zdaniami i przepuść je przez drzewo decyzyjne i klinikę antywzorców. Potem otwórz repozytorium szkolenia i porównaj swój model z testami scenariuszowymi odpowiedniego modułu.