To split or not: forking and metrics
Yuri starts with the chapter's flowchart: first decide whether the monolith is reasonable, then whether the code is decomposable, and choose between tactical forking and component-based decomposition. The order bothers him: metrics are computed per component, yet the question "are there components" comes afterwards. Alexander reads the chart differently: first you look at how the code is laid out in namespaces and packages and how tangled it is; if the codebase can be tidied you extract components and move them out, if not you fork a copy and, like Pinocchio out of a log, carve away the excess. He never considered tactical forking an option before: one bad piece of code becomes two, the stale code goes nowhere, and shared functionality in two copies drifts apart — it is a decision of despair, for when two teams must be handed their halves. Yet for a quick product hypothesis a fork worked: Ilya recalls a copy of an application deployed separately, run for half a year, and buried.
Alexander tells a story from acquisition six years back: a public front-end application — a monolith with fifty-odd developers and a release every two or three weeks — onto which he had to move the main products fast. He stood up separate infrastructure and a separate release cycle for his slice of code inside the monolith, made two or three quick releases, then merged breaking changes from the shared master with a full regression, and so on until the needed components were transplanted into a new front end — after which the monolith died. The metrics for "is the code decomposable" — abstractness, instability, and distance from the main sequence — were invented by Robert Martin in 1994, before Java. Yuri doubts abstractness as a measure of extensibility: Python and Go have almost no abstract entities, functional languages even fewer; Vova counters with external systems, which in a bank change constantly — interfaces let you swap the implementation without rewriting the code.
Instability and the zones of pain
Alexander explains the dependency inversion principle on the 2019 mobile bank: logic lay in layers, concrete implementations without interfaces, and when the single team was split into some forty product teams, the restaurant-booking team turned out to depend on the payment signatures, payments were reworked for the business — and everything started breaking. Extracting interfaces helped, although nobody designed the convenience of the contracts between modules. Instability is the ratio of outgoing dependencies to all of them; Yuri gets tangled in afferent and efferent, and Alexander advises calling them fan-in and fan-out, as Uncle Bob does. If nobody depends on a component its instability is one and anything goes inside; if everyone depends on it, it is chained down: in the mobile bank those are cards, accounts, and payments, which the other forty teams want, and they can hardly breathe, while a new product with no consumers moves fast and thinks itself brilliant.
Hence the two zones on the abstractness–instability chart. The zone of pain is concreteness without abstractions that everyone depends on: guts exposed, nothing can be changed or people come saying "payments are down". The zone of uselessness is interfaces nobody uses. Alexander once hired a guru from the Java community to analyse the mobile bank's code with these metrics: some dependency directions turned out wrong, some modules sat in the zone of pain, and such insights are genuinely extractable from a codebase too big to scan by eye. Ilya sums up: the metrics describe how the code is cut now, and if the component graph is complete, like a microservice mesh where everyone calls everyone, nothing can be extracted — then the chart's right branch, the fork. Alexander compares: a properly split application is the blocks his son builds words from, a fork is two piles of kinetic sand in different corners of the room.
Six steps of decomposition
The second chapter calls the steps patterns, although, Ilya jokes, it is an algorithm; Alexander likes that each step is explained through "why" and comes with fitness functions so that two months later it does not slide back. Step one — identify and size components: count statements per component; the book's heroes find reporting at 30% of the code and split it into financial, other, and shared functions; the control functions — no new namespaces appear, no component exceeds a share of total statements or strays beyond two standard deviations. Alexander notes this is not pipeline automation but a way to keep the architect informed: it fires, and they come asking for justification. Step two — gather common domain components such as notification scattered across modules; the function looks for identical names and code. Step three — flatten components: classes live only in leaf namespaces and the parent is the subdomain; Yuri dislikes losing structure inside a component, Ilya suggests treating the first three name segments as the component.
Step four — determine component dependencies: the authors joke about difficulty grades from a golf ball to an airplane, and the functions forbid unwanted dependencies on a specific component. Alexander argues with the ideal of fully unconnected components: a system is elements plus links, and without interaction there is no emergent behaviour, just as people who do not talk are not a team. Shared code goes into libraries or a separate service, and here the club takes a detour: Alexander recalls that the anti-corruption layer from Vlad's book can be a library or a service in front of the consumer, Yuri that log collection in Kubernetes is done with a sidecar without touching applications, and Ilya warns about latency: he saw a project where an unconnected system was launched and a page took nine minutes to render. Step five — group components into domains, essentially renaming by convention; step six — extract into services, the shortest in the chapter, though all the infrastructure is in it. Alexander recalls Vlad's lesson — do not split while the business logic is unclear — and tells of the front-end configuration service where investment news and acquisition pages lived in one failure domain. There is no translation of the book — read the original, although everyone agrees it is watery.
What to take away
- 01First decide whether the monolith is reasonable and the code decomposable; tactical forking is a decision of despair or a way to test a hypothesis fast, not a route to clean architecture.
- 02Martin's metrics — abstractness, instability, distance from the main sequence — reveal the zone of pain, where everyone depends on concreteness, and the zone of uselessness, where interfaces serve nobody.
- 03Component-based decomposition takes six steps — size components, gather common ones, flatten, determine dependencies, group into domains, extract services — with fitness functions that keep the architect informed.
- 04Shared code can become a library, a service, or a sidecar, but a separate service raises latency sharply; split only where the business logic is clear and the coupling hurts.