Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Od smutnego monolitu do modularnego monolitu – ...

Od smutnego monolitu do modularnego monolitu – historia prawdziwej refaktoryzacji

Gdy dołączyłem do zespołu, myślałem że projekt to rocket science - inaczej nie wyobrażałem sobie takiego chaosu w kodzie. Prawda była prostsza i smutniejsza: system robił dość podstawowe rzeczy, tylko strasznie źle napisane.

Ta prezentacja to prawdziwa historia tego, jak nie przepisywaliśmy systemu od zera,
nie uciekliśmy w mikroserwisy i nie zaczęliśmy od idealnej architektury. Zamiast tego
zaczęliśmy od fundamentów: wspólnych ustaleń developerskich, nauki i budowania wspólnego
języka wokół czystej architektury.

Mając tę wiedzę, wprowadzaliśmy zmiany małymi krokami — tworząc pierwsze bounded contexty (logicznie odseparowane obszary biznesowe) wewnątrz jednego monolitu. Z czasem pojawiły się nowe wyzwania: integracja między kontekstami, zacierające się granice i reguły
architektoniczne istniejące głównie w głowach developerów.

Wtedy sięgnęliśmy po narzędzia statycznej analizy, które pozwoliły egzekwować struktury
wewnątrz kontekstów i zależności między nimi. Efektem była architektura modularnego
monolitu, którą można było rozwijać bez strachu — a w pewnym momencie w naturalny sposób
wydzielić pierwszy niezależny serwis.

To nie jest teoretyczna opowieść o idealnej architekturze. To praktyczna historia pracy
z legacy codebase, zespołowych kompromisów, błędów i decyzji, które pozwoliły odzyskać
kontrolę nad systemem.

Avatar for Damian Dziaduch

Damian Dziaduch

April 03, 2026

More Decks by Damian Dziaduch

Other Decks in Programming

Transcript

  1. DependsOnDisallowedLayer FYUL\Clean\OrderSubmission\Application\OrderSubmissionService must not depend on FYUL\Clean\OrderSubmission\Adapter\Out\Http\Request\SendOrderToProductionRequest You are depending

    on token that is a part of a layer that you are not allowed to depend on. (Adapter) /opt/project/srcHexagonal/OrderSubmission/Application/OrderSubmissionService.php:23
  2. parameters: paths: - ./srcHexagonal layers: - name: Domain collectors: -

    type: classNameRegex value: /^.*\\Domain\\.*/ - name: Adapter collectors: - type: classNameRegex value: /^.*\\Adapter\\.*/ - name: Application collectors: - type: classNameRegex value: /^.*\\Application\\.*/ - name: Framework collectors: - type: classNameRegex value: /^.*\\Framework\\.*/ - name: SharedKernel collectors: - type: classNameRegex value: /^SharedKernel\\.*/ ruleset: Domain: - SharedKernel Application: - SharedKernel - Domain Adapter: - Application - SharedKernel - Domain Framework: - Domain - Application - Adapter - SharedKernel
  3. parameters: paths: - ./srcHexagonal - ./src layers: - name: Legacy

    collectors: - type: directory value: src/.* - name: OrderCancelation collectors: - type: classNameRegex value: /^FYUL\\Clean\\OrderCancelation\\.*/ - name: OrderSubmission collectors: - type: classNameRegex value: /^FYUL\\Clean\\OrderSubmission\\.*/ - name: StockContext collectors: - type: classNameRegex value: /^FYUL\\Clean\\StockContext\\.*/ - name: SharedKernel collectors: - type: classNameRegex value: /^FYUL\\Clean\\SharedKernel\\.*/ ruleset: OrderSubmission: - SharedKernel OrderCancelation: - SharedKernel StockContext: - SharedKernel Legacy: - OrderSubmission - OrderCancelation - StockContext - SharedKernel
  4. • Zanim dotkniesz kodu, zbuduj wspólny język w zespole (ubiquitous

    language) • Zgoda i wola całego zespołu to fundament wizji długoterminowej • Refaktoryzacja to nie big-bang, ale maraton małych kroków • Green f ield obok legacy – osobny katalog pozwala strzec granic bez walki ze starym kodem • Narzędzia statycznej analizy egzekwują architekturę lepiej niż ustalenia w głowach inżynierów • Najpierw granice w monolicie (nawet proste), potem dopiero rozmowa o wydzieleniu serwisu • Mikroserwis wyciągasz wtedy, gdy cechy architektury tego wymagają – nie wtedy, gdy masz dość monolitu