Architectural styles and architectural patterns
◈ 10 cardsThe four-part anatomy of a style, the five-family taxonomy, and the scope axis that separates a style from an architectural pattern from a design pattern.
A style is a four-part anatomy
An architectural style is a named family that describes a whole category of system. Naming the family is not enough for marks; a style is defined by four things, and an answer that lists styles without the anatomy is answering a different question.
- A set of components that perform a function the system needs (a database, a computational module, a rendering engine).
- A set of connectors through which those components talk to one another, hand work across and stay in step (a procedure call, a pipe, an event bus, a shared store).
- Constraints defining how components may legally be integrated to form the system.
- Semantic models that let a designer understand properties of the whole by analysing the known properties of its parts.
A style is a transformation imposed on the design of an entire system. That is why re-styling an existing architecture is not a tidy-up: it causes fundamental structural change, including reassigning functionality between components.
The taxonomy
- Data-centred. A data store sits at the centre and clients read and write it. Clients are independent of one another, which makes the style highly integrable — you can add a client without touching the others. If the store notifies interested clients when data changes, it is a blackboard rather than a passive repository.
- Data-flow. Input is transformed through a series of computational components into output. The pipe-and-filter arrangement is the archetype: each filter expects data in a known form, produces data in a known form, and knows nothing about its neighbours' internals.
- Call-and-return. A control hierarchy: a main program invokes subprograms, which invoke others. Distribute those components across machines and you have the remote-procedure-call substyle. Easy to modify and scale, which is why it survives.
- Object-oriented. Components encapsulate data with the operations that manipulate it; coordination happens by message passing.
- Layered. Layers are defined so that each is progressively closer to the machine; outer layers serve the user interface, inner layers the operating system, with utility and application services between.
Real systems mix. A layered style over a data-centred core is the most common combination in existence, and saying so is a stronger answer than picking one label.
Style, architectural pattern, design pattern — the axis is scope
An architectural pattern also imposes a transformation, but it differs from a style in scope and in kind. Its scope is narrower: it addresses one aspect of the architecture rather than the architecture entire. It imposes a rule about how the software handles some aspect of its functionality at the infrastructure level — concurrency, persistence, distribution, synchronisation. And a design pattern is narrower again: it addresses one recurring collaboration among a handful of components or classes.
The three compose. You can hold a layered style, an offline-tolerant persistence pattern and the Observer design pattern in the same system at the same time without contradiction, and a good answer says so.
What moderates the choice
Five considerations pull against one another as you decide. Economy — the best architecture is uncluttered and leans on abstraction rather than extra features. Visibility — a later reader must be able to see the decisions and the reasons. Spacing — separation of concerns, but too much of it fragments the system and destroys visibility. Symmetry — a consistent, balanced structure is easier to understand; if you model an object's life cycle with an open(), model it with a close() too. Emergence — event-driven behaviour cannot be planned exhaustively, so leave room for it.
Worked example — BorrowBox is three styles at once
BorrowBox's catalogue of tools, copies, loans and members is a data-centred core: the app, the librarian console and the overnight overdue job all read and write it independently, which is precisely why a new client (a public availability map) can be added without touching the existing three. The lending application above it is layered: the app calls services, services call persistence, and nothing calls upward. The locker estate is reached through an event channel — the gateway publishes DoorOpened and ToolReturned, and whoever cares subscribes — which is a data-flow flavour, chosen because a street cabinet cannot be relied on to answer a synchronous call.
Name the connectors and the constraint in each and the answer earns its marks. Layered: connector = a local service call; constraint = calls go downward only. Data-centred: connector = a transactional read or write against the store; constraint = clients never message each other, only the store. Event channel: connector = a published message; constraint = publishers may not assume a subscriber exists, so nothing may be required to happen synchronously when a door opens.