Pytania rekrutacyjne Architektura oprogramowania
107 pytań — 20 odpowiedzi dostępnych od razu
Fundamenty i analiza trade-offów
Dlaczego w nowoczesnej architekturze rozproszonej nie ma uniwersalnych „best practices"?
Programista zwykle rozwiązuje problemy powtarzalne — konfigurację narzędzia czy błąd frameworka da się znaleźć na Stack Overflow. Architekt pracuje inaczej: każdy istotny problem jest splotem konkretnej organizacji, jej historii, zespołów i ograniczeń technicznych, więc rzadko ktokolwiek na świecie rozwiązał dokładnie ten sam przypadek. Stąd o architekturze powstaje znacznie mniej „przepisów" niż o API.
Konsekwencja praktyczna: nie istnieje „najlepszy" projekt, bo „najlepszy" zakładałby jednoczesną maksymalizację wszystkich konkurujących cech (wydajności, skalowalności, odporności, prostoty), co jest niemożliwe. Realnym celem jest najmniej zła kombinacja kompromisów (least worst combination of trade-offs) — taka, w której żadna cecha nie błyszczy w izolacji, ale całość sprzyja powodzeniu projektu.
Dlatego rdzeniem pracy architekta nie jest znajomość gotowych wzorców, lecz podejmowanie decyzji: obiektywne wyważanie kompromisów po obu stronach każdego wyboru. To umiejętność ponadczasowa — konkretne technologie (orkiestrowane SOA → mikroserwisy → kontenery → Kubernetes) wymieniają się co kilka lat, a metoda oceny trade-offów zostaje.
Na czym polega systematyczna analiza trade-offów w architekturze?
To dyscyplina, nie intuicja. Można ją sprowadzić do trzech kroków:
- Znajdź splecione wymiary (find what is entangled) — wskaż części, które wzajemnie na siebie wpływają. Robocza definicja sprzężenia: „jeśli ktoś zmieni X, czy może to wymusić zmianę Y?".
- Przeanalizuj punkty sprzężenia — zbadaj, jak dokładnie te części są ze sobą powiązane (statycznie i dynamicznie).
- Oceń kompromisy — przeanalizuj wpływ zmiany na współzależne elementy i wybierz wariant o najlepszym bilansie.
Kilka technik podnoszących jakość tej analizy:
- Modeluj iteracyjnie — pierwsza wersja nigdy nie jest dobra. Zamiast budować cały system, modeluj „lekkie" warianty i scenariusze what-if, aż zbudujesz macierz porównań.
- Wybór fundamentalnego wymiaru najpierw (np. komunikacja synchroniczna vs asynchroniczna) ogranicza dalsze opcje — potem iterujesz po decyzjach wymuszonych przez pierwszą.
- Większość tabel trade-offów jest jakościowa, nie ilościowa — dwie architektury różnią się na tyle, że twarde porównanie liczbowe rzadko jest możliwe. Tam, gdzie da się zmierzyć (testy z obiektywnym wynikiem), przesuwaj analizę ku ilościowej.
To, co zostaje po rozstrzygnięciu wszystkich splątanych wymiarów, jest już designem, nie architekturą.
Jakie pułapki najczęściej zniekształcają ocenę rozwiązań architektonicznych?
Najczęstsze błędy poznawcze i ich antidota:
- Pułapka „poza kontekstem" (out-of-context trap) — generyczna macierz trade-offów może wskazać jedną opcję, ale dodanie realnego kontekstu odwraca decyzję. Klasyczny przykład: „w ogólności" shared library wygrywa z shared service, dopóki nie dołożymy wymagania heterogeniczności języków, które przechyla wybór na serwis. Wąsko zdefiniowany kontekst pozwala rozważać mniej opcji — to realne uproszczenie.
- Listy MECE (Mutually Exclusive, Collectively Exhaustive) — porównuj rzeczy tej samej kategorii, bez nakładania się i bez dziur. Porównywanie kolejki komunikatów do całego ESB łamie „mutually exclusive"; pominięcie Kafki przy ocenie wydajnych kolejek łamie „collectively exhaustive".
- Przewaga konkluzji nad nawałem dowodów — interesariuszy nietechnicznych przytłaczają detale. Sprowadź analizę do bottom line: „co ważniejsze — natychmiastowy start autoryzacji czy responsywność i odporność?".
- Ewangelizm i snake oil — entuzjazm wyolbrzymia zalety i ukrywa wady, a trade-offy zawsze wracają. Architekt ma być obiektywnym arbitrem kompromisów, nie wyznawcą jednej technologii.
Czym są architecture fitness functions i do czego służą?
To dowolny mechanizm dający obiektywną ocenę wybranej cechy architektonicznej (lub ich kombinacji). Pełnią rolę governance — automatyzują pilnowanie zasad architektury tak, jak testy jednostkowe pilnują poprawności domeny, a CI zautomatyzował integrację.
Rozróżnienie od testów: pytanie kontrolne brzmi „czy do wykonania potrzebna jest wiedza domenowa?". Jeśli tak (poprawność kodu pocztowego) — to test funkcjonalny. Jeśli nie (brak cykli między komponentami, czas startu, próg wydajności) — to fitness function.
Zakres:
- atomic — pojedyncza cecha w izolacji (np. wykrywanie cyklicznych zależności),
- holistic — kombinacja cech wchodzących w interakcję (np. bezpieczeństwo vs wydajność).
Konkretne narzędzia: ArchUnit (Java) i NetArchTest (.NET) do walidacji reguł warstw i zależności, JDepend do wykrywania cykli między pakietami, SonarQube jako gotowy zestaw reguł higieny kodu. Fitness function, która się nie wykonuje, niczego nie waliduje — dlatego wpina się ją do pipeline'u i uruchamia jak najczęściej. Mocno automatyzowalna obrona przed dryfem architektury (np. zespół bezpieczeństwa może wstrzyknąć regułę failującą build przy podatnej wersji frameworka).
Czym jest Architecture Decision Record (ADR)?
ADR to krótki dokument (zwykle 1–2 strony, w Markdown lub AsciiDoc, trzymany w repo obok kodu) opisujący jedną istotną decyzję architektoniczną. Spopularyzował go Michael Nygard. To najprostszy skuteczny sposób, by decyzje nie żyły wyłącznie w głowach i mailach.
Typowy ADR ma trzy sekcje:
- Context (kontekst) — na czym polega problem i jakie były rozważane alternatywy.
- Decision (decyzja) — co postanowiono, wraz z uzasadnieniem dlaczego.
- Consequences (konsekwencje) — jakie są skutki wyboru i jakie trade-offy świadomie zaakceptowano.
Wartość ADR-ów rośnie w czasie: nowy członek zespołu czyta nie tylko jak coś zbudowano, ale dlaczego — a druga zasada architektury mówi, że „dlaczego" jest ważniejsze niż „jak". ADR dokumentuje decyzję; jej egzekwowaniem zajmują się już fitness functions.
Coupling i kwant architektoniczny
Czym jest architecture quantum (kwant architektoniczny)?
Kwant architektoniczny to niezależnie wdrażalny artefakt o wysokiej spójności funkcjonalnej i wysokim sprzężeniu statycznym wewnątrz, sprzężony dynamicznie (synchronicznie) na zewnątrz. To miara łącząca topologię i zachowanie systemu — pozwala mówić jednym językiem o granicach wdrożeniowych, zakresie domeny i sprzężeniach.
Trzy składowe definicji:
| Składowa | Co oznacza |
|---|---|
| Independently deployable | Każdy kwant to osobna jednostka wdrożeniowa |
| High functional cohesion | Elementy realizują jeden spójny workflow domenowy (zbieżne z bounded context z DDD) |
| High static coupling | Wszystko jest ze sobą „okablowane" w spójną całość |
Praktyczne wnioski: monolit jest zawsze jednym kwantem (jeden deployment + zwykle jedna baza). Dobrze uformowany mikroserwis z własną bazą to osobny kwant — może mieć własne charakterystyki (inną skalowalność, inny poziom bezpieczeństwa). Pojęcie kwantu jest punktem wyjścia do całej analizy sprzężeń w systemie rozproszonym.
Czym różni się static coupling od dynamic coupling?
To dwa prostopadłe spojrzenia na sprzężenie, oba potrzebne.
Static coupling opisuje, jak rzeczy są ze sobą okablowane — czyli zależności potrzebne, by serwis w ogóle wystartował: system operacyjny, frameworki i biblioteki (także tranzytywne), baza danych, broker komunikatów, orkiestracja kontenerów. Pytanie diagnostyczne: „czego potrzeba, żeby uruchomić ten serwis od zera?". Samo istnienie brokera to sprzężenie statyczne.
Dynamic coupling opisuje, jak serwisy wołają się nawzajem w czasie działania — synchronicznie czy asynchronicznie, jak ścisły jest kontrakt, jaką spójność wymuszają. Wywołanie przez broker to sprzężenie dynamiczne.
Rozróżnienie ma praktyczne skutki. Diagram sprzężeń statycznych służy do analizy ryzyka i niezawodności („jeśli zmienię X, co się zepsuje?") — dane do niego można pozyskać z manifestów kontenerów, plików POM (Maven), zależności NPM i grafu wywołań z observability. Diagram dynamiczny służy do projektowania workflow i jego trade-offów wydajności i spójności.
Jakie są trzy wymiary dynamic quantum coupling?
Każdą interakcję między serwisami w workflow rozproszonym opisują trzy zazębiające się siły:
- Communication (komunikacja) — synchroniczna (np. gRPC; nadawca blokuje się i czeka) vs asynchroniczna (kolejka + kolejka zwrotna; nadawca pracuje dalej). Wpływa na obsługę błędów, transakcyjność, skalowalność.
- Consistency (spójność) — atomowość (wszystko albo nic) vs eventual consistency (dane uzgodnią się po czasie). Transakcje atomowe między serwisami to jeden z najtrudniejszych problemów rozproszonych — ogólna rada to ich unikać.
- Coordination (koordynacja) — orkiestracja (dedykowany mediator) vs choreografia (serwisy koordynują się same).
Sił nie wybiera się niezależnie — one na siebie ciążą. Transakcyjność jest łatwiejsza w wariancie synchronicznym + orkiestrowanym; najwyższą skalę daje asynchroniczny + eventually consistent + choreografowany. Te trzy wymiary, każdy dwuwartościowy, dają 8 możliwych kombinacji — i właśnie z nich wyprowadza się 8 wzorców sag transakcyjnych. Kluczowa obserwacja: im więcej couplingu, tym gorsza skalowalność i (słabiej) tym niższa dostępność całego workflow.
Dlaczego współdzielona baza danych redukuje wiele serwisów do jednego kwantu?
Bo baza danych jest częścią sprzężenia statycznego kwantu. Jeśli kilka serwisów współdzieli jedną bazę o wspólnym cyklu wdrożeń, to żaden z nich nie jest naprawdę niezależnie wdrażalny — zmiana schematu może złamać dowolny z nich, a awaria bazy zatrzymuje wszystkie naraz. Cały zbiór spada więc do jednego kwantu, niezależnie od tego, jak ładnie rozdzielony jest kod.
Dotyczy to nawet architektur z pozoru rozproszonych: w service-based architecture (osobno wdrażane gruboziarniste serwisy + jedna monolityczna baza) kwant nadal wynosi 1. Dopiero rozbicie danych na osobne schematy/serwery pozwala uformować odrębne kwanty.
flowchart TB
subgraph Q1["Jeden kwant"]
S1["Serwis A"] --> DB[("Wspolna baza")]
S2["Serwis B"] --> DB
S3["Serwis C"] --> DB
end
subgraph Q2["Trzy kwanty"]
SA["Serwis A"] --> DBA[("Baza A")]
SB["Serwis B"] --> DBB[("Baza B")]
SC["Serwis C"] --> DBC[("Baza C")]
end
Ta sama logika dotyczy ciasno sprzężonego frontendu: monolityczny UI, bez którego backend jest bezużyteczny, sam w sobie scala mikroserwisy w jeden kwant — chyba że rozdzielimy go przez asynchroniczność lub framework micro-frontendów.
Modularność architektoniczna
Czym jest modularność architektoniczna i co ją napędza biznesowo?
Modularność architektoniczna to rozbijanie wielkiego monolitu na mniejsze, osobne części, by zyskać jednocześnie pojemność na wzrost i zdolność do szybkiej, ciągłej zmiany. Ważne: nie rozbijaj systemu bez wyraźnego drivera biznesowego — sama chęć „mikroserwisów" to nie uzasadnienie.
Dwa nadrzędne drivery biznesowe to speed-to-market (tempo dostarczania) i competitive advantage (przewaga konkurencyjna). Tempo wynika z agility — cechy złożonej z maintainability + testability + deployability. Przewagę dają jeszcze scalability oraz availability/fault tolerance.
Pięć kluczowych charakterystyk technicznych, które poprawia modularność:
- Maintainability — łatwość dodawania/zmiany funkcji,
- Testability — łatwość i kompletność testów,
- Deployability — łatwość, częstotliwość i niskie ryzyko wdrożeń,
- Scalability — responsywność przy rosnącym obciążeniu,
- Availability / fault tolerance — odporność na awarie części systemu.
Modularność nie zawsze oznacza system rozproszony — maintainability i deployability osiąga też modular monolith (partycjonowany domenowo) czy architektura microkernel z pluginami.
Jak dekompozycja wpływa na maintainability, testability i deployability?
We wszystkich trzech działa ta sama mechanika: modularność zmniejsza zakres („blast radius") zmiany.
- Maintainability — w monolicie warstwowym dodanie pola (np. daty wygaśnięcia) propaguje się przez UI, backend i bazę, wymuszając koordynację kilku zespołów; zmiana ma zakres na poziomie aplikacji. W service-based zakres spada do poziomu domeny, a w mikroserwisach do poziomu funkcji. Metryka ML (maintainability level) spada wraz z rosnącym sprzężeniem przychodzącym między komponentami.
- Testability — mniejsza jednostka to mniejszy, ukierunkowany zestaw testów i pełniejszy regres. Uwaga na pułapkę: gdy serwisy zaczynają intensywnie się komunikować, zakres testu zmiany w serwisie A rozlewa się na B i C — testability gwałtownie spada.
- Deployability — to nie tylko łatwość, ale i częstotliwość oraz ryzyko. Monolit wymusza ceremoniał (code freeze, kumulowanie nietestowanych razem zmian). Za drobne serwisy, które trzeba wdrażać razem w określonej kolejności, dają „big ball of distributed mud" — wtedy lepszy bywa powrót do monolitu.
Czym różni się scalability od elasticity i czym jest MTTS?
To dwie różne cechy, często mylone:
- Scalability (skalowalność) — utrzymanie responsywności przy stopniowym wzroście obciążenia w czasie (np. z 1000 do 10 000 użytkowników w ciągu miesięcy).
- Elasticity (elastyczność) — responsywność przy nagłych, gwałtownych skokach (np. system biletowy: 20 → 3000 użytkowników w kilka sekund po starcie sprzedaży).
Co ważne, zależą od różnych rzeczy. Skalowalność jest funkcją modularności (rozbicia na osobne jednostki), a elastyczność — funkcją granularności (rozmiaru jednostki), bo zależy od małego MTTS (mean time to startup) — czasu, w jakim nowa instancja staje się gotowa. Drobne serwisy na lekkim runtime startują w sekundy; monolit z długim MTTS nie nadąży za skokiem.
Stąd: monolit warstwowy skaluje się słabo i kosztownie (cała aplikacja skaluje się tak samo), mikroserwisy dają maksymalną skalę i elastyczność. Trade-off: im więcej komunikacji synchronicznej w jednej transakcji, tym gorsza skala — przy wysokich wymaganiach minimalizuj wywołania synchroniczne.
Jak zbudować business case za rozbiciem monolitu?
„Nic innego już nie działa" to nie jest uzasadnienie biznesowe. Poprawna ścieżka ma trzy kroki: (1) zrozum korzyści modularności, (2) dopasuj każdy konkretny problem systemu do konkretnego drivera, (3) przeanalizuj i udokumentuj trade-offy (najlepiej w ADR).
Przykładowe mapowanie problem → driver:
| Objaw w systemie | Driver |
|---|---|
| Zmiany psują niepowiązane rzeczy, trudno znaleźć miejsce edycji | Maintainability |
| 30% testów wyłączonych, trzeba odpalać cały zestaw | Testability |
| Comiesięczne wydania kumulują ryzyko, dużo nietestowanych razem zmian | Deployability |
| Padają moduły poboczne (ankiety, raporty), nie rdzeń | Availability / fault tolerance |
| Zawieszanie powyżej 25 równoczesnych użytkowników; raporty duszą bazę | Scalability + rozbicie bazy |
Po stronie konsekwencji trzeba uczciwie wpisać trade-offy migracji: chwilowe spowolnienie nowych funkcji (zespół zajęty migracją), dodatkowy koszt, konieczność zarządzania wieloma jednostkami wdrożeniowymi i — najtrudniejsze — rozbicie monolitycznej bazy danych. Dobry business case mówi nie tylko, co zyskamy, ale i co świadomie poświęcamy.
Dekompozycja monolitu
Jak ocenić, czy kod nadaje się do dekompozycji?
Pierwszy krok każdej migracji to ustalić, czy w ogóle warto i czy się da. Skrajnym przeciwieństwem struktury jest Big Ball of Mud — kod bez wewnętrznych granic (np. obsługa zdarzeń wpięta wprost w wywołania bazy). Architektura zajmuje się strukturą; jeśli jej nie ma, nie ma czego rozdzielać.
Żadna pojedyncza metryka nie rozstrzyga, ale metryki sprzężeń dają makro-obraz. Kluczowe są afferent i efferent coupling (Yourdon i Constantine):
- Afferent coupling (CA) — sprzężenia przychodzące: ile innych elementów zależy od danego komponentu.
- Efferent coupling (CE) — sprzężenia wychodzące: od ilu innych elementów dany komponent zależy.
Przykład praktyczny: współdzielona klasa Address jest w monolicie zachętą do reuse, ale przy podziale trzeba znać jej afferent coupling — ile części systemu ją wywołuje — bo to przesądza o koszcie rozplątania. Narzędzia jak JDepend liczą te metryki per pakiet.
Co mówią metryki abstractness, instability i distance from the main sequence?
To pochodne metryki Roberta C. Martina, mierzące równowagę wnętrza kodu (dla dowolnego języka obiektowego):
- Abstractness (A) = elementy abstrakcyjne / (abstrakcyjne + konkretne). Kod typu jeden
main()na 10 000 linii ma A bliskie 0 — trudny do zrozumienia i rozszerzania. - Instability (I) = CE / (CE + CA). Mierzy podatność na zmianę. I bliskie 1 = bardzo niestabilny (dużo zależności wychodzących). Niskie I może oznaczać komponent stabilny (oparty na abstrakcjach) albo sztywny (sam konkret, trudny do zmiany) — dlatego A i I czyta się razem.
- Distance from the main sequence (D) = |A + I − 1|. Wyobraża idealną prostą zdrowej równowagi; im bliżej niej, tym lepiej zbalansowany komponent.
Skrajności są nazwane: zone of uselessness (zbyt abstrakcyjny, nieużywalny) i zone of pain (zbyt konkretny, kruchy, trudny w utrzymaniu). Po co to architektowi: jak przy przenoszeniu budynku — jeśli wiele komponentów leży w strefach bólu/bezużyteczności, „przeniesienie" aplikacji do architektury rozproszonej może się po prostu nie opłacać bez wcześniejszej naprawy struktury.
Czym różni się Component-Based Decomposition od Tactical Forking?
To dwa podejścia do rozbicia monolitu, dobierane wg stanu kodu.
Component-Based Decomposition to podejście ekstrakcyjne: stopniowo, wzorcami refaktoryzacji, wydobywasz komponenty i składasz z nich serwisy. Prowadzi naturalnie do service-based architecture (gruboziarniste, osobno wdrażane serwisy + jedna wspólna baza). Zaleta: jest bezpieczne i inkrementalne, nie wymaga od razu rozbijania bazy ani konteneryzacji; granice serwisów wyłaniają się z grupowania komponentów. Wymaga jednak kodu z czytelnymi (choćby luźnymi) granicami komponentów.
Tactical Forking (Fausto De La Torre) działa odwrotnie — przez usuwanie, nie wyrywanie. Klonujesz cały monolit tyle razy, ile chcesz docelowych serwisów, i każdy zespół kasuje to, czego nie potrzebuje. W chaotycznym kodzie kasowanie jest łatwiejsze niż ekstrakcja (nie trzeba rozplątywać zależności, wystarczy kompilacja i testy). Wady: w serwisach zostaje dużo martwego kodu, a współdzielony kod jest powielony.
flowchart TD
A{"Kod jest dekomponowalny?"} -->|nie| STOP["Stop: najpierw napraw strukture"]
A -->|tak| B{"Sa czytelne granice komponentow?"}
B -->|tak| C["Component-Based Decomposition"]
B -->|nie, big ball of mud| D["Tactical Forking"]
Wspólne zagrożenie obu ścieżek to antywzorzec migracji „kęs po kęsie" — wyrywanie kawałków bez planu prowadzi do distributed monolith (rozproszony monolit), który łączy wady obu światów.
Wzorce dekompozycji komponentów
Na czym polega dekompozycja oparta o komponenty i dlaczego robi się ją inkrementalnie?
Komponent to blok budulcowy aplikacji o dobrze określonej roli i zestawie operacji, fizycznie reprezentowany przez namespace lub strukturę katalogów (np. katalog ticket/assign → komponent Ticket Assign). Kluczowa zasada: serwisy buduje się z komponentów, a nie z pojedynczych klas.
Migracje „na raz" (big bang) rzadko się udają, bo niosą ogromne ryzyko i trudno je wycofać. Dlatego wzorce dekompozycji stosuje się sekwencyjnie przy pierwszym przejściu monolit → architektura rozproszona, a potem pojedynczo, żeby utrzymać porządek w monolicie w trakcie długiej migracji. Daje to podejście ustrukturyzowane, kontrolowane i odwracalne, które ogranicza ryzyko rozproszonego monolitu.
Pomocne pojęcie to component domain — logiczne grupowanie powiązanych komponentów (manifestowane przez hierarchię namespace, np. customer.billing.payment), które później stanie się gruboziarnistym domain service. Same refaktoryzacje warto opisywać jako architecture stories — analogię user stories, ale dotyczącą struktury kodu i realizującą driver architektoniczny.
Jakie jest sześć wzorców dekompozycji opartej o komponenty?
Stosowane zwykle w tej kolejności, prowadzą od bałaganu monolitu do service-based architecture:
- Identify and Size Components — skataloguj wszystkie komponenty i wyrównaj ich rozmiar (mierzony liczbą statements, nie plików). Zbyt duże komponenty są bardziej sprzężone i trudniejsze do wydzielenia; celuj w rozmiary w granicach 1–2 odchyleń standardowych od średniej.
- Gather Common Domain Components — skonsoliduj rozproszoną wspólną logikę domenową (np. trzy mechanizmy notyfikacji → jeden Notification). Dotyczy shared domain (logiki biznesowej), nie shared infrastructure (logowanie, metryki).
- Flatten Components — dopilnuj, by komponenty były liśćmi namespace, nie były budowane jeden na drugim, i wychwyć „osierocone" klasy w korzeniu namespace.
- Determine Component Dependencies — przeanalizuj sprzężenia między komponentami; to one przesądzają o wykonalności migracji.
- Create Component Domains — pogrupuj komponenty w logiczne domeny, refaktoryzując namespace tak, by odzwierciedlały przynależność domenową.
- Create Domain Services — wyodrębnij domeny do osobno wdrażanych domain services. Nie zaczynaj, dopóki wszystkie domeny nie są zidentyfikowane — inaczej dokładanie komponentu do gotowego serwisu wymusza jego modyfikację.
Jak ocenić wykonalność migracji na podstawie sprzężeń komponentów?
Sercem oceny jest analiza sprzężeń między komponentami (nie klas wewnątrz nich — te mogą być splątane dowolnie). Pomocna jest metafora rozmiaru diagramu zależności:
- golf ball — minimalne zależności → migracja wykonalna, wystarczy refaktoryzacja,
- basketball — dużo zależności (typowe dla aplikacji biznesowych) → trudniej, miks refaktoryzacji i przepisania,
- airliner — gęsta plątanina → praktycznie niewykonalne, realnie tylko przepisanie od zera.
Poziom sprzężenia komponentów jest jednym z najważniejszych czynników powodzenia — zespoły, które rzucają się na mikroserwisy bez tej analizy, najczęściej zawodzą. Sprzężenie można redukować: silnie sprzężony komponent A (CA=20) da się rozbić na A1 (mała, gęsto wołana część, CA=14) i A2 (reszta, CA=6), zmniejszając zależności. Warto też odfiltrować komponenty będące bibliotekami współdzielonymi (wiązanymi w kompilacji), żeby zobaczyć rzeczywiste zależności rdzenia. Do wymiarowania używa się obiektywnej metryki liczby statements, a nie liczby plików czy linii kodu — bo te zależą od stylu programisty.
Rozbijanie danych operacyjnych
Kiedy warto rozdzielić bazę danych — jakie są data disintegrators?
Rozbicie bazy jest trudniejsze niż rozbicie kodu — dane to najważniejszy zasób firmy, a sprzęgła (klucze obce, widoki, triggery, procedury) trudno znaleźć i rozplątać. Sześć powodów przemawiających za podziałem:
- Change control — ile serwisów psuje zmiana schematu? Przy współdzielonej bazie breaking change (usunięcie/zmiana kolumny) wymusza skoordynowaną zmianę wszystkich zależnych serwisów, a o zapomnianym dowiesz się dopiero z awarii na produkcji.
- Connection management — każda instancja serwisu ma własny pool; 50 serwisów × 10 połączeń × 2 instancje to już 1000 połączeń. Saturacja objawia się jako connection waits, time-outy i wyzwolone circuit breakery.
- Scalability / throughput — gdy serwisy się skalują, wspólna baza staje się wąskim gardłem.
- Fault tolerance — wspólna baza to single point of failure; jej awaria zatrzymuje wszystkich.
- Architectural quanta — wspólna baza wymusza jeden kwant; rozbicie pozwala uformować odrębne kwanty o własnych charakterystykach.
- Database type optimization — w monolicie wszystkie dane muszą zmieścić się w jednym typie bazy; rozbicie umożliwia polyglot persistence (np. dane referencyjne klucz–wartość w Redis zamiast w bazie relacyjnej).
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziGranularność serwisów
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziWzorce ponownego użycia
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziWłasność danych i transakcje rozproszone
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziRozproszony dostęp do danych
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziWorkflow rozproszony
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziSagi transakcyjne
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziKontrakty
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziDane analityczne
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziMetryki wdrożeń: cztery kluczowe metryki (DORA)
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziFitness functions: kategorie i piramida testów
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOd metryk do inżynierii architektury
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziArchitektura ewolucyjna: testowalność i wdrażalność
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziDług techniczny i Modularity Maturity Index (MMI)
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziPrivate builds i metryki przejścia na DevOps
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziArchitektura sterowana metrykami w skali organizacji
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziMierzenie atrybutów jakościowych architektury
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziMetryki utrzymywalności i erozji strukturalnej
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziGoal-Question-Metric (GQM)
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziArchitektura ewolucyjna: zmiana kierowana, prawo Conwaya i wymiary
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziFitness functions w praktyce
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziZmiana przyrostowa oparta na danych i eksperymencie
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziEwolucyjność stylów architektonicznych
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziDane ewolucyjne
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziZasady budowy architektury ewolucyjnej
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziAntywzorce i pułapki ewolucji
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziWdrażanie architektury ewolucyjnej w organizacji
Odpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedziOdpowiedź dostępna w pełnej wersji. Odblokuj 87 pozostałych odpowiedzi i ucz się z pełnego zestawu.
Odblokuj odpowiedzi