A modern módszerek klasszikus gyökerekre épülnek. Parnas információrejtése, Dijkstra strukturált vezérlése, Conway törvénye és Brooks koncepcionális integritása részletesen a papírkorszak módszereiről szóló kézikönyvben szerepel, itt csak visszautalunk rájuk. Az alábbi módszerek a 2026 októberi állapot szerinti kiadásokra épülnek, a teljes lista a Források alatt található.
1. Az architektúra törvényei és alapfogalmai (Richards és Ford)
1.1 A törvények
Az első törvény. A szoftverarchitektúrában minden kompromisszum. Ehhez a szerzők egy következményt is fűznek, hogy ha valaki azt hiszi, talált valamit, ami nem kompromisszum, akkor valószínűleg csak még nem azonosította, mivel fizet érte.
A második törvény. Fontosabb a miért, mint a hogyan. Egy diagram megmutatja, hogyan néz ki a rendszer, de azt nem, miért ilyen. Ezért kell az ADR (7.3 pont).
A 2. kiadás kiegészítése. A legtöbb architekturális döntés egy skálán mozog két szélsőség között, nem bináris választás. Monolit és microservices között ott van a moduláris monolit és a service based architektúra. Szinkron és aszinkron hívás között pedig ott a kérés és válasz üzenetsoron keresztül.
Gyakorlati alkalmazás. Minden architekturális javaslat mellé odaírjuk a költségét is. Egy javaslat költség nélkül marketing, nem mérnöki munka.
1.2 Architekturális jellemzők azonosítása és priorizálása
Az architekturális jellemző (architectural characteristic, a régebbi irodalomban nem funkcionális követelmény vagy quality attribute) akkor számít, ha három feltétel teljesül. Nem a domain funkciója, befolyásolja a szerkezetet, és kritikus vagy fontos az alkalmazás sikere szempontjából.
Kategóriák a 2. kiadás szerint
| Kategória | Példák |
|---|---|
| Működési (operational) | availability, performance, scalability, elasticity, reliability, recoverability |
| Szerkezeti (structural) | modularity, maintainability, extensibility, testability, deployability, portability |
| Felhő jellemzők | on demand skálázás, szolgáltatói függés, zónák közti redundancia |
| Átfogó (cross cutting) | security, privacy, accessibility, legal, auditability, usability |
Lépések
- A domain szempontok kigyűjtése. A megrendelő üzleti nyelvén (gyors piacra jutás, felhasználói elégedettség, versenyelőny, költségcsökkentés, összeolvadás és felvásárlás).
- Fordítás jellemzőkre. Gyors piacra jutás jelentése agility, ami összetett jellemző (testability plus deployability plus modularity). Felvásárlás jelentése interoperability és extensibility.
- Explicit jellemzők a követelményekből. Például 1000 egyidejű felhasználó, ez scalability. Napi egyszeri csúcs (Black Friday, jegyértékesítés) pedig elasticity.
- Az implicit jellemzők megnevezése. Amit senki nem mond ki, de mindenki elvár (availability, security, alap performance).
- Legfeljebb hét jelölt marad. Ennél több jellemzőre tervezett rendszer általános és ezért semmire nem jó.
- A top három kiválasztása. Mind a hetet nem kell sorrendbe tenni, mert azon a csapat sosem egyezik meg. A három legfontosabban viszont egyet kell érteni.
- Mérhető cél mindegyikhez. Ami nem mérhető, arra fitness function sem írható (4. pont).
Sablon (architektúra jellemző lap)
## Architekturális jellemzők. <projekt>
| Jellemző | Forrás (domain szempont vagy követelmény) | Cél, mérőszám | Top 3? |
|----------|-------------------------------------------|---------------|--------|
| auditability | GDPR, ügyféladat kezelés | minden írás naplózva, ki, mit, mikor | igen |
| simplicity | egy fejlesztő plus AI | egy deploy egység, egy adatbázis | igen |
| availability | belső eszköz, munkaidőben | 99,5% munkaidőben | nem |
Implicit: security, alap performance (p95 < 500 ms)
Szándékosan NEM optimalizált: elasticity, multi region
Tipikus hibák
- A lista minden jellemzőt tartalmaz, és mind egyformán fontos. Ilyenkor a döntés valójában nem született meg.
- Összekeverik a domain követelményt a jellemzővel. A számlázás funkció, az auditálhatóság jellemző.
- A legjobb architektúrát keresik. Richards és Ford szerint a cél a legkevésbé rossz architektúra (least worst), mert minden szerkezet valamiben gyenge.
AI asszisztált fejlesztésnél. A generált kód implicit módon mindig a gyors elkészülésre optimalizál. Ha a projekt jellemzői közt ott van az auditability vagy a privacy, ezt a promptba és az AI asszisztens projektszintű instrukciós fájljába (például AGENTS.md vagy CLAUDE.md) is be kell írni, különben nem lesz benne a kódban. A témáról bővebben az AI ügynökökről és a vibecodingról szóló kézikönyv ír.
1.3 Architecture quantum
Egy architecture quantum a rendszer önállóan telepíthető darabja, amelynek magas a funkcionális kohéziója, magas a statikus csatolása (közös adatbázis, közös könyvtár, közös broker), és szinkron a dinamikus csatolása (futás közben szinkron hívással várnak egymásra). A Hard Parts finomítja a fogalmat, és a dinamikus csatolást három dimenzió mentén vizsgálja (kommunikáció, konzisztencia, koordináció).
Miért hasznos. Az architekturális jellemzők quantumonként eltérhetnek. Ha a rendelésfelvételnek elasticity kell, a riportolásnak nem, akkor két quantum indokolt. Amikor az egész rendszernek ugyanazok a jellemzői, egy quantum is elég, és akkor egy deploy egységről beszélünk.
A quantumok megszámolása
- Felrajzoljuk a deploy egységeket.
- Összehúzzuk azokat, amelyek közös adatbázist használnak. Egy közös adatbázis egy quantumba köti őket, akárhány szolgáltatásra van bontva a kód.
- Összehúzzuk azokat is, amelyek szinkron hívással egymásra várnak egy felhasználói kérésen belül.
- Ami külön marad, az egy-egy quantum.
Tipikus hiba. A disztribuált monolit. Tíz szolgáltatás, egy adatbázis, szinkron hívásláncok. Ez egy quantum tíz deploy egység költségével.
1.4 Komponensek meghatározása
A komponens a logikai építőelem (Javában csomag, TypeScriptben könyvtár vagy modul névtér), a szolgáltatás a fizikai. Előbb a logikai architektúra készül el, utána a fizikai.
Lépések (Richards és Ford ciklusa)
- Kezdeti komponensek azonosítása. Három megközelítés közül lehet választani. A szereplő és cselekvés (actor/actions) módszer a felhasználói szerepekből és azok tevékenységeiből indul. Workflow módszernél a fő üzleti folyamatok lépéssora a kiindulópont. Az event storming pedig a domain eseményekből dolgozik (5.4 pont).
- Követelmények hozzárendelése. Minden user story egy komponenshez kerül. Ha egy komponenshez túl sok jut, túl durva. Amikor egy story három komponenst érint egyszerre, rossz a vágás.
- Szerepek és felelősségek elemzése. Leírható egy mondatban, mit csinál a komponens? Ha nem, darabolni kell.
- Jellemzők elemzése. Indokolja-e a top 3 jellemző a komponens kettévágását? Például a fizetés komponens security szempontból elkülönül.
- Átalakítás. Iterálunk, amíg a szerkezet stabil nem lesz.
Tipikus hiba, az entity trap. A komponenseket az adatbázis táblák köré szervezik (UserManager, OrderManager, ProductManager), amelyek CRUD műveleteket csomagolnak. Ilyenkor a viselkedés szétszóródik, a komponensnevek semmit nem mondanak a rendszerről. AI generált kódnál ez a leggyakoribb kiinduló szerkezet, mert a modell a táblákból indul ki.
Granularitási jelek. Túl durva, ha egy komponens neve általános (Manager, Service, Utils, Common), vagy ha a fájlok több mint fele független változtatásokat kap. Ellenkező irányban túl finom, ha egy komponens egyetlen függvényből áll, és minden hívása egy másik komponensbe továbbít.
1.5 Stíluskatalógus
A 2. kiadás külön tárgyalja a monolitikus stílusokat (layered, modular monolith, pipeline, microkernel) és az elosztottakat (service based, event driven, space based, orchestration driven SOA, microservices). Az alábbi értékelés 1 és 5 csillag közötti, 5 a legjobb. A számok a könyv 1. kiadásának táblázatait követik, a moduláris monolit sora viszont a 2. kiadás szövegéből becsült érték, nem a könyv szó szerinti adata. Az olcsóság oszlopban az 5 csillag a legolcsóbbat jelenti.
| Stílus | Telepíthetőség | Rugalmas skálázás (elasticity) | Továbbfejleszthetőség | Hibatűrés | Modularitás | Olcsóság | Teljesítmény | Megbízhatóság | Skálázhatóság | Egyszerűség | Tesztelhetőség |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Layered | 1 | 1 | 1 | 1 | 1 | 5 | 2 | 3 | 1 | 5 | 2 |
| Modular monolith | 2 | 1 | 3 | 1 | 4 | 5 | 3 | 3 | 1 | 4 | 3 |
| Pipeline | 2 | 1 | 3 | 1 | 3 | 5 | 2 | 3 | 1 | 5 | 3 |
| Microkernel | 3 | 1 | 3 | 1 | 3 | 5 | 3 | 3 | 1 | 4 | 3 |
| Service based | 4 | 2 | 3 | 4 | 4 | 4 | 3 | 4 | 3 | 3 | 4 |
| Event driven | 3 | 3 | 5 | 5 | 4 | 3 | 5 | 3 | 5 | 1 | 2 |
| Space based | 3 | 5 | 3 | 3 | 3 | 1 | 5 | 4 | 5 | 1 | 1 |
| Orchestration driven SOA | 1 | 3 | 1 | 3 | 3 | 1 | 2 | 2 | 4 | 1 | 1 |
| Microservices | 4 | 5 | 5 | 4 | 5 | 1 | 2 | 4 | 5 | 1 | 4 |
Stílusonként röviden
- Layered (rétegzett). Prezentáció, üzleti logika, perzisztencia, adatbázis. Technikai particionálás, vagyis a kód a technikai szerep szerint van csoportosítva, nem a domain szerint. Gyors indulásra jó, de egy új mező hozzáadása minden réteget érint. Antimintája az architecture sinkhole, amikor a rétegek logika nélkül csak továbbadják a hívást. Ha a kérések több mint 20 százaléka ilyen, a rétegzés teher.
- Modular monolith. Egy deploy egység, de a kód domain szerint particionált modulokra bomlik, amelyeknek kijelölt nyilvános felülete van. A 2. kiadásban önálló fejezetet kapott, és kis csapatnak ez a legjobb alapértelmezés (részletesen a 15. pontban).
- Pipeline (pipes and filters). Szűrők láncolata, egyirányú adatfolyammal. Szűrőtípusok a producer, a transformer, a tester és a consumer. Ez az ETL, a képfeldolgozás és az LLM feldolgozó láncok (betöltés, darabolás, embedding, indexelés) természetes formája.
- Microkernel (plugin). Minimális mag plusz bővítmények. IDE-k, böngészők, szabálymotorok, olyan termékek, amelyeket ügyfelenként testre kell szabni. A bővítményeket egy regiszter tartja nyilván, a mag a szerződést (interface) határozza meg.
- Service based. Négy és tizenkét közötti durva szemcsés domain szolgáltatás, gyakran közös adatbázissal, egy felhasználói felülettel. A microservices pragmatikus testvére, a könyv szerint az egyik leginkább alulértékelt stílus. Kis cégnek, amely kinőtte a monolitot, ez a következő lépés.
- Event driven. Broker topológia (koreográfia, nincs központi koordinátor) vagy mediator topológia (orkesztráció egy közvetítővel). Nagy teljesítmény és hibatűrés, de nehéz a hibakezelés, a sorrend és a tesztelés. A 2. kiadás külön tárgyalja a kérés alapú és az esemény alapú modell keverését.
- Space based. Memóriában replikált adatrácsok (processing unit), aszinkron írás az adatbázisba (data pump, data writer). Extrém egyidejű terhelésre való (jegyértékesítés, aukció). Drága és bonyolult.
- Orchestration driven SOA. A 2000-es évek vállalati szolgáltatásbusza. Történelmi okból szerepel, főleg tanulságként, mert a közös újrahasznosítás maximalizálása extrém csatoláshoz vezetett.
- Microservices. Bounded contextenként egy szolgáltatás, saját adattal, önálló telepítéssel. Akkor éri meg, ha a csapatok függetlensége és a quantumonként eltérő jellemzők indokolják. Egyszemélyes fejlesztésnél majdnem soha.
A stílusválasztás lépései
- Top 3 jellemző az 1.2 pont szerint.
- A quantumok száma az 1.3 pont szerint. Egy quantumhoz monolitikus stílus illik, többhöz elosztott.
- Domain vagy technikai particionálás? Ma a domain szerinti az alapértelmezés.
- A táblázatból azt a stílust választjuk, amely a top 3-ban nem gyenge (legalább 3 csillag), és amelynek az egyszerűsége elfogadható a csapat méretéhez.
- ADR rögzíti, mit adtunk fel érte.
1.6 Architekturális governance
A governance a szerzőknél nem jóváhagyó bizottság, hanem automatizált ellenőrzés. Az architektúra szabályait kóddá alakítjuk (fitness function, 4. pont), és a CI futtatja őket. A 2. kiadás a governance-t a fejlesztési folyamatba ágyazza, és külön foglalkozik azzal, hogyan mérhető a kódbázisból a modularitás (kohézió, csatolás, a fő sorozattól való távolság, Robert C. Martin absztraktság és instabilitás mérőszámai alapján).
Mérőszámok röviden
| Mérőszám | Jelentés | Jel |
|---|---|---|
| Afferent coupling (Ca) | hány modul függ ettől | magas érték, óvatos változtatás |
| Efferent coupling (Ce) | hány modultól függ ez | magas érték, törékeny |
| Instabilitás I = Ce / (Ca + Ce) | 0 stabil, 1 instabil | |
| Absztraktság A | absztrakt elemek aránya | |
| Távolság a fő sorozattól D = abs(A + I - 1) | 0 ideális | közel 1 érték a fájdalom zónája (konkrét és stabil) vagy a haszontalanság zónája (absztrakt és instabil) |
| Connascence | Meilir Page-Jones fogalma, a csatolás fajtái név, típus, jelentés, pozíció, algoritmus, végrehajtási sorrend, időzítés, érték, identitás szerint | minél gyengébb fajta és minél közelebb van egymáshoz, annál jobb |
1.7 A 2. kiadás új témái
- Generatív AI. A szerzők az AI-t két oldalról nézik. Egyrészt az architekt eszköze (kompromisszumok feltárása, alternatívák generálása, dokumentáció), másrészt architekturális elem, amelynek saját jellemzői vannak (nem determinisztikus kimenet, tokenenkénti költség, késleltetés, szolgáltatói függés, adatvédelem). Óvatosságra intenek, mert a modell nem érti a kontextust, a kompromisszumok mérlegelése emberi munka marad.
- Team Topologies. A csapatszerkezet és az architektúra stílus illeszkedése. Microservices stream aligned csapatokat feltételez, a layered stílus technikai csapatokat (frontend, backend, DBA). Ha a stílus és a csapatszerkezet ütközik, Conway törvénye a csapatszerkezet javára dönt (10. pont).
- Moduláris monolit, felhő szempontok, adat az architektúrában, diagramozás, ADR, governance. Ezek önálló fejezetként vagy kibővítve szerepelnek a könyvben.
- Puha készségek. Tárgyalás, vezetés, együttműködés a fejlesztőcsapattal. Az architekt hatékonysága azon múlik, mennyi kontrollt gyakorol a csapat fölött. Sem a túl szoros (control freak), sem a túl laza (armchair architect) nem működik.
2. Minőségi attribútumok, taktikák, ATAM (Bass, Clements, Kazman)
A SEI iskola a 4. kiadásban tíz minőségi attribútumot tárgyal külön fejezetben. Ezek az availability, deployability, energy efficiency, integrability, modifiability, performance, safety, security, testability és usability. Az energy efficiency és a safety új a korábbi kiadásokhoz képest.
2.1 A minőségi attribútum forgatókönyv hat része
Egy jellemző akkor használható, ha forgatókönyvvé alakítjuk. A forgatókönyv hat részből áll.
| Rész | Kérdés | Példa (availability) |
|---|---|---|
| Forrás (source) | ki vagy mi váltja ki | külső fizetési szolgáltató |
| Inger (stimulus) | mi történik | 30 másodpercig nem válaszol |
| Környezet (environment) | milyen állapotban van a rendszer | normál üzem, munkaidő |
| Érintett elem (artifact) | mire hat | rendelés leadás szolgáltatás |
| Válasz (response) | mit tesz a rendszer | a rendelést függőben rögzíti, a felhasználót értesíti |
| Válaszmérték (response measure) | hogyan mérjük | a felhasználó 2 másodpercen belül választ kap, adatvesztés nulla |
Gyakorlat. Minden top 3 jellemzőhöz legalább egy ilyen sor tartozik. Az AI asszisztensnek ez kiváló bemenet, mert a válaszmértékből közvetlenül teszt vagy fitness function írható.
2.2 Taktikák
A taktika egy tervezési döntés, amely egyetlen minőségi attribútum válaszát befolyásolja. Ezzel szemben a minta (pattern) több taktika csomagja. A fontosabb taktikacsaládokat a táblázat foglalja össze.
| Attribútum | Taktikacsoport | Példák |
|---|---|---|
| Availability | hibafelismerés | heartbeat, ping/echo, monitor, időbélyeg, önteszt |
| Availability | helyreállítás | aktív és passzív redundancia, rollback, retry, degradáció, újraindítás |
| Availability | megelőzés | szolgáltatás kivonása, tranzakció, prediktív modell |
| Modifiability | méret csökkentése | modul szétvágása |
| Modifiability | kohézió növelése | szemantikai koherencia növelése, felelősség áthelyezése |
| Modifiability | csatolás csökkentése | beágyazás, közvetítő, absztrakt közös szolgáltatás, korlátozott függőségek |
| Modifiability | késleltetett kötés | konfiguráció, plugin, futásidejű regisztráció |
| Performance | erőforrás igény szabályozása | mintavételezés, kérések priorizálása, rate limit, hatékonyabb algoritmus |
| Performance | erőforrások kezelése | párhuzamosítás, cache, replikák, ütemezés |
| Security | támadás felismerése | behatolás érzékelés, üzenet integritás |
| Security | támadásnak ellenállás | azonosítás, hitelesítés, jogosultság, titkosítás, korlátozott kitettség |
| Security | reagálás, helyreállítás | hozzáférés visszavonása, zárolás, audit napló |
| Testability | megfigyelhetőség és vezérlés | speciális interfészek, rögzítés és visszajátszás, állapot lokalizálás, sandbox |
| Deployability | pipeline kezelés | skálázott rollout, rollback, feature toggle |
Használat. A forgatókönyv válaszmértékéhez megkeressük a taktikacsoportot, onnan egy-két konkrét taktikát választunk, és ADR-ben rögzítjük, melyik másik attribútumot rontja. Jó példa a cache, amely javítja a performance-t, de rontja a konzisztenciát és a modifiability-t.
2.3 Utility tree
Fa szerkezet. A gyökér az utility (a rendszer hasznossága), alatta a minőségi attribútumok, azok alatt finomítások, a leveleken konkrét forgatókönyvek. Minden levél két értéket kap (H, M, L), az üzleti fontosságot és a megvalósítás nehézségét.
Utility
├── Performance
│ └── Kereséskor válaszidő
│ └── (H,M) 10 000 termék között a keresés p95 < 300 ms normál terhelésnél
├── Security
│ └── Adathozzáférés
│ └── (H,H) Másik bérlő adatai semmilyen API hívással nem érhetők el
└── Modifiability
└── Új fizetési szolgáltató
└── (M,L) Új szolgáltató bekötése 2 napon belül, a rendelés modul változatlan
A (H,H) levelek a legkockázatosabbak, ezekkel foglalkozunk elsőként.
2.4 Az ATAM lépései
Az Architecture Tradeoff Analysis Method kilenc lépés négy fázisban. A 0. fázis a partnerség és előkészítés, a 3. a követés.
| Fázis | Lépés | Tartalom |
|---|---|---|
| 1. Értékelés | 1 | ATAM bemutatása |
| 2 | Üzleti célok bemutatása (business drivers) | |
| 3 | Architektúra bemutatása | |
| 4 | Architekturális megközelítések azonosítása | |
| 5 | Utility tree felépítése | |
| 6 | Megközelítések elemzése a magas prioritású forgatókönyveken | |
| 2. Értékelés bővített körrel | 7 | Forgatókönyvek ötletelése és priorizálása az érintettekkel |
| 8 | Megközelítések újraelemzése az új forgatókönyveken | |
| 9 | Eredmények bemutatása |
Kimenetek. Kockázatok (risk), nem kockázatok (non risk), érzékenységi pontok (sensitivity point, ahol egy paraméter erősen befolyásol egy attribútumot), kompromisszumpontok (tradeoff point, ahol egy döntés több attribútumot ellentétesen érint), kockázati témák.
Kis csapatnak vagy egy fejlesztőnek. A teljes ATAM napokig tart, a mini változat egy óra. Utility tree tíz levéllel, a (H,H) és (H,M) leveleken végigmegyünk a 6. lépésen, a kimenet egy kockázatlista, abból születnek az ADR-ek. Ez a mini változat egy nagyobb refaktor vagy egy új rendszer előtt mindig belefér, és AI asszisztenssel a forgatókönyvek első vázlata gyorsan összeáll.
3. Software Architecture: The Hard Parts
A könyv alapgondolata szerint elosztott rendszerben nincsenek legjobb gyakorlatok, csak kompromisszumok, és ezek elemzését kell megtanulni. Egy kitalált cég (Sysops Squad) migrációján vezet végig.
3.1 Szolgáltatás granularitás, disintegrators és integrators
Mekkora legyen egy szolgáltatás? Két erőcsoport hat egymás ellen.
Szétbontó erők (granularity disintegrators)
| Erő | Kérdés |
|---|---|
| Szolgáltatás hatóköre és funkciója | Egy jól körülhatárolt dolgot csinál, vagy több, egymástól független dolgot? |
| Kód volatilitás | A kód egy része sokkal gyakrabban változik, mint a többi? |
| Skálázhatóság és áteresztőképesség | Egyes részeknek eltérő skálázás kell? |
| Hibatűrés | Egy rész hibája ne döntse le a többit? |
| Biztonság | Egyes részek érzékenyebb adatot kezelnek, eltérő hozzáféréssel? |
| Bővíthetőség | Tervezetten bővülni fog újabb változatokkal (új fizetési mód)? |
Összetartó erők (granularity integrators)
| Erő | Kérdés |
|---|---|
| Adatbázis tranzakciók | Kell ACID tranzakció a részek között? |
| Munkafolyamat és koreográfia | Annyit hívnák egymást, hogy a késleltetés és a hibalehetőség elfogadhatatlan? |
| Közös kód | Jelentős közös üzleti logikát használnak, ami együtt változik? |
| Adatkapcsolatok | Az adataik szorosan összefüggnek (közös kulcsok, join)? |
Lépések. Egy táblázatba felírjuk a jelölt szétvágást, és minden erőhöz beírjuk, hogy hat-e, és mennyire erősen. Nem a darabszám dönt, hanem az, hogy melyik erő kapcsolódik a top 3 jellemzőhöz. A döntést az üzleti oldallal együtt hozzuk, nekik is érthető nyelven. Például szétbontva gyorsabb az új fizetési mód bevezetése, de a rendelés és a fizetés között csak végső konzisztencia lesz.
3.2 Adat szétválasztás
Adat szétbontó erők (data disintegrators). Változáskezelés (egy séma változás hány szolgáltatást érint), kapcsolatkezelés (connection pool kimerülése), skálázhatóság, hibatűrés, architecture quantum (közös adatbázis egy quantumba köt), adatbázis típus optimalizálása (kulcs érték, dokumentum, gráf).
Adat összetartó erők (data integrators). Adatkapcsolatok (idegen kulcsok, nézetek, triggerek) és adatbázis tranzakciók.
A szétválasztás öt lépése a könyv szerint
- Adatdomainek elemzése a táblák és a kód viselkedése alapján, sémánként csoportosítva.
- Táblák hozzárendelése adatdomainhez (például séma per domain).
- Adatbázis kapcsolatok szétválasztása, minden szolgáltatás csak a saját sémáját éri el.
- Sémák áthelyezése külön adatbázis szerverre.
- Független adatbázisokra váltás.
Adathozzáférési minták más domain adatához
| Minta | Leírás | Ára |
|---|---|---|
| Interservice communication | Szinkron hívás a tulajdonos szolgáltatáshoz | késleltetés, rendelkezésre állás függés |
| Column schema replication | Néhány oszlop másolása a fogyasztóhoz | szinkronizálás, elavult adat |
| Replicated caching | Memóriában replikált cache | memória, indulási idő |
| Data domain | Közös séma több szolgáltatásnak | tágabb quantum |
AI asszisztált fejlesztésnél. Supabase vagy egy Postgres esetén a séma per modul (például billing, crm) olcsó első lépés. Megadja a határt, de nem kényszerít elosztott tranzakcióra. Az adatmodellezés részleteiről az adatokról és adatbázisokról szóló kézikönyv ír.
3.3 A nyolc saga típus
A Hard Parts a dinamikus csatolást három dimenzióval írja le. Ezek a kommunikáció (szinkron vagy aszinkron), a konzisztencia (atomi vagy végső) és a koordináció (orkesztrált vagy koreografált). Minden kombináció egy saga minta.
| Név | Kommunikáció | Konzisztencia | Koordináció | Csatolás | Jellemzés |
|---|---|---|---|---|---|
| Epic Saga | szinkron | atomi | orkesztrált | nagyon magas | a monolit viselkedését utánozza elosztottan, a legtöbb csapat ide tér vissza ösztönösen |
| Phone Tag | szinkron | atomi | koreografált | magas | nincs koordinátor, az első szolgáltatás viszi a hibakezelést |
| Fairy Tale | szinkron | végső | orkesztrált | magas | könnyen érthető, jó kompromisszum, gyakori |
| Time Travel | szinkron | végső | koreografált | közepes | lánc szerű folyamatokra (pipeline) jó |
| Fantasy Fiction | aszinkron | atomi | orkesztrált | magas | az aszinkronitás és az atomiság üti egymást, ritkán jó |
| Horror Story | aszinkron | atomi | koreografált | közepes | a legrosszabb kombináció, atomiság koordinátor nélkül aszinkronban |
| Parallel Saga | aszinkron | végső | orkesztrált | alacsony | jól skálázódik, összetett hibakezelés |
| Anthology Saga | aszinkron | végső | koreografált | nagyon alacsony | a legnagyobb skálázhatóság, a legnehezebb követni |
Kiegészítő minták a sagákhoz. Kompenzáló tranzakció (a már végrehajtott lépés visszafordítása), állapotgép a sagához (a hosszú futású folyamat állapota explicit, például CREATED, PAYMENT_PENDING, PAID, FAILED), transactional outbox (az üzenet az adatbázis tranzakción belül egy outbox táblába kerül, és onnan egy külön folyamat küldi tovább, így nem fordulhat elő, hogy az írás megtörtént, de az esemény elveszett).
Döntési szabály. Ha a folyamathoz atomi konzisztencia kell, a résztvevő szolgáltatásokat nem vágjuk szét. Ahol a szétvágás elkerülhetetlen, ott végső konzisztenciával és Fairy Tale vagy Parallel mintával dolgozunk.
3.4 Szerződések (contracts)
| Fogalom | Jelentés |
|---|---|
| Szigorú szerződés (strict) | séma, típus, verzió (JSON Schema, gRPC, OpenAPI) |
| Laza szerződés (loose) | név érték párok, csak a szükséges mezőket olvassák |
| Stamp coupling | egy nagy adatstruktúrát adunk át, amiből a fogyasztó egy mezőt használ. Fölösleges csatolás és sávszélesség |
| Consumer driven contracts | a fogyasztók tesztként leírják, mit várnak, és a szolgáltató buildje ezeket futtatja (Pact) |
Szabály. Belső modulok között lehet szigorú, típusos szerződés. Csapat vagy szervezeti határon a laza szerződés és a consumer driven tesztek csökkentik a koordinációs igényt.
3.5 A kompromisszum elemzés módszere
- Az összegabalyodás feltárása. Melyik rész függ melyiktől statikusan és dinamikusan.
- A csatolás elemzése. Statikus (közös könyvtár, közös adat) és dinamikus (hívás, konzisztencia, koordináció).
- A kompromisszumok értékelése. Minőségi (kvalitatív) és ahol lehet, mennyiségi összehasonlítás. A szempontlista legyen MECE (kölcsönösen kizáró, együttesen teljes).
- A kontextuson kívüli csapda elkerülése. Egy általános előny és hátrány lista nem dönt, csak a saját top 3 jellemzőre vetítve.
- Forgatókönyvek modellezése. Konkrét esetekre (új mező hozzáadása, a fizetés kiesése) mindkét változatot végigrajzoljuk.
- A lényeg kimondása, evangelizálás nélkül. A döntéshozónak egy mondatos következtetés kell, nem technológiai lelkesedés.
4. Fejlődőképes architektúra és fitness functions
A Building Evolutionary Architectures (2. kiadás, 2022) szerint az architektúrának a változás irányítására kell felkészülnie. Az eszköz a fitness function, egy objektív, automatizálható ellenőrzés, amely egy architekturális jellemző teljesülését méri.
4.1 Típusok
| Dimenzió | Változatok | Példa |
|---|---|---|
| Hatókör | atomi (egy jellemző egy kontextusban) vagy holisztikus (több jellemző együtt) | rétegfüggőség ellenőrzése, illetve biztonság és teljesítmény együtt terhelés alatt |
| Ütemezés | triggerelt (CI futás) vagy folyamatos (éles monitorozás) | unit teszt, illetve szintetikus tranzakció élesben |
| Eredmény | statikus (fix küszöb) vagy dinamikus (kontextusfüggő küszöb) | ciklikus függőség tilos, illetve a válaszidő a terheléstől függ |
| Végrehajtás | automatizált vagy manuális | ArchUnit szabály, illetve jogi átnézés |
| Időbeliség | temporális | figyelmeztet, ha egy függőség 6 hónapja nem frissült |
| Szándék | szándékos (tervezett) vagy emergens (később derül ki, hogy kell) | |
| Domain | domain specifikus | pénzügyi számítások pontossága, adatvédelmi szabály |
A bevezetés lépései
- A top 3 jellemzőből és a forgatókönyvekből (2.1 pont) kiválasztjuk, amelyik automatizálható.
- Megírjuk a legegyszerűbb ellenőrzést, ami megbukik, ha a szabály sérül.
- CI-be tesszük, így a build elbukik, ha a szabály sérül.
- Ha egy szabályt tudatosan megszegünk, ADR-ben rögzítjük, és a fitness functionben kivételt adunk hozzá, hivatkozással.
4.2 Példák
ArchUnit (Java), rétegszabály és ciklusmentesség
@AnalyzeClasses(packages = "com.acme.shop")
class ArchitectureTest {
@ArchTest
static final ArchRule layers = layeredArchitecture().consideringAllDependencies()
.layer("Web").definedBy("..web..")
.layer("Application").definedBy("..application..")
.layer("Domain").definedBy("..domain..")
.layer("Infrastructure").definedBy("..infrastructure..")
.whereLayer("Web").mayNotBeAccessedByAnyLayer()
.whereLayer("Application").mayOnlyBeAccessedByLayers("Web")
.whereLayer("Domain").mayOnlyBeAccessedByLayers("Application", "Infrastructure");
@ArchTest
static final ArchRule noCycles = slices().matching("com.acme.shop.(*)..").should().beFreeOfCycles();
}
dependency-cruiser (JavaScript, TypeScript), moduláris monolit határai
// .dependency-cruiser.cjs
module.exports = {
forbidden: [
{ name: "no-circular", severity: "error", from: {}, to: { circular: true } },
{
name: "modul-csak-a-publikus-feluleten-at",
comment: "Más modul belső fájljait nem importáljuk, csak az index.ts-t",
severity: "error",
from: { path: "^src/modules/([^/]+)/" },
to: { path: "^src/modules/([^/]+)/(?!index\\.ts$)", pathNot: "^src/modules/$1/" }
},
{
name: "domain-nem-fugg-infrastrukturatol",
severity: "error",
from: { path: "/domain/" },
to: { path: "(/infrastructure/|node_modules/(@supabase|stripe|openai|@anthropic-ai))" }
}
]
};
// futtatás: npx depcruise src --config .dependency-cruiser.cjs
További eszközök. NetArchTest és ArchUnitNET (.NET), PyTestArch és import-linter (Python), Konsist (Kotlin), eslint-plugin-boundaries (JavaScript), Nx module boundaries (monorepó), Spring Modulith (ApplicationModules.of(App.class).verify()), Packwerk (Ruby, Shopify).
Nem kód szintű fitness functionök
- Bundle méret küszöb (például a fő chunk legfeljebb 250 KB gzip).
- Lighthouse vagy Core Web Vitals küszöb CI-ben.
- k6 terheléses teszt p95 küszöbbel.
npm auditvagy OSV scanner, amely kritikus sebezhetőségnél megbuktatja a buildet.- Séma szabály, például minden Supabase táblán be van kapcsolva az RLS (lekérdezés a
pg_tablesés apg_class.relrowsecurityalapján). - Szintetikus monitorozás élesben (folyamatos fitness function).
5. Domain Driven Design
5.1 Stratégiai tervezés (Evans 2003)
Ubiquitous language (közös nyelv). A domain szakértők és a fejlesztők ugyanazokat a szavakat használják, és ezek a szavak a kódban is megjelennek (osztálynév, függvénynév, tábla, esemény). Ha az üzlet ajánlatot mond, a kódban ne Quote legyen az egyik helyen és Offer a másikon.
Lépések
- Fogalomtár (glossary) a projekt gyökerében, minden kulcsfogalommal, egy mondatos definícióval.
- Ha egy szónak két területen két jelentése van, az két bounded context jele.
- A kód elnevezéseit a fogalomtárhoz igazítjuk. Egy kódgeneráló modell számára is ez a fogalomtár a legjobb bemenet a következetes elnevezéshez.
Bounded context. Az a határ, amelyen belül egy modell és annak nyelve egyértelmű. Egy ügyfél például a számlázásban adószám és számlázási cím, a támogatásban jegyek és SLA, a marketingben szegmens és hozzájárulás. Közös Customer osztály mindhárom igényt rosszul szolgálja.
Context map minták
| Minta | Mit jelent | Mikor |
|---|---|---|
| Partnership | két csapat közösen tervez, együtt sikerül vagy bukik | szoros együttműködés, közös cél |
| Shared kernel | a modell egy kis részét közösen birtokolják | kis, stabil közös rész, jó kommunikáció |
| Customer supplier | a fogyasztó igényeit a szolgáltató beépíti a tervezésbe | upstream és downstream világos viszonnyal |
| Conformist | a fogyasztó átveszi a szolgáltató modelljét változtatás nélkül | ha nincs befolyás és a modell elfogadható |
| Anticorruption layer (ACL) | fordító réteg védi a saját modellt a külső modelltől | legacy rendszer, rossz külső API, harmadik fél |
| Open host service | a szolgáltató jól definiált, nyilvános protokollt kínál | sok fogyasztó |
| Published language | dokumentált közös adatformátum (például iCalendar, UBL) | integráció szabványos nyelven |
| Separate ways | nincs integráció, mindenki megoldja magának | az integráció drágább, mint a duplikáció |
| Big ball of mud | határok nélküli rész, amit körbe kell keríteni | legacy terület jelölésére |
AI asszisztált fejlesztésnél az ACL a legfontosabb. Minden külső API (Stripe, számlázó, LLM szolgáltató, CRM) egy adapter mögé kerül, amely a külső modellt a saját domain típusaira fordítja. A domain kód soha nem lát Stripe objektumot.
5.2 Taktikai tervezés
| Építőelem | Lényege | Ellenőrző kérdés |
|---|---|---|
| Entity | identitása van, ami az életciklusán át megmarad | két példány akkor is különböző, ha minden mezőjük egyezik? |
| Value object | identitás nélküli, értéke határozza meg, megváltoztathatatlan | Money, EmailAddress, DateRange. Csere az új értékre, nem módosítás |
| Aggregate | konzisztencia határ, egy gyökér entityvel | melyik invariáns kell, hogy egy tranzakción belül mindig igaz legyen? |
| Repository | aggregátum szintű gyűjtemény absztrakció | aggregátum gyökérenként egy, nem táblánként |
| Domain service | olyan művelet, ami egyik entityhez sem tartozik természetesen | például árfolyam konverzió két érték között |
| Domain event | a domainben megtörtént, múlt idejű tény | RendelesLeadva, SzamlaKiallitva |
| Factory | bonyolult létrehozás elrejtése | amikor a konstruktor nem tudja garantálni az invariánsokat |
Vernon négy aggregátum szabálya
- Az igazi invariánsokat konzisztencia határon belül modellezzük.
- Kicsi aggregátumokat tervezünk. A nagy aggregátum zárolási ütközést és lassú betöltést okoz.
- Más aggregátumokra csak azonosítóval hivatkozunk, objektum referenciával nem.
- Az aggregátum határon kívül végső konzisztencia érvényes (domain eventtel).
Egy tranzakció egy aggregátumot módosít. Ha egy felhasználói műveletnek kettőt kell módosítania, az egyik szinkron, a másik eseményre reagál.
// Value object
export class Money {
private constructor(readonly amount: bigint, readonly currency: "HUF" | "EUR") {}
static of(amount: bigint, currency: "HUF" | "EUR") {
if (amount < 0n) throw new Error("Negatív összeg");
return new Money(amount, currency);
}
add(o: Money) {
if (o.currency !== this.currency) throw new Error("Eltérő pénznem");
return new Money(this.amount + o.amount, this.currency);
}
}
// Aggregate gyökér, az invariánst ő védi
export class Order {
private lines: OrderLine[] = [];
private status: "draft" | "placed" = "draft";
readonly events: DomainEvent[] = [];
constructor(readonly id: OrderId, readonly customerId: CustomerId) {} // más aggregátum csak ID
addLine(productId: ProductId, qty: number, price: Money) {
if (this.status !== "draft") throw new Error("Leadott rendelés nem módosítható");
this.lines.push(new OrderLine(productId, qty, price));
}
place() {
if (this.lines.length === 0) throw new Error("Üres rendelés nem adható le");
this.status = "placed";
this.events.push({ type: "OrderPlaced", orderId: this.id, at: new Date() });
}
}
Tipikus hibák. Anemic domain model (Fowler kifejezése), amikor az entity csak getter és setter, a logika a service osztályokban van. CRUD alkalmazásnál ez önmagában nem bűn, de a core domainben a szabályok szétszóródását okozza. Gyakori még a táblánkénti repository, a fél adatbázist betöltő nagy aggregátum, és a domain event, amely valójában parancs (SendEmail esemény néven).
5.3 Khononov, subdomain típusok és döntési heurisztika
| Subdomain | Jellemző | Példa | Javasolt megoldás |
|---|---|---|---|
| Core | versenyelőny, bonyolult, gyakran változik | ajánlatkalkulátor egyedi szabályokkal, ajánlómotor | házon belül, a legjobb emberrel, gazdag domain modellel |
| Supporting | szükséges, de nem különböztet meg, egyszerű | belső admin, egyedi riport | egyszerű megoldás, akár kiszervezve vagy low code |
| Generic | mindenki ugyanígy oldja meg | hitelesítés, számlázás, email küldés, fizetés | megvásárolt vagy kész szolgáltatás |
Döntési fa az üzleti logika mintájához
- Generic subdomain? Kész szolgáltatás (Supabase Auth, Stripe, Számlázz.hu API).
- Egyszerű adatbevitel és lekérdezés, kevés szabály? Transaction script (egy függvény egy üzleti művelet) vagy active record.
- Pénzt kezel, auditálni kell, vagy az állapotváltozások története üzleti érték? Event sourced domain model.
- Bonyolult üzleti szabályok, invariánsok? Domain model (az 5.2 pont építőelemei).
Az architektúra minta ehhez igazítva. Transaction script és active record mellé layered architektúra elég. Domain model mellé ports and adapters illik, event sourced domain model mellé CQRS.
A tesztelési stratégia ehhez igazítva. Domain modelnél tesztpiramis (sok unit teszt az aggregátumokon). Active recordnál gyémánt, ott az integrációs tesztek a legfontosabbak. Transaction scriptnél fordított piramis (főleg végponttól végpontig tartó tesztek).
Bounded context határ heurisztika. A bounded context nem feltétlenül egyezik a subdomainnel. Bizonytalan helyzetben szélesebb határral érdemes kezdeni, és akkor vágni szét, amikor a modell megérik. A core subdomaint érdemes a saját kontextusában tartani.
5.4 Event Storming (Brandolini)
Workshop technika, ahol a domain eseményeket egy hosszú papírfalon, színes cetlikkel rakják idősorba. A Big Picture változat a teljes üzletet, a Process Level egy folyamatot tár fel, a Software Design szint pedig az aggregátumokat és a bounded contexteket.
Lépések (Khononov tíz lépéses leírása szerint)
- Strukturálatlan feltárás. Mindenki narancs cetlire írja a domain eseményeket, múlt időben (Ajánlat elküldve, Szerződés aláírva).
- Idősor. Az eseményeket balról jobbra időrendbe rakják, a duplikátumokat összevonják.
- Fájdalompontok. Lila vagy rózsaszín cetli (hot spot) a vitatott, bizonytalan, problémás helyekre.
- Kulcsesemények (pivotal events). A folyamat fázisait elválasztó események, függőleges vonallal jelölve.
- Parancsok. Kék cetli, ami kiváltja az eseményt (Ajánlat elküldése), mellé sárga kis cetli a szereplővel.
- Szabályok (policy). Lila cetli, automatikus reakció egy eseményre (amikor a szerződés aláírva, akkor számla kiállítása).
- Olvasási modellek. Zöld cetli, az az adat, amit a szereplő lát, amikor dönt.
- Külső rendszerek. Rózsaszín cetli, amelyek parancsot adnak vagy eseményt kapnak.
- Aggregátumok. Nagy sárga cetli, amely a parancsokat fogadja és az eseményeket kibocsátja.
- Bounded contextek. Az összetartozó aggregátumok és események köré húzott határ.
Kis csapatos változat AI asszisztenssel. Az AI asszisztens egy beszélgetés átiratából vagy egy meglévő folyamatleírásból eseménylistát állít össze (múlt idejű igék, időrendben), ezt a domain szakértő javítja. Utána a modell parancsokat, szabályokat és aggregátum jelölteket rendel az eseményekhez egy táblázatban. A hot spotok listája a nyitott kérdések listája, ezekre addig nem generálunk kódot, amíg el nem dőlnek.
| # | Esemény (múlt idő) | Parancs | Szereplő vagy szabály | Aggregátum | Olvasási modell | Hot spot |
|---|--------------------|---------|-----------------------|------------|-----------------|----------|
| 1 | Érdeklődés beérkezett | Űrlap beküldése | Látogató | Lead | | |
| 2 | Cég átvilágítva | Átvilágítás indítása | szabály, új lead esetén | Lead | cégadat | ki dönt, ha negatív? |
| 3 | Ajánlat elküldve | Ajánlat küldése | Tanácsadó | Ajánlat | ármátrix | |
6. Hexagonal, Onion, Clean Architecture
6.1 Közös mag, a függőségi szabály
Mindhárom ugyanazt mondja más ábrával. A forráskód függőségei csak befelé, a domain felé mutathatnak, ezért a domain nem tud az adatbázisról, a webes keretrendszerről, a külső API-ról. Kifelé portokon (interfészeken) keresztül kommunikál, amelyeket a domain vagy az alkalmazási réteg határoz meg, és adapterek valósítanak meg.
| Változat | Kép | Hangsúly |
|---|---|---|
| Hexagonal, Ports and Adapters (Cockburn 2005) | hatszög, rajta portok, kívül adapterek | driving (elsődleges, például HTTP, CLI, teszt) és driven (másodlagos, például DB, email) adapterek szimmetriája |
| Onion (Palermo 2008) | koncentrikus körök, domain model, domain services, application services, infrastruktúra | az infrastruktúra a legkülső héj |
| Clean Architecture (Martin 2012) | körök, entities, use cases, interface adapters, frameworks and drivers | use case mint központi egység, a keretrendszer részletkérdés |
Könyvtárszerkezet egy moduláris monolitban, belül ports and adapters szerkezettel (TypeScript)
src/
modules/
ajanlat/
index.ts # a modul nyilvános felülete, más modul csak ezt importálja
domain/
ajanlat.ts # aggregate, value objectek, invariánsok
events.ts
application/
ajanlat-kuldese.ts # use case
ports.ts # interface AjanlatRepository, interface EmailKuldo
infrastructure/
supabase-ajanlat-repository.ts
resend-email-kuldo.ts
http/
routes.ts # driving adapter
szamlazas/
...
shared/
kernel/ # nagyon kicsi, stabil közös típusok (Money, Id)
main.ts # composition root, itt kötjük össze a portot az adapterrel
// application/ports.ts
export interface EmailKuldo { kuld(cimzett: string, targy: string, html: string): Promise<void> }
// application/ajanlat-kuldese.ts
export const ajanlatKuldese = (deps: { repo: AjanlatRepository; email: EmailKuldo }) =>
async (id: AjanlatId) => {
const a = await deps.repo.get(id);
a.kuldes(); // invariáns a domainben
await deps.repo.save(a);
await deps.email.kuld(a.cimzett, a.targy(), a.html());
};
6.2 Mikor túlzás
- CRUD alkalmazás, kevés szabállyal. Ide transaction script illik rétegzett szerkezetben, vagy vertical slice szerkezet (Jimmy Bogard), ahol egy funkció egy mappa, benne a kezelő, a lekérdezés és a validáció. Négy réteg és interfész minden táblához csak ceremónia, ami lassítja a változtatást.
- Prototípus, pilot, egyszer használatos szkript. Ott a sebesség a jellemző.
- Egyetlen adapter, ami soha nem fog cserélődni. Ha nincs második implementáció és nincs tesztelési igény, az interfész csak indirekció, Ousterhout szavaival sekély modul.
Mikor éri meg. Core subdomain, bonyolult invariánsok, legalább két driving adapter (HTTP és háttérfeladat, vagy HTTP és MCP szerver), reális szolgáltatócsere, vagy az az igény, hogy a domain logikát gyors, adatbázis nélküli unit tesztek fedjék le.
Pragmatikus köztes út. A domain és a külső szolgáltatások közé mindig kerül egy adapter (Parnas információrejtése, ACL), de a belső rétegeket nem bontjuk tovább, amíg nincs rá ok. AI asszisztált fejlesztésnél ez a mélység szinte mindig elég.
7. Dokumentálás, C4, arc42, ADR
7.1 C4 modell (Simon Brown)
Négy nagyítási szint, mint egy térképen.
| Szint | Mit mutat | Kinek | Kötelező? |
|---|---|---|---|
| 1. System Context | a rendszer, a felhasználói és a külső rendszerek | mindenki, üzleti oldal is | mindig |
| 2. Container | futtatható vagy adattároló egységek (web app, API, adatbázis, edge function, üzenetsor) és a köztük lévő protokollok | fejlesztők, üzemeltetés | mindig |
| 3. Component | egy container belső komponensei | fejlesztők | ha a container bonyolult |
| 4. Code | osztálydiagram | ritkán | szinte soha, a kód maga a dokumentáció |
Kiegészítő diagram a System Landscape (a cég összes rendszere), a Dynamic (egy forgatókönyv lépései) és a Deployment (melyik container hol fut).
Jelölési szabályok. Minden doboznak legyen típusa és technológiája. A nyilak egyirányúak, felirattal (mit és hogyan, például Számlát kér, HTTPS JSON). Jelmagyarázat is kell, a diagramnak pedig címe és hatóköre.
Diagram mint kód (Structurizr DSL)
workspace {
model {
tanacsado = person "Tanácsadó"
ugyfel = person "Ügyfél"
crm = softwareSystem "Ajánlatkezelő CRM" {
web = container "Web app" "Next.js"
db = container "Adatbázis" "Supabase Postgres" { tags "Database" }
fn = container "Edge functions" "Deno"
}
szamlazo = softwareSystem "Számlázó szolgáltatás" { tags "External" }
tanacsado -> web "Kezeli az ajánlatokat" "HTTPS"
ugyfel -> web "Elfogadja az ajánlatot" "HTTPS"
web -> db "Olvas, ír" "PostgREST, RLS"
fn -> szamlazo "Számlát állít ki" "HTTPS JSON"
}
views { systemContext crm { include * autolayout lr } container crm { include * autolayout lr } }
}
Structurizr nélkül a Mermaid C4 szintaxisa (C4Context, C4Container) is renderelhető markdownban.
7.2 arc42
Tizenkét szakaszos sablon. Nem kell mindet kitölteni, egy kis projektnek a vastagon jelöltek elegendők.
| # | Szakasz | Tartalom |
|---|---|---|
| 1 | Bevezetés és célok | feladat, top 3 minőségi cél, érintettek |
| 2 | Kényszerek | technikai, szervezeti, jogi korlátok |
| 3 | Kontextus és hatókör | C4 System Context |
| 4 | Megoldási stratégia | a kulcsdöntések egy oldalon |
| 5 | Építőelem nézet | C4 Container és Component |
| 6 | Futásidejű nézet | fő forgatókönyvek szekvenciái |
| 7 | Telepítési nézet | infrastruktúra |
| 8 | Átfogó koncepciók | hibakezelés, naplózás, biztonság, i18n |
| 9 | Architekturális döntések | ADR lista hivatkozással |
| 10 | Minőségi követelmények | utility tree, forgatókönyvek |
| 11 | Kockázatok és technikai adósság | |
| 12 | Fogalomtár | ubiquitous language |
7.3 Architecture Decision Record
Mikor kell ADR. Ha a döntést nehéz visszafordítani (adatbázis, hitelesítés módja, bérlőelválasztás modellje), ha több értelmes alternatíva volt, ha egy szabályt tudatosan megszegünk, vagy ha egy jövőbeli olvasó (új kolléga, egy új AI munkamenet) azt kérdezné, miért így van ez.
Nygard sablon (2011)
# ADR-0007. Bérlőelválasztás sor szintű biztonsággal (RLS) egy adatbázisban
## Állapot
Elfogadva, 2026-10-20
## Kontextus
Több ügyfél adata kerül egy rendszerbe. Egy ember üzemelteti. Az ügyfelek száma 50 alatt.
## Döntés
Egy Postgres adatbázis, minden bérlőhöz tartozó táblán tenant_id oszlop és RLS policy.
Bérlőnként külön séma vagy adatbázis nem lesz.
## Következmények
+ Egy migráció, egy biztonsági mentés, olcsó üzemeltetés.
- Egy hibás policy minden bérlőt érint, ezért CI fitness function ellenőrzi, hogy minden táblán be van kapcsolva az RLS.
- Bérlőnkénti visszaállítás csak logikai exporttal megy.
A lehetséges állapotok Javasolt, Elfogadva, Elvetve, Elavult és Felváltotta ADR-XXXX. Az ADR megváltoztathatatlan. Ha a döntés változik, új ADR készül, ami felváltja a régit.
MADR 4.0 sablon (bővebb, ha alternatívákat kell összevetni)
# <rövid cím, a megoldott probléma és a választott megoldás>
## Context and Problem Statement
## Decision Drivers
## Considered Options
## Decision Outcome
Chosen option: "...", because ...
### Consequences
### Confirmation <- hogyan ellenőrizzük, hogy betartják (fitness function, review)
## Pros and Cons of the Options
## More Information
Hely és eszköz. Sorszámozott markdown fájlok a kód mellett, verziókezelve (például docs/adr/0001-cim.md). Eszköz lehet az adr-tools vagy a log4brains, de egy markdown fájl is elég.
8. Stabilitás, Release It! (Nygard, 2. kiadás 2018)
Az alaptétel szerint minden integrációs pont előbb-utóbb meghibásodik, és a rendszer túlélése azon múlik, megállítjuk-e a hiba terjedését.
8.1 Stabilitási antiminták
| Antiminta | Mi történik | Felismerés |
|---|---|---|
| Integration points | minden külső hívás (HTTP, DB, socket) hibaforrás, beleértve a lassú választ is | hívás timeout nélkül |
| Chain reactions | egy példány kiesése után a többire nagyobb terhelés jut, és sorban dőlnek el | memóriaszivárgás, ami terheléssel gyorsul |
| Cascading failures | egy réteg hibája felfelé terjed a hívókra | szinkron hívásláncok védelem nélkül |
| Users | a felhasználók száma, viselkedése, a botok és a rosszindulatú forgalom | munkamenet memóriában, korlátlan feltöltés |
| Blocked threads | a szálak vagy kapcsolatok elfogynak, mert valamire örökké várnak | connection pool kimerülés |
| Self denial attacks | saját marketing kampány vagy kupon dönti le a rendszert | előre nem jelzett akciók |
| Scaling effects | ami 2 példánynál működik, 50-nél nem (példányok közti közvetlen kapcsolatok, közös erőforrás) | O(n négyzet) kommunikáció |
| Unbalanced capacities | a front sokkal többet bír, mint a háttér | a háttérszolgáltatás kisebb, mint a hívói |
| Dogpile | sok kliens egyszerre indul (cache lejárat, cron egész órakor, újraindítás után) | szinkronizált retry |
| Force multiplier | automatizálás, ami a hibát felnagyítja (autoscaler, konfigurációkezelő) | ellenőrzés nélküli automatikus beavatkozás |
| Slow responses | a lassú válasz rosszabb, mint a hiba, mert lefoglalja a hívót | |
| Unbounded result sets | lekérdezés limit nélkül | select * lapozás nélkül, LLM válasz max token nélkül |
8.2 Stabilitási minták
| Minta | Lényege | Konkrétan |
|---|---|---|
| Timeouts | minden külső hívásnak legyen időkorlátja | kapcsolódási és olvasási timeout külön, retry exponenciális visszalépéssel és jitterrel, legfeljebb kétszer-háromszor |
| Circuit breaker | ha a hibaarány átlép egy küszöböt, a hívások egy ideig azonnal elbuknak, majd félig nyitott állapotban próbálkozik | zárt, nyitott, félig nyitott állapot. Könyvtár például opossum (Node), resilience4j (Java), Polly (.NET) |
| Bulkheads | erőforrások elkülönítése, hogy egy rész kimerülése ne vigye el a többit | külön connection pool vagy szálkészlet a kritikus és a kevésbé kritikus hívásoknak, külön példány a riportolásnak |
| Steady state | a rendszer emberi beavatkozás nélkül hosszú ideig futtatható | naplórotáció, régi adatok törlése vagy archiválása, cache méretkorlát |
| Fail fast | ha előre látszik, hogy a kérés el fog bukni, azonnal elutasítjuk | erőforrások ellenőrzése a munka elején, bemenet validálás a határon |
| Let it crash | egy komponens inkább induljon újra tiszta állapotból (Erlang hagyomány) | felügyelő újraindít, gyors indulás kell hozzá |
| Handshaking | a szerver jelezheti, hogy nem tud több munkát fogadni | health check, ami a valós kapacitást mutatja, HTTP 503 Retry-After fejléccel |
| Test harnesses | hamis külső szolgáltatás, ami hibásan viselkedik | lassú, félig válaszoló, rossz formátumú válasz szimulálása |
| Decoupling middleware | üzenetsor időben elválasztja a küldőt és a fogadót | |
| Shed load | túlterhelésnél kérések eldobása, hogy a többit ki lehessen szolgálni | rate limit, 429 válasz |
| Create back pressure | a fogyasztó lassítja a termelőt, korlátos sorral | korlátos várakozási sor, ami tele állapotban blokkol vagy elutasít |
| Governor | az automatizálás sebességének korlátozása | autoscaler lépcső és felső korlát, megerősítés kérése romboló műveleteknél |
Mai alkalmazás LLM hívásokra. Az LLM szolgáltató is integrációs pont, ugyanazok a szabályok érvényesek rá. Timeout, retry jitterrel a 429 és a túlterhelést jelző 5xx válaszoknál, költségkorlát (governor), max_tokens (unbounded result set ellen), tartalék modell vagy degradált válasz (circuit breaker után), és bulkhead, hogy a háttérben futó kötegelt feldolgozás ne egye meg az interaktív felhasználók kvótáját.
async function hivasTimeouttal<T>(fn: (s: AbortSignal) => Promise<T>, ms = 10_000, proba = 3): Promise<T> {
for (let i = 0; ; i++) {
const ac = new AbortController();
const t = setTimeout(() => ac.abort(), ms);
try { return await fn(ac.signal); }
catch (e) {
if (i >= proba - 1 || !ujraprobalhato(e)) throw e;
await new Promise(r => setTimeout(r, 2 ** i * 500 + Math.random() * 250)); // backoff plusz jitter
} finally { clearTimeout(t); }
}
}
9. A Philosophy of Software Design (Ousterhout, 2. kiadás 2021)
Ousterhout a bonyolultságot három tünettel írja le. Ezek a változásfelnagyítás (egy egyszerű változás sok helyen kell), a kognitív terhelés (mennyit kell tudni egy változtatáshoz) és az ismeretlen ismeretlenek (nem derül ki, mit kell módosítani). Okai a függőségek és a homályosság (obscurity).
9.1 Fő elvek
Mély modulok. A modul értéke a funkcionalitás és a felület aránya. Mély modul egyszerű felület mögött sok funkciót rejt (a Unix fájl I/O öt hívással). Sekély modul felülete majdnem olyan bonyolult, mint a megvalósítása. Az osztályok minél kisebbre darabolása (classitis) sok sekély modult szül.
Információrejtés és szivárgás. A Parnas elv mai formája. Information leakage akkor van, ha ugyanaz a tervezési döntés (például egy fájlformátum) több modulban is megjelenik. Tipikus oka a temporal decomposition, amikor a kód a végrehajtás sorrendje szerint bomlik (olvasás, feldolgozás, írás modul), pedig a fájlformátum ismerete mindháromba kell.
Az általános célú modulok mélyebbek. A felület legyen kissé általánosabb, mint a mostani igény, a megvalósítás viszont a mostani igényt szolgálja. Ellenőrző kérdés, hogy mi a legegyszerűbb felület, ami lefedi az összes jelenlegi igényt.
A bonyolultság lefelé húzása (pull complexity downward). Jobb, ha a modul írója szenved, mint ha minden hívója. Konfigurációs paraméter helyett jó alapértelmezés kell.
Define errors out of existence. A kivételek bonyolultságot adnak. Ezért úgy tervezzük a szemantikát, hogy a hibaeset ne létezzen. Például a delete idempotens (ha nincs mit törölni, az is siker), a substring a tartományon kívüli indexeket levágja. Egyéb technikák a kivétel elfedése (exception masking), az aggregálás (sok hibát egy helyen kezelünk) és az összeomlás (just crash), ha a hiba ritka és helyreállíthatatlan.
Különböző réteg, különböző absztrakció. Ha két szomszédos réteg ugyanazt az absztrakciót kínálja, az egyik felesleges. Ennek tünete a pass through method.
Stratégiai és taktikai programozás. A taktikai programozó a feature gyors elkészülésére optimalizál, a stratégiai a rendszer szerkezetére is (a szerző a munkaidő 10 és 20 százaléka közé teszi ezt a befektetést). Tactical tornado az a fejlesztő, aki gyorsan szállít és szétszórt bonyolultságot hagy maga után. Kontroll nélküli AI generálás ennek gépi változata.
Kommentek. A komment azt írja le, ami a kódból nem derül ki (miért, milyen feltételek mellett, milyen mértékegységben). Előbb készüljön el a felület kommentje, mint a megvalósítás (comment driven design), mert ha nehéz leírni, rossz a felület.
9.2 Red flags
| Jel | Mit jelent |
|---|---|
| Shallow module | a felület nem sokkal egyszerűbb, mint a megvalósítás |
| Information leakage | ugyanaz a döntés több modulban |
| Temporal decomposition | a szerkezet a végrehajtás sorrendjét követi, nem a rejtett tudást |
| Overexposure | a gyakori használathoz ritka funkciókat is ismerni kell |
| Pass through method | a metódus csak továbbadja a paramétereit egy hasonló metódusnak |
| Repetition | ugyanaz a kódrészlet több helyen |
| Special general mixture | az általános célú kódba speciális esetek keverednek |
| Conjoined methods | két metódust csak együtt lehet megérteni |
| Comment repeats code | a komment a kódot ismétli |
| Implementation documentation contaminates interface | a felület kommentje megvalósítási részleteket tartalmaz |
| Vague name | a név semmit nem mond (data, info, manager, handle) |
| Hard to pick name | nehéz nevet adni, a felelősség nem tiszta |
| Hard to describe | a dokumentáció hosszú, a modul túl sokat csinál |
| Nonobvious code | a viselkedés nem érthető gyors olvasásra |
AI asszisztált fejlesztésnél. A generált kód két jellegzetes hibája a sekély modul (minden egy apró utils függvény vagy wrapper osztály) és a repetition (a modell nem tud a meglévő segédfüggvényről, ezért újat ír). Ellenszer, hogy új függvény írása előtt az AI asszisztens keres a kódbázisban (grep a hasonló nevekre és mintákra), és a modul felületét előbb mondatokban fogalmazza meg.
10. Team Topologies, Conway törvénye, kognitív terhelés
10.1 Négy csapattípus, három interakciós mód
| Csapattípus | Feladat |
|---|---|
| Stream aligned | egy értékfolyamért (termék, felhasználói út) felel végponttól végpontig. Ez az alapértelmezés, a többi őt szolgálja |
| Enabling | ideiglenesen segít egy stream aligned csapatnak új képesség elsajátításában |
| Complicated subsystem | mély szakértelmet igénylő részt visz (videókódoló, számítási motor, ML modell) |
| Platform | belső szolgáltatásokat ad önkiszolgáló módon, hogy csökkentse a stream aligned csapatok terhét |
| Interakciós mód | Mikor |
|---|---|
| Collaboration | felfedezés idején, rövid ideig, magas költséggel |
| X as a Service | stabil, jól definiált felületnél, alacsony koordinációval |
| Facilitating | enabling csapat segít, majd kivonul |
10.2 Conway törvénye és az inverz manőver
Conway törvénye (1968) szerint a rendszer szerkezete a szervezet kommunikációs szerkezetét másolja. Az inverz Conway manőver ezt tudatosan használja, előbb a kívánt architektúrát tervezik meg, majd ahhoz igazítják a csapatokat és a kommunikációs csatornákat. Ha három csapat dolgozik egy rendszeren, három fő komponens lesz, akár akarják, akár nem.
10.3 Kognitív terhelés
Egy csapat (és egy ember) kognitív kapacitása korlátos, a terhelésnek három típusa van. Intrinsic (a feladat lényegi nehézsége), extraneous (a környezet okozta, például bonyolult deploy, kézi lépések, rossz eszközök), germane (a domain megértése, ez az értékes). Az extraneous terhet kell minimalizálni, hogy maradjon kapacitás a germane részre. A szoftver határait úgy húzzuk meg, hogy egy csapat egy darabot teljesen fejben tudjon tartani (team sized software).
A 2025-ös 2. kiadás a megközelítést a platform szemlélet és a gyors áramlás (fast flow) irányába finomítja, a lényeg változatlan (a 2026 októberi állapot szerint, ellenőrizendő).
Egyszemélyes fejlesztés AI asszisztenssel. Itt a csapat egy ember, a kognitív kapacitás egy emberé. Az AI asszisztens csökkenti az extraneous terhet (boilerplate, konfiguráció), de növelheti is, ha a generált szerkezet több darabból áll, mint amit egy ember átlát. Szabály, hogy a rendszer annyi deploy egységből, annyi technológiából és annyi modulból álljon, amennyit a fejlesztő fejben tud tartani. A platform csapat szerepét a menedzselt szolgáltatások töltik be (Supabase, Vercel, Cloudflare).
11. Megbízhatóság mérése, SRE és DORA
11.1 SLI, SLO, error budget
| Fogalom | Meghatározás | Példa |
|---|---|---|
| SLI (service level indicator) | mért arány, jó események per összes esemény | sikeres (nem 5xx) és 300 ms alatti válaszok aránya |
| SLO (service level objective) | cél az SLI-re egy időablakban | 99,5% 28 napos gördülő ablakban |
| SLA (service level agreement) | szerződéses vállalás következménnyel | az SLO-nál lazább |
| Error budget | 1 mínusz SLO | 0,5%, azaz 28 napon kb. 3 óra 22 perc |
Lépések
- Felhasználói út kiválasztása (bejelentkezés, ajánlat megnyitása, fizetés).
- SLI meghatározása a felhasználó szemszögéből (rendelkezésre állás, késleltetés, helyesség, frissesség).
- SLO beállítása a jelenlegi teljesítmény és az igény alapján. A 100% helytelen cél.
- Error budget szabály írásban. Ha a büdzsé elfogyott, új funkció helyett megbízhatósági munka jön.
- Riasztás a büdzsé fogyási sebességére (burn rate), nem minden egyes hibára. A Workbook többablakos burn rate riasztást javasol (például 1 órás és 5 perces ablak 14,4 szeres fogyásnál).
11.2 Toil
A toil kézi, ismétlődő, automatizálható, taktikai, tartós érték nélküli munka, ami a szolgáltatás méretével lineárisan nő. Google célja, hogy az SRE munkaidő legfeljebb 50 százaléka legyen toil. Kis csapatnál a toil azonosítása egyszerű, ami harmadszor fordul elő kézzel, azt szkript vagy ütemezett feladat váltja ki.
11.3 Accelerate és DORA metrikák
| Metrika | Mit mér | Csoport |
|---|---|---|
| Deployment frequency | milyen gyakran kerül élesbe változás | áteresztés (throughput) |
| Lead time for changes | commit és éles között eltelt idő | áteresztés |
| Change failure rate | élesítések hány százaléka okoz hibát | stabilitás |
| Failed deployment recovery time (korábban time to restore) | mennyi idő alatt áll helyre egy hibás élesítés után | stabilitás |
| Rework rate (2024 óta) | nem tervezett, hibajavító élesítések aránya | stabilitás |
A 2021-es jelentés az operatív teljesítményt (reliability) ötödik dimenzióként vezette be, a 2024-es pedig a rework rate-et ötödik élesítési metrikaként. Az Accelerate kutatás fő eredménye, hogy a sebesség és a stabilitás nem egymás ellen hat, a legjobb csapatok mindkettőben jók. A 2024 és 2025 közötti DORA jelentések szerint az AI használat növeli az egyéni produktivitást, de kontroll nélkül ronthatja a szállítási stabilitást. Javulás ott jön, ahol megvan a kis változtatási csomag, az erős tesztelés és a jó belső platform, vagyis az AI felerősíti azt, ami a csapatban már megvan (a 2026 októberi állapot szerint).
Kis csapatnál AI asszisztenssel. A DORA metrikák közül a lead time és a change failure rate a hasznos. Cél a sok kicsi, gyakori, visszafordítható élesítés a ritka nagy helyett.
12. Twelve Factor App és ami azóta változott
| # | Faktor | Eredeti lényeg (2011) | 2026-os megjegyzés |
|---|---|---|---|
| I | Codebase | egy kódbázis verziókezelve, sok deploy | monorepó is elfogadott, ha a deploy egységek világosak |
| II | Dependencies | explicit deklarálás és izolálás | lock fájl kötelező, ellátási lánc ellenőrzés (SBOM, SLSA) |
| III | Config | konfiguráció környezeti változóban | a titkok titokkezelőben (Vault, Doppler, Supabase secrets), nem .env fájlban a repóban |
| IV | Backing services | a csatolt erőforrás cserélhető URL | változatlan |
| V | Build, release, run | szigorúan elválasztott fázisok | immutable artifact, konténer kép digest szerint |
| VI | Processes | állapotmentes folyamatok | serverless és edge esetén magától értetődő |
| VII | Port binding | a szolgáltatás saját portot exportál | serverless platformnál nem releváns |
| VIII | Concurrency | skálázás folyamatokkal | a platform végzi (autoscaling) |
| IX | Disposability | gyors indulás, kecses leállás | cold start serverlessnél újra fontos |
| X | Dev/prod parity | fejlesztés és éles hasonló | preview környezet ágonként, helyi Supabase |
| XI | Logs | eseményfolyam a stdout-ra | strukturált napló, OpenTelemetry nyomkövetés és metrika |
| XII | Admin processes | egyszeri feladatok ugyanabban a környezetben | migrációk verziózva, CI-ből futtatva |
Azóta hozzájött (Kevin Hoffman, Beyond the Twelve Factor App, 2016, plusz a mai gyakorlat). API first tervezés, telemetria (megfigyelhetőség mint első osztályú követelmény), hitelesítés és jogosultság minden kérésnél (zero trust), feature flag, infrastruktúra mint kód. A Heroku 2024-ben nyílt forrásúvá tette a 12 factor szöveget, hogy a közösség modernizálja. Titokkezelés és zero trust ügyében a biztonsági részleteket a kiberbiztonsági kézikönyv tárgyalja.
13. Meglévő kód megváltoztatása
13.1 Refactoring (Fowler, 2. kiadás 2018)
A refaktorálás a kód belső szerkezetének megváltoztatása a megfigyelhető viselkedés megváltoztatása nélkül, kis, biztonságos lépésekben, mindegyik után futó tesztekkel. Fowler 2. kiadása JavaScript példákkal dolgozik, és a függvényeket az osztályokkal egyenrangúan kezeli.
Két kalap szabály (Kent Beck). Egy időben vagy funkciót adunk hozzá, vagy refaktorálunk. A kettő nem keveredik egy lépésben és egy commitban.
Code smells (a 2. kiadás 24 szaga)
| Szag | Tipikus refaktor |
|---|---|
| Mysterious Name | Rename Variable, Change Function Declaration |
| Duplicated Code | Extract Function, Slide Statements |
| Long Function | Extract Function, Replace Temp with Query, Decompose Conditional |
| Long Parameter List | Introduce Parameter Object, Preserve Whole Object |
| Global Data | Encapsulate Variable |
| Mutable Data | Encapsulate Variable, Separate Query from Modifier |
| Divergent Change | Split Phase, Extract Class (egy modul sokféle okból változik) |
| Shotgun Surgery | Move Function, Combine Functions into Class (egy változás sok helyen) |
| Feature Envy | Move Function |
| Data Clumps | Extract Class, Introduce Parameter Object |
| Primitive Obsession | Replace Primitive with Object (value object) |
| Repeated Switches | Replace Conditional with Polymorphism |
| Loops | Replace Loop with Pipeline |
| Lazy Element | Inline Function, Inline Class |
| Speculative Generality | Collapse Hierarchy, Remove Dead Code |
| Temporary Field | Extract Class, Introduce Special Case |
| Message Chains | Hide Delegate |
| Middle Man | Remove Middle Man |
| Insider Trading | Move Function, Hide Delegate |
| Large Class | Extract Class, Extract Superclass |
| Alternative Classes with Different Interfaces | Change Function Declaration, Move Function |
| Data Class | Encapsulate Record, Move Function |
| Refused Bequest | Push Down Method, Replace Superclass with Delegate |
| Comments | Extract Function, Introduce Assertion |
AI asszisztált fejlesztésnél. A refaktorálási kérés egy szagot, egy refaktort és egy commitot jelent. Ha egy kérés funkcióváltozást és refaktort keverne, az AI asszisztens ezt jelzi, és kettébontja.
13.2 Legacy kód (Feathers 2004)
Feathers definíciója szerint legacy kód az, aminek nincs tesztje. A dilemma, hogy a változtatáshoz teszt kellene, a teszthez pedig változtatás (a függőségek miatt).
Seam (varrat). Olyan hely, ahol a viselkedés a kód szerkesztése nélkül megváltoztatható. Minden seamnek van engedélyező pontja (enabling point), ahol eldől, melyik viselkedés fut.
| Seam típus | Engedélyező pont | Mai megfelelő |
|---|---|---|
| Preprocessing seam | makró, fordítás előtti feldolgozás | build flag |
| Link seam | melyik könyvtár linkelődik | modul alias, vi.mock, jest.mock |
| Object seam | melyik objektumot kapja a kód | függőség injektálás, paraméterként átadott kliens |
A legacy kód változtatási algoritmusa
- Változási pontok azonosítása.
- Tesztpontok megkeresése.
- Függőségek megtörése (seam bevezetése).
- Tesztek írása.
- Változtatás és refaktorálás.
Characterization test. Olyan teszt, ami a jelenlegi viselkedést rögzíti, nem a helyeset. Írunk egy tesztet szándékosan rossz elvárással, a hibaüzenetből kiolvassuk a tényleges eredményt, és azt írjuk be elvárásnak. Mai változata a snapshot vagy golden master teszt, és az approval testing.
Technikák új kódhoz régi környezetben. Sprout method vagy sprout class (az új logika új, tesztelt függvénybe kerül, a régi csak meghívja), wrap method vagy wrap class (a régi köré tesztelt burok kerül).
AI asszisztált fejlesztésnél. Ismeretlen kód módosítása előtt az AI asszisztens először characterization teszteket ír a módosítandó függvényekre, és csak utána változtat. Ez kiszűri, ha a generált változtatás csendben más viselkedést is módosít.
13.3 Strangler Fig (Fowler 2004)
Az új rendszer fokozatosan nő a régi köré, és funkciónként veszi át a forgalmat, amíg a régi kikapcsolható.
Lépések
- Homlokzat (proxy, API gateway, router) a régi rendszer elé, kezdetben mindent átenged.
- Egy szelet kiválasztása (kis, jól körülhatárolt, értékes funkció).
- A szelet megírása az új rendszerben.
- A homlokzat az adott útvonalat az újra irányítja (feature flaggel, fokozatosan).
- Párhuzamos futtatás (parallel run), ha a helyesség kritikus. Mindkettő fut, az eredményeket összevetjük, és a régi a mérvadó.
- A régi kód törlése az adott szeletre.
- Ismétlés.
Kapcsolódó minták Newmantól a branch by abstraction (a kódon belül absztrakció mögé kerül a régi és az új implementáció), a decorating collaborator és a change data capture (az adatváltozások folyama a régi adatbázisból).
13.4 Tidy First? (Kent Beck 2023)
Alapgondolat. A szerkezeti változtatást (tidying) elválasztjuk a viselkedési változtatástól, külön commitban, ideálisan külön PR-ban. Minden alkalommal felmerül, hogy előbb jöjjön a rendrakás, utána, később vagy soha. A válasz gazdasági. Előbb akkor érdemes rendet rakni, ha az olcsóbbá teszi a következő változtatást, és maga is olcsó.
Tidyingek (kis, biztonságos lépések)
| Tidying | Mit csinál |
|---|---|
| Guard clauses | korai visszatérés a mély beágyazás helyett |
| Dead code | használaton kívüli kód törlése |
| Normalize symmetries | ugyanaz a dolog mindenhol ugyanúgy legyen megírva |
| New interface, old implementation | a kívánt felület bevezetése, ami a régit hívja |
| Reading order | a fájl sorrendje az olvasás sorrendje |
| Cohesion order | az együtt változó elemek egymás mellé kerülnek |
| Move declaration and initialization together | deklaráció és kezdőérték egy helyre kerül |
| Explaining variables, explaining constants | magyarázó nevű változó vagy konstans egy kifejezés helyett |
| Explicit parameters | rejtett bemenet (globális, környezet) helyett paraméter |
| Chunk statements | üres sor a logikai blokkok között |
| Extract helper | segédfüggvény kiemelése |
| One pile | túldarabolt kód visszaolvasztása, hogy átlátható legyen, majd újradarabolás |
| Explaining comments, delete redundant comments | magyarázó komment ott, ahol kell, a felesleges törlése |
Elméleti háttér. A szoftver költsége lényegében a változtatás költsége, ami a csatolás költsége (Constantine egyenértékűsége). Rendrakással opció születik a jövőbeli változtatásra. Az időérték elve szerint a ma megszerzett érték többet ér, mint a holnapi, ezért a rendrakás nem lehet öncél.
AI asszisztált fejlesztésnél. A funkcióváltozás előtt egy külön commitban készülnek el a szükséges tidyingek (például guard clause, explaining variable), lefutnak a tesztek, és csak utána jön a viselkedési változás. Így a diff olvasható marad.
14. Tesztelés, TDD, piramis és trófea
14.1 TDD (Beck 2002)
A ciklus
- Red. Egy kicsi, bukó teszt a következő viselkedésre.
- Green. A legkisebb kód, amitől átmegy (akár hamisítva).
- Refactor. A duplikáció és a rossz szerkezet eltüntetése, zöld tesztekkel.
Teszt lista. A munka elején felírjuk a teszteseteket, amelyek eszünkbe jutnak, és egyesével haladunk. Beck 2023-ban a Canon TDD írásában megerősítette, hogy a lista, a lépésenként egy teszt és a refaktorálás a lényeg, nem a teszt előbb írásának dogmája.
Mikor éri meg. Üzleti szabályok, számítások, parserek, állapotgépek esetén. UI elrendezésnél és feltáró prototípusnál kevésbé.
AI asszisztált fejlesztésnél. A TDD kiváló kontroll a generált kód fölött. Előbb a kódgeneráló modell írja meg a teszteket a specifikációból, ezeket a fejlesztő jóváhagyja (ez olcsóbb, mint a kódot átnézni), majd a modell addig implementál, amíg zöld nem lesz. Közben a teszteket nem módosíthatja azért, hogy átmenjenek.
14.2 Testing pyramid és testing trophy
| Modell | Szerző | Alakja | Hangsúly |
|---|---|---|---|
| Test pyramid | Mike Cohn 2009, Fowler és Ham Vocke 2018 (Practical Test Pyramid) | sok unit, kevesebb service vagy integrációs, kevés UI teszt | gyors, olcsó, izolált tesztek a bázisban |
| Testing trophy | Kent C. Dodds 2018 | statikus elemzés alul, kevés unit, sok integrációs, kevés e2e | a felhasználói viselkedéshez közeli tesztek adják a legtöbb bizalmat |
| Testing honeycomb | Spotify 2018 | kevés implementációs részlet teszt, sok integrációs, kevés integrált | microservices környezet |
Választás. Domain modellnél (sok szabály) piramis. Webalkalmazásnál, ahol a logika vékony és főleg komponensek, API és adatbázis együttműködéséből áll, trófea. A Khononov féle hozzárendelés (5.3 pont) jó kiindulás.
Mai trófea egy TypeScript projektben
Statikus: TypeScript strict, ESLint, dependency-cruiser (mindig, minden commitnál)
Unit: Vitest a tiszta domain függvényekre (ahol szabály van)
Integráció: Vitest plus helyi Supabase vagy Testcontainers (API végpontok, RLS policyk)
E2E: Playwright 3-10 kritikus felhasználói útra (bejelentkezés, fizetés)
Tipikus hiba. Mock mindenre, ami a tesztet a megvalósításhoz köti. Refaktornál minden teszt eltörik, a valódi hibát viszont egyik sem fogja meg. Másik gyakori hiba, hogy az AI olyan tesztet ír, ami a saját implementációját ismétli meg elvárásként, ezért mindig zöld.
15. Monolit vagy microservices, moduláris monolit
15.1 Newman döntési szempontjai
Newman szerint a microservices eszköz, nem cél és nem alapértelmezés. Akkor éri meg, ha az alábbi célok valamelyike fontos, és egyszerűbb eszközzel nem érhető el.
- Több csapat független fejlesztése és élesítése.
- Eltérő skálázási igény egyes részeknél.
- Hibaelszigetelés (robustness).
- Technológiai heterogenitás.
- A régi rendszer fokozatos lecserélése.
Microservices ellen szól, ha új a domain és még nem tiszták a határok (a rossz határt elosztott rendszerben nagyon drága javítani), kicsi a csapat, nincs automatizált deploy és megfigyelhetőség, vagy a fő cél a sebesség egy új terméknél. Newman és Fowler (MonolithFirst, 2015) egyaránt monolittal kezdést javasol új rendszernél.
Az elosztott rendszer költségei. Hálózati késleltetés és hiba (az elosztott számítástechnika tévhitei, Deutsch), végső konzisztencia, elosztott nyomkövetés, verziózás, szerződéstesztek, több deploy pipeline, nehezebb lokális fejlesztés.
Monolith to Microservices migrációs lépések
- A cél megfogalmazása (miért akarunk szétbontani, mit mérünk).
- Domain modell és határok (event storming, context map).
- Az első szolgáltatás kiválasztása. Alacsony bonyolultság, magas érték, kevés adatfüggőség.
- Kódszétválasztás (strangler fig, branch by abstraction).
- Adatszétválasztás (először séma, aztán adatbázis, a 3.2 pont szerint), olyan mintákkal, mint a database view, a database wrapping service és a change data capture.
- Mérés, majd a következő szelet.
15.2 A moduláris monolit kialakítása
Szabályok
- Domain particionálás. A felső szintű mappák bounded contextek vagy subdomainek (
ajanlat,szamlazas,crm), nem technikai rétegek (controllers,services,models). - Nyilvános felület modulonként. Egy
index.tsvagyapicsomag, minden más belső. Fitness function ellenőrzi (4.2 pont). - Adattulajdonlás. Minden tábla egy modulhoz tartozik, más modul nem írja, és lehetőleg közvetlenül nem is olvassa, hanem a tulajdonos modul felületén keresztül éri el. Postgresben séma per modul.
- Kommunikáció a modulok között. Szinkron függvényhívás a nyilvános felületen, vagy belső domain event (in process event bus, outbox táblával, ha megbízható kézbesítés kell).
- Nincs ciklikus függőség a modulok között.
- Közös kód minimális. A
sharedcsak stabil, domain független típusokat tartalmaz. Ami üzleti logika, az egy modulé. - Egy deploy, egy adatbázis. A modularitás logikai, a fizikai szétválasztás opció marad.
Eszközök. Spring Modulith (Java), Packwerk (Ruby, a Shopify, amely a moduláris monolitot nagy léptékben is megmutatta), Nx vagy Turborepo modulhatárokkal (TypeScript), import-linter (Python), .NET esetén projektek modulonként és NetArchTest.
Mikor érdemes továbblépni. Ha egy modulnak quantum szinten eltérő jellemző kell (elasticity, eltérő biztonsági zóna), vagy egy modult külön csapat visz. Ilyenkor az a modul kiemelhető egy service based architektúra szolgáltatásává, a határ már megvan.
16. A gyakorlatban
A cél, hogy a generálás sebessége ne rontsa a szerkezetet. Az alábbi szabályok a tervezés, az írás és az asztali ellenőrzés hagyományos munkarendjét egészítik ki architektúra szinten, és ugyanúgy érvényesek kézzel írt és AI asszisztenssel generált kódra.
16.1 Öt perces architektúra kártya új projekt előtt
Új projekt vagy új nagyobb modul előtt a csapat kitölti ezt a kártyát, és a döntéshozóval együtt átnézi. A kártya a repó gyökerébe kerül (ARCHITECTURE.md), vagy az AI asszisztens projektszintű instrukciós fájljának elejére.
# Architektúra kártya. <projekt>, <dátum>
**Egy bekezdés.** Mit csinál a rendszer, kinek, milyen fő úton.
**Top 3 jellemző** (mérhető céllal)
1. ...
2. ...
3. ...
Szándékosan nem optimalizált: ...
**Subdomainek**
| Terület | Típus (core, supporting, generic) | Megoldás (saját kód, kész szolgáltatás) |
**Stílus és quantumok.** Például moduláris monolit, 1 quantum, Next.js plus Supabase.
Miért nem más: ...
**Modulok és adattulajdonlás**
| Modul | Felelősség egy mondatban | Saját táblák vagy séma |
**Bizalmi határok és integrációs pontok** (mindegyikhez timeout, ACL adapter)
| Külső rendszer | Irány | Adapter fájl | Timeout és retry |
**Fitness functionök a CI-ben**
- modulhatár (dependency-cruiser), RLS minden táblán, ...
**Nyitott kérdések (hot spotok).** Ezekre nem generálunk kódot, amíg el nem dőlnek.
**ADR-ek.** docs/adr/0001-..., 0002-...
16.2 A generált kód tipikus architekturális hibái és felismerésük
| Hiba | Felismerés | Javítás |
|---|---|---|
| Entity trap, táblák köré szervezett CRUD service-ek | UserService, OrderService nevek, a viselkedés a route handlerekben | domain particionálás, use case függvények |
| Szivárgó külső modell | Stripe, Supabase vagy LLM SDK típusok a domain kódban | ACL adapter, saját típusok (dependency-cruiser szabállyal) |
| Szétszórt jogosultság | if (user.role === ...) sok fájlban, vagy csak a frontenden | egy helyen (RLS, middleware, policy modul), szerver oldalon |
| Hiányzó timeout és retry | fetch vagy SDK hívás signal és időkorlát nélkül | a 8.2 pont mintái egy közös wrapperben |
| Unbounded result set | lekérdezés limit nélkül, LLM hívás max_tokens nélkül | lapozás, korlátok |
| Duplikált segédfüggvények | hasonló nevű függvények (formatDate, fmtDate, dateToString) | keresés írás előtt, egy helyre vonás |
| Sekély wrapperek és spekulatív általánosítás | interfész egyetlen implementációval, factory egy termékkel, nem használt konfigurációs opciók | inline, YAGNI, Ousterhout mély modulja |
| Rejtett ciklikus függőség | két modul kölcsönösen importál | dependency-cruiser no-circular |
| Disztribuált monolit | több edge function vagy szolgáltatás egy adatbázison, szinkron láncban hívják egymást | egy deploy egység, vagy valódi szétválasztás adattal együtt |
| Kettős írás | adatbázis írás, utána külön esemény vagy email küldés tranzakción kívül | outbox tábla, vagy idempotens újrapróbálás |
| Keveredő szerkezeti és viselkedési változás | egy diffben átnevezés, mozgatás és új funkció | Tidy First, külön commitok |
| Teszt, ami a megvalósítást tükrözi | a teszt elvárása ugyanazzal a képlettel számol, mint a kód | konkrét példaértékek, specifikációból írt teszt |
| Konfiguráció és titok a kódban | API kulcs vagy URL literálként | környezeti változó, titokkezelő |
| Architektúra sodródás munkamenetek között | minden új munkamenet más mintát követ (egyszer server action, egyszer API route) | ARCHITECTURE.md, fitness function és ADR, amelyeket az AI asszisztens minden munkamenet elején beolvas |
16.3 Mikor kell ADR
ADR vázlat készül, ha az alábbiak valamelyike igaz.
- Új adatbázis, új tárolási technológia vagy új külső szolgáltató kerül be.
- Hitelesítés, jogosultság, bérlőelválasztás vagy adatmegőrzés módja dől el.
- Változik a deploy egységek száma (új edge function csoport, új szolgáltatás, új worker).
- Egy fitness function alól kivételt kell tenni.
- Egy korábbi ADR-t felülírunk.
- Két vagy több értelmes alternatíva közül választottunk, és a választás nem nyilvánvaló a kódból.
- A döntést nehéz vagy drága visszafordítani (séma, nyilvános API, eseményformátum).
Keretrendszeren belüli szokásos döntésre, könnyen visszafordítható implementációs részletre és ízlésbeli kérdésre nem kell ADR. Ha az AI asszisztens dolgozik a kódon, ezekben a helyzetekben ő is jelzi az ADR igényét, és megírja a vázlatot, amelyet a fejlesztő hagy jóvá.
16.4 Munkaszabályok
- Munka előtt olvasunk. A fejlesztő és az AI asszisztens is elolvassa az
ARCHITECTURE.md-t, a projektszintű instrukciós fájlt és a releváns ADR-eket, és a meglévő mintát követi. Az eltérést előbb jelezni és indokolni kell. - A legegyszerűbb stílus az alapértelmezés. Moduláris monolit egy adatbázissal. Elosztott elem (üzenetsor, külön szolgáltatás, külön adatbázis) csak megnevezett jellemző és ADR alapján kerül be.
- Minden javaslat költséggel. Az első törvény szerint minden javaslathoz tartozik egy mondat arról, mit ad fel.
- Domain particionálás és közös nyelv. A mappák és a nevek a fogalomtárat követik, nem a technikai szerepet.
- Külső világ adapter mögött. Minden külső API, SDK és LLM hívás egy fájlban él, timeouttal, retryjal, saját típusokkal.
- Kis lépések, külön szerkezet és viselkedés. Tidying külön commitban, refaktor egy szag szerint, funkció tesztekkel.
- Ismeretlen kódnál a characterization teszt jön előbb.
- A szabályokból fitness function lesz. Amit kétszer kell kézzel ellenőrizni, az CI szabállyá válik (modulhatár, ciklusmentesség, RLS, bundle méret).
- Stabilitási minimum minden integrációs pontra. Timeout, korlátozott retry jitterrel, eredményhalmaz korlát, költségkorlát LLM hívásnál, idempotens újrapróbálás.
- Kognitív keret. A rendszer maradjon akkora, amekkorát egy ember átlát. Ha egy változtatás után több a deploy egység, a technológia vagy a modul, mint előtte, ezt kimondjuk, és megvizsgáljuk, megéri-e.
- Mérés. Éles rendszernél legalább egy SLO tartozik a legfontosabb felhasználói útra, a hibák után pedig rövid, hibáztatás nélküli visszatekintés készül, amiből fitness function vagy teszt születik.
- Mielőtt késznek mondjuk. A saját diffet végigvetjük a 16.2 pont táblázatán, és amit nem ellenőriztünk, azt kimondjuk.
16.5 Gyors döntési táblázat
| Helyzet | Javasolt kiindulás |
|---|---|
| Belső eszköz, egy felhasználói kör, kevés szabály | moduláris monolit, transaction script, vertical slice, trófea tesztelés |
| Ügyféladatot kezelő SaaS, több bérlő | moduláris monolit, RLS, auditálhatóság a top 3-ban, ADR a bérlőelválasztásról |
| Bonyolult árazás, szabálymotor, core domain | domain model aggregátumokkal, ports and adapters a core modulban, TDD |
| LLM feldolgozó lánc (dokumentum betöltés, darabolás, embedding) | pipeline stílus, idempotens lépések, timeout és költségkorlát minden LLM hívásnál |
| Bővíthető termék ügyfélenkénti testreszabással | microkernel, plugin szerződés, regiszter |
| Legacy rendszer cseréje | strangler fig, characterization tesztek, ACL a régi modell felé |
| Hirtelen, extrém terhelési csúcs (jegyértékesítés) | előbb mérés és cache, sor alapú backpressure, space based csak végső esetben |
| Több csapat, eltérő skálázási igény, érett domain | service based, majd indokolt esetben microservices, quantumonként saját adattal |
Források
A kiadások a 2026 októberi állapotot tükrözik.
| Mű | Szerző | Kiadás |
|---|---|---|
| Fundamentals of Software Architecture | Mark Richards, Neal Ford | 2. kiadás, 2025 március |
| Software Architecture: The Hard Parts | Ford, Richards, Sadalage, Dehghani | 2021 |
| Building Evolutionary Architectures | Ford, Parsons, Kua, Sadalage | 2. kiadás, 2022 |
| Software Architecture in Practice | Bass, Clements, Kazman | 4. kiadás, 2021 |
| Domain Driven Design | Eric Evans | 2003 |
| Implementing Domain Driven Design, Domain Driven Design Distilled | Vaughn Vernon | 2013, 2016 |
| Learning Domain Driven Design | Vlad Khononov | 2021 |
| Introducing EventStorming | Alberto Brandolini | 2013 óta folyamatosan bővülő elektronikus könyv |
| Hexagonal Architecture (Ports and Adapters) | Alistair Cockburn | 2005 |
| Onion Architecture | Jeffrey Palermo | 2008 |
| Clean Architecture | Robert C. Martin | blog 2012, könyv 2017 |
| C4 model | Simon Brown | 2011 óta, c4model.com |
| arc42 | Gernot Starke, Peter Hruschka | 2005 óta, 8.x sablon |
| Documenting Architecture Decisions | Michael Nygard | blogposzt, 2011 |
| MADR | Markdown Architectural Decision Records | 4.0, 2024 |
| Release It! | Michael Nygard | 2. kiadás, 2018 |
| A Philosophy of Software Design | John Ousterhout | 2. kiadás, 2021 |
| Team Topologies | Matthew Skelton, Manuel Pais | 2019, a 2. kiadás 2025 (ellenőrizendő) |
| Site Reliability Engineering, The Site Reliability Workbook | 2016, 2018 | |
| Accelerate | Forsgren, Humble, Kim | 2018, plusz az éves DORA jelentések |
| The Twelve Factor App | Adam Wiggins (Heroku) | 2011, nyílt forrású 2024 óta |
| Beyond the Twelve Factor App | Kevin Hoffman | 2016 |
| Refactoring | Martin Fowler | 2. kiadás, 2018 |
| Working Effectively with Legacy Code | Michael Feathers | 2004 |
| Tidy First? | Kent Beck | 2023 |
| Test Driven Development: By Example | Kent Beck | 2002 |
| Building Microservices, Monolith to Microservices | Sam Newman | 2. kiadás 2021, illetve 2019 |
Állapot 2026 októberében. A szöveg szakmai összefoglaló, a hivatkozott művek aktuális kiadását érdemes a kiadónál ellenőrizni.