Przejdź do treści
juz-ide.pl blog
Wróć

Własna biblioteka DDD: build, buy czy wydziel-własne?

Paweł G.
4 min czytania
Własna biblioteka DDD: build, buy czy wydziel-własne?
Temat Technologia scaling-solo-dev

Dwa tygodnie po pierwszym commicie produktu. Siedzę z kodem, który działa — i widzę, że przepisuję te same struktury po raz trzeci. Agregat tu, encja tam, zdarzenie domenowe gdzie indziej. Za każdym razem od zera.

Wtedy pojawia się pytanie, które pewnie każdy solo developer zadaje sobie raz za razem: napisać to od nowa, kupić gotowe, czy może… wyciągnąć własne?

Trzy opcje, jedna głowa

Kiedy budujesz coś poważnego — platformę z logiką domeny, regułami biznesowymi, zdarzeniami — prędzej czy później potrzebujesz jakiegoś fundamentu pod DDD. Pytanie brzmi: skąd go wziąć?

Buy — kup gotowy framework. W ekosystemie .NET są NServiceBus, MassTransit, Ardalis Clean Architecture. W Node.js — ubóstwo. Są biblioteki do zdarzeń, są do walidacji, ale nic co spinałoby to w spójny zestaw wzorców, z testowalnością i TypeScriptem. Praktycznie: opcja buy odpada.

Build — napisz od zera w produkcie. Najszybszy start. Ale: dwa projekty później masz dwa zestawy tych samych wzorców, które żyją osobno, ewoluują osobno, psują się osobno.

Wydziel-własne — zrób bibliotekę raz, użyj wszędzie. Koszt: trzeba ją faktycznie utrzymywać.

Wybrałem trzecią opcję. Repozytorium vytches-ddd założyłem pod koniec czerwca, a w połowie lipca wydałem pierwszą wersję. Prawie dwa miesiące przerwy od produktu — o czym opiszę osobno w „Świadomej pauzie”.

Co trafiło do biblioteki

vytches-ddd to monorepo oparte na NX i pnpm. Na start wylądowało w nim ponad 20 pakietów: agregaty (aggregates), obiekty wartości (value-objects), zdarzenia domenowe (events), wzorzec rezultatu (result-pattern), repozytoria, polityki, serwisy domenowe, warstwa CQRS, testowanie, walidacja i kilka innych.

Każdy pakiet jest oddzielną jednostką z własnym package.json, publikowaną przez CI do GitHub Packages (prywatny rejestr). W produkcie — jeden wpis w .npmrc i normalne npm install.

Czy to over-engineering?

Uczciwa odpowiedź: może. Ale over-engineering to rozwiązywanie problemów, których nie masz. Ja miałem ten problem — przepisywałem te same wzorce po raz drugi i wiedziałem, że to nie ostatni projekt.

Kluczowe pytanie nie brzmi „czy biblioteka to dobry pomysł ogólnie”. Brzmi: „czy będę faktycznie utrzymywał drugi projekt?”. Jeśli odpowiedź jest „nie wiem”, wydzielanie własnej biblioteki to przedwczesna inwestycja.

U mnie odpowiedź była „tak” — mam plan na kilka produktów na tym samym stosie. Biblioteka to fundament systemu, nie jednorazowy kaprys.

Alternatywa, której nie wybrałem: podfolder shared/ wewnątrz monorepo produktu. Prostszy start, gorszy podział. Można do niego wrócić, jeśli plan się zmieni.

Co oznacza „ponad 20 pakietów” w praktyce

Nie wrzuciłem ich wszystkich naraz i nie ogłosiłem sukcesu. Pierwsza wersja v0.1.0 miała to, czego produkt potrzebował na dzień pierwszy: agregaty, obiekty wartości, zdarzenia, repozytoria, wynik domenowy (Result pattern). Reszta powstawała w kolejnych tygodniach, gdy produkt sygnalizował potrzebę.

Biblioteka żyje w rytmie produktu — nie odwrotnie.

Dalej

W sierpniu 2025, gdy produkt ruszył na pełnych obrotach, biblioteka stanęła w tle — ale była już tam i działała. Parę tygodni później podjąłem decyzję, żeby ponownie ją zatrzymać i mocno zrefaktoryzować. Ale to już osobna historia.

Jak to działa od środka (dla ciekawych)

Struktura monorepo

vytches-ddd to NX monorepo z pnpm workspaces. Każdy pakiet pod packages/<nazwa>/, każdy z osobnym package.json i własnym cyklem wydań.

Przykładowe pakiety: @vytches/ddd-core, @vytches/ddd-cqrs, @vytches/ddd-events, @vytches/ddd-policies, @vytches/ddd-testing, @vytches/ddd-utils.

Podłączenie do produktu

# .npmrc w projekcie produktowym
@vytches:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}

Pakiety zainstalowane jak każda zależność npm:

{
  "dependencies": {
    "@vytches/ddd": "^0.4.0"
  }
}

W lipcu w produkcie pojawił się tylko wpis w .npmrc (rejestr) — faktyczna zależność @vytches/ddd weszła do package.json na początku sierpnia, już w wersji ^0.4.0. Biblioteka przez tych kilka tygodni zdążyła dojrzeć szybciej niż produkt, który miał z niej korzystać.

Kiedy NIE robić własnej biblioteki

  • Masz jeden projekt i jeden stos — zwykły shared/ w monorepo wystarczy.
  • Nie masz planu na drugi projekt — to inwestycja bez zwrotu.
  • Nie lubisz zarządzać CI dla N pakietów — próg wejścia jest realny.


Poprzedni wpis
Skąd u mnie DDD: historia samouka
Następny wpis
Świadoma pauza: zatrzymałem produkt, żeby zbudować bibliotekę