{"id":11,"date":"2026-03-01T12:11:47","date_gmt":"2026-03-01T11:11:47","guid":{"rendered":"https:\/\/test.high-five.cc\/?p=11"},"modified":"2026-03-01T12:12:23","modified_gmt":"2026-03-01T11:12:23","slug":"art2","status":"publish","type":"post","link":"https:\/\/test.high-five.cc\/?p=11","title":{"rendered":"Architektura oprogramowania, czyli jak nie usma\u017cy\u0107 projektu w pierwszym kwartale"},"content":{"rendered":"<p>Boli dopiero po czasie. Architektura systemu to nie galeria sztuki nowoczesnej, gdzie stawiasz dziwn\u0105 rze\u017ab\u0119 z mikroserwis\u00f3w i liczysz na oklaski; to raczej polisa OC dla kodu. Zaczyna mie\u0107 sens dok\u0142adnie w momencie, gdy klient rzuca radosne \u201edodajmy ma\u0142\u0105 funkcj\u0119\u201d, a ta drobnostka dotyka siedmiu modu\u0142\u00f3w, trzech baz danych i jednego biednego <code>if-a<\/code>, kt\u00f3ry mia\u0142 \u017cy\u0107 wiecznie, a teraz p\u0119ka pod presj\u0105. Koniec z\u0142udze\u0144. W e-commerce na 120 tysi\u0119cy linii kodu, gdzie 6 deweloper\u00f3w rze\u017abi\u0142o bez architekta, dodanie prostego rabatu zajmowa\u0142o po dw\u00f3ch latach a\u017c 11 dni. Wi\u0119kszo\u015b\u0107 tego czasu to debugowanie efekt\u00f3w ubocznych. Kiedy brak separacji odpowiedzialno\u015bci, wtedy wszystko wie o wszystkim \u2014 kontroler zna struktur\u0119 tabeli, a walidator wysy\u0142a maile. Chaos, tylko \u017ce w kodzie.<\/p>\n<p>ISO\/IEC 25010 wygl\u0105da powa\u017cnie. Ma grube PDF-y i tabelki z \u201emaintainability\u201d, ale spr\u00f3buj to wdro\u017cy\u0107 w sprincie numer 7, gdy deadline wisi nad zespo\u0142em jak top\u00f3r. Teoria robi si\u0119 mi\u0119kka. Standard m\u00f3wi: \u201esystem powinien by\u0107 \u0142atwy w utrzymaniu\u201d, ale nikt nie podaje, czy mierzymy to liczb\u0105 klas, czy czasem na pull requesta. Tu pojawia si\u0119 w\u0105tpliwo\u015b\u0107. Definicja musi pasowa\u0107 i do banku, i do pralki, wi\u0119c nie pasuje do niczego idealnie. Nawet model 4+1 Philippe\u2019a Kruchtena \u2014 logiczny, procesowy, wdro\u017ceniowy, implementacyjny i scenariusze \u2014 w ma\u0142ym startupie bywa armat\u0105 na much\u0119. Junior patrzy na 140 stron dokumentacji i czuje, \u017ce to plan zdj\u0119ciowy, a nie opis API. Cz\u0119sto lepiej sprawdza si\u0119 model C4 Simona Browna: Context, Container, Component, Code. Od og\u00f3\u0142u do szczeg\u00f3\u0142u, bez zb\u0119dnej filozofii i bez rysowania ka\u017cdej prywatnej metody w UML, jakby IntelliJ przesta\u0142 istnie\u0107.<\/p>\n<p>Juniorzy cz\u0119sto chc\u0105 zbawi\u0107 \u015bwiat nowym frameworkiem z GitHuba, kt\u00f3ry ma 300 gwiazdek i jest \u201elekki jak pi\u00f3rko\u201d. Pami\u0119tam typa \u2014 wpad\u0142 na daily z oczami jak po trzech Red Bullach, przepisa\u0142 modu\u0142 p\u0142atno\u015bci i tydzie\u0144 p\u00f3\u017aniej produkcja mieli\u0142a CPU jak betoniarka. Brak cache\u2019owania i synchroniczne requesty zabi\u0142y system. Nie w ka\u017cdym przypadku winne jest narz\u0119dzie, cz\u0119\u015bciej zawodzi brak nudnych rozwi\u0105za\u0144 typu memoizacja czy kolejka asynchroniczna. Je\u015bli system ma \u017cy\u0107 d\u0142u\u017cej ni\u017c tw\u00f3j obecny laptop, planuj tak, jakby\u015b to ty mia\u0142 go utrzymywa\u0107 za trzy lata. Bo mo\u017cliwe, \u017ce b\u0119dziesz. Najgorsze refaktoryzacje robi si\u0119 pod presj\u0105 sprzeda\u017cy, kiedy nikt nie oddziela odpowiedzialno\u015bci, bo \u201etermin\u201d. Potem architektura przypomina patchwork zszyty z ticket\u00f3w z Jiry.<\/p>\n<p>W podr\u0119cznikach zobaczysz wykresy czyste jak \u0142za, a w repozytorium \u2014 kontroler wywo\u0142uj\u0105cy DAO przez statyczny helper z 2009 roku. Legacy k\u0142amie bez mrugni\u0119cia okiem. Dokumentacja twierdzi, \u017ce to architektura heksagonalna, a kod odpowiada: \u201esingleton i modlitwa\u201d. Cz\u0119sto prawda mieszka w bazie danych, w polach typu <code>isLegacyMode<\/code> albo <code>clientTier3OverrideFlag<\/code>, kt\u00f3re rz\u0105dz\u0105 logik\u0105 od czasu, gdy klient enterprise odszed\u0142 dwa lata temu. Je\u015bli widzisz klas\u0119 <code>Utils<\/code>, to zazwyczaj nie jest \u017caden util, tylko magazyn wstydu na 1200 linii. Nie poprawiaj ka\u017cdego zdania do poziomu eseju, po prostu buduj cienki szkielet i pozw\u00f3l mu si\u0119 deformowa\u0107 pod realnym obci\u0105\u017ceniem. Kod, kt\u00f3ry przechodzi testy, daje wi\u0119cej informacji ni\u017c najpi\u0119kniejszy diagram z 80 prostok\u0105tami, kt\u00f3rego i tak nikt nie zaktualizuje po pierwszym merge reque\u015bcie.<\/p>\n<p>Dobra, zejd\u017amy na ziemi\u0119, bo teoretyzowanie o czystym kodzie przy kawie to sport dla ludzi, kt\u00f3rzy nie maj\u0105 ticket\u00f3w na \u201eju\u017c\u201d. Wyobra\u017a sobie, \u017ce piszesz prosty system zam\u00f3wie\u0144. Masz encj\u0119 <code>Order<\/code>. Wrzucasz tam wszystko: ID klienta, list\u0119 produkt\u00f3w, status p\u0142atno\u015bci, logik\u0119 obliczania podatku VAT, a na koniec jeszcze metod\u0119 do generowania PDF-a z faktur\u0105. Dzia\u0142a? No pewnie, \u017ce dzia\u0142a. Przez pierwsze dwa tygodnie jeste\u015b bohaterem. Potem przychodzi zmiana: VAT w Niemczech jest inny ni\u017c w Polsce, a faktury maj\u0105 by\u0107 wysy\u0142ane przez zewn\u0119trzny system API, a nie generowane lokalnie. I nagle tw\u00f3j <code>Order.java<\/code> ma 800 linii, a ka\u017cda pr\u00f3ba zmiany podatku wywala wysy\u0142k\u0119 maili. Gratulacje, w\u0142a\u015bnie zbudowa\u0142e\u015b Big Ball of Mud.<\/p>\n<p>Zastosujmy tu inwersj\u0119 zale\u017cno\u015bci, zanim zginiesz marnie. Zamiast <code>Order<\/code> prosi\u0107 o PDF-a, stw\u00f3rz interfejs <code>InvoiceGenerator<\/code>. Niech <code>Order<\/code> nawet nie wie, czy to generuje biblioteka iText, czy hinduski sta\u017cysta przepisuj\u0105cy dane do Notatnika. To jest ta s\u0142ynna abstrakcja, o kt\u00f3rej juniorzy zapominaj\u0105, gdy widz\u0105 now\u0105 wersj\u0119 Springa. Logik\u0119 biznesow\u0105 \u2014 te wszystkie \u201eje\u015bli klient z Gruzji i kupi\u0142 wino, to daj rabat 5%\u201d \u2014 zamknij w osobnej us\u0142udze. Niech kontroler tylko odbiera request i przekazuje go dalej. Kontroler to recepcjonista, a nie kucharz. On ma tylko sprawdzi\u0107, czy go\u015b\u0107 ma rezerwacj\u0119 (walidacja DTO), a nie sma\u017cy\u0107 steki.<\/p>\n<p>Pojawia si\u0119 w\u0105tpliwo\u015b\u0107: czy warto traci\u0107 czas na te wszystkie interfejsy w ma\u0142ym projekcie? Nie zawsze. Je\u015bli piszesz skrypt do migracji danych, kt\u00f3ry odpalisz raz i skasujesz, to olej architektur\u0119. Wal to w jednej metodzie <code>main<\/code>. Ale je\u015bli to ma by\u0107 rdze\u0144 biznesu, to oszcz\u0119dno\u015b\u0107 na architekturze to po prostu branie kredytu w chwil\u00f3wce na 5000%. Oddasz z odsetkami w postaci nadgodzin w weekendy. Widzia\u0142em projekty, gdzie koszt dodania nowej kolumny do tabeli by\u0142 tak du\u017cy, \u017ce firma wola\u0142a zbankrutowa\u0107. Serio. Techniczny d\u0142ug to nie jest metafora literacka, to realne pieni\u0105dze uciekaj\u0105ce z konta klienta przez dziurawy kod.<\/p>\n<p>We\u017amy teraz na warsztat mikroserwisy, bo to s\u0142owo dzia\u0142a na junior\u00f3w jak magnes. \u201eZr\u00f3bmy mikroserwisy, bo Netflix tak robi\u201d. Netflix ma tysi\u0105ce in\u017cynier\u00f3w i problemy, o kt\u00f3rych ci si\u0119 nie \u015bni\u0142o. Ty masz trzyosobowy zesp\u00f3\u0142 i problem z poprawnym skonfigurowaniem Dockera. Zanim rozbijesz monolit na 15 kawa\u0142k\u00f3w, upewnij si\u0119, \u017ce potrafisz zarz\u0105dza\u0107 transakcjami rozproszonymi. Bo co zrobisz, gdy serwis p\u0142atno\u015bci powie \u201eOK\u201d, a serwis magazynu wywali b\u0142\u0105d 500? Masz wtedy pieni\u0105dze klienta, ale nie masz towaru, a system my\u015bli, \u017ce wszystko jest w porz\u0105dku. Architektura to wyb\u00f3r mniejszego z\u0142a. Czasem lepiej mie\u0107 jeden, dobrze uporz\u0105dkowany monolit (modu\u0142owy monolit to nie jest obelga!), ni\u017c \u201erozproszone spaghetti\u201d, gdzie debugowanie jednego requesta wymaga przeszukania log\u00f3w w pi\u0119ciu r\u00f3\u017cnych kontenerach.<\/p>\n<p>Dygresja o nazewnictwie: przesta\u0144 nazywa\u0107 wszystko <code>Manager<\/code>, <code>Processor<\/code> albo <code>Helper<\/code>. Te s\u0142owa nic nie znacz\u0105. <code>OrderManager<\/code> to \u015bmietnik, do kt\u00f3rego wrzucisz wszystko, od walidacji po zapis do bazy. Nazwij to <code>OrderPriceCalculator<\/code>, <code>OrderRepository<\/code> albo <code>OrderValidator<\/code>. Konkret. Im bardziej precyzyjna nazwa, tym trudniej dopisa\u0107 tam kod, kt\u00f3ry tam nie pasuje. To taki psychologiczny trik na samego siebie. Je\u015bli klasa nazywa si\u0119 <code>EmailSender<\/code>, to raczej nie dopiszesz tam logiki przeliczania kursu walut, prawda? A w <code>GlobalService<\/code> dopisa\u0142by\u015b to bez mrugni\u0119cia okiem.<\/p>\n<p>Na koniec sp\u00f3jrzmy na testy. Architektura, kt\u00f3rej nie da si\u0119 przetestowa\u0107 jednostkowo, to po prostu b\u0142\u0105d w sztuce. Je\u015bli twoja logika biznesowa jest tak mocno sklejona z baz\u0105 danych, \u017ce musisz stawia\u0107 ca\u0142ego PostgreSQL-a, \u017ceby sprawdzi\u0107 prosty warunek <code>if<\/code>, to przegra\u0142e\u015b \u017cycie. Dobra architektura pozwala ci testowa\u0107 zasady gry w izolacji. Infrastruktura \u2014 baza, API, system plik\u00f3w \u2014 powinna by\u0107 tylko wymiennym detalem. Dzisiaj masz SQL-a, jutro klient wymy\u015bli NoSQL, a pojutrze wszystko b\u0119dzie w chmurze AWS S3. Brzmi nierealnie? Prze\u017cy\u0142em takie migracje. Te, kt\u00f3re mia\u0142y warstwy, trwa\u0142y miesi\u0105c. Te \u201esklejone\u201d pisali\u015bmy od zera.<\/p>\n<p>Pami\u0119taj, juniorze: Twoim zadaniem nie jest pisanie kodu. Twoim zadaniem jest dostarczanie dzia\u0142aj\u0105cych rozwi\u0105za\u0144, kt\u00f3re da si\u0119 zmieni\u0107 bez p\u0142aczu. Kod to tylko koszt. Im mniej go napiszesz, by osi\u0105gn\u0105\u0107 cel, tym lepszym jeste\u015b architektem. Wi\u0119c zamiast rzuca\u0107 si\u0119 na najnowsze wzorce z blog\u00f3w technologicznych, zacznij od pytania: \u201eco si\u0119 stanie, gdy klient zmieni zdanie?\u201d. Je\u015bli odpowied\u017a brzmi \u201eb\u0119d\u0119 musia\u0142 przepisa\u0107 p\u00f3\u0142 systemu\u201d, to znaczy, \u017ce czas wr\u00f3ci\u0107 do rysowania prostok\u0105t\u00f3w. Tylko tym razem z g\u0142ow\u0105.<\/p>\n<p>Autor: programista z 15 letnim doswiadczeniem, expert, redaktor z zacieciem do pisania lekkich i zartobliwych tekstow<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Kr\u00f3tki opis artyku\u0142u widoczny w wynikach wyszukiwania.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[7,6],"class_list":["post-11","post","type-post","status-publish","format-standard","hentry","category-technologia","tag-automatyzacja","tag-python"],"_links":{"self":[{"href":"https:\/\/test.high-five.cc\/index.php?rest_route=\/wp\/v2\/posts\/11","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/test.high-five.cc\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/test.high-five.cc\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/test.high-five.cc\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/test.high-five.cc\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=11"}],"version-history":[{"count":2,"href":"https:\/\/test.high-five.cc\/index.php?rest_route=\/wp\/v2\/posts\/11\/revisions"}],"predecessor-version":[{"id":19,"href":"https:\/\/test.high-five.cc\/index.php?rest_route=\/wp\/v2\/posts\/11\/revisions\/19"}],"wp:attachment":[{"href":"https:\/\/test.high-five.cc\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=11"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/test.high-five.cc\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=11"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/test.high-five.cc\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=11"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}