# The principle architecture

> Three maps place the terms below.

Page: Architecture · Glossary
Canonical: https://banes-lab.com/software-architecture/glossary#the-principle-architecture

This section is stop 72 of 102 in the learning route. Previous: [04 - The honest gaps](https://banes-lab.com/software-architecture/coverage/the-honest-gaps.md). Next: [02 - Architectural rules and principles](https://banes-lab.com/software-architecture/glossary/architectural-principles.md).

Three maps place the terms below. The first is the layer diagram the whole page rests on, the second sets the stateless half of the core against the stateful half, and the third sets what holds inside one boundary against what holds across boundaries. A term sits where its rule holds whole, and two terms that seem to contradict are two terms on two sides of a line the map draws.

### The layers

Four core layers carry the rules about code itself. Computation is where data flows through and nothing is retained. Resource is where state lives and every handle has one owner. Execution is where the two meet through control flow and events. Structural applies to all of it and observes itself.

Resource observes computation, both feed execution, execution feeds structural, and structural feeds back into execution, which is [the loop](https://banes-lab.com/disciplined-methodology/start/the-loop.md) that lets a system read its own behaviour and correct it. Beneath the four sit [human factors](https://banes-lab.com/records/layer/human-factors.md), which bound the whole by what a developer can hold, and evolution, which says how the whole changes over time.

### Stateless against stateful

Five pairs of terms look like contradictions until the layer is read. They are [statelessness](https://banes-lab.com/records/arch/statelessness.md) against state before mutation, [immutability](https://banes-lab.com/records/arch/immutability.md) against state over code, explicit invalidity against [fail fast](https://banes-lab.com/records/arch/fail-fast.md), deliberate under-specification against not building what is not needed, and [homoiconicity](https://banes-lab.com/records/arch/homoiconicity.md) against single ownership.

Each pair is two principles on two layers, so each is resolved by scope, and the edge between them names the boundary. A computation flows through while a resource is snapshotted. Computed data is frozen while resource state is managed. An uncertainty is marked in a computation while a broken invariant halts a resource.

### Inside a boundary, across boundaries

The distributed pairs live where one boundary ends. [Consistency](https://banes-lab.com/records/arch/consistency.md) against availability, and [asynchronous communication](https://banes-lab.com/records/arch/asynchronous-communication.md) against immediate consistency, are trade-offs, strong or immediate inside one [transaction boundary](https://banes-lab.com/records/arch/transaction-boundary.md) or trust boundary and eventual across [autonomy](https://banes-lab.com/records/arch/autonomy.md) boundaries, with the operating point a measured choice. A [canonical model](https://banes-lab.com/records/arch/canonical-model.md) against the autonomy of a [bounded context](https://banes-lab.com/records/arch/bounded-context.md) is a trade-off too, one model where contexts share meaning and an [anti-corruption layer](https://banes-lab.com/records/arch/anti-corruption-layer.md) where they do not.

[Normalization](https://banes-lab.com/records/arch/normalization.md) against query performance separates by scope, the canonical store one way and the derived read models the other. [Do not repeat yourself](https://banes-lab.com/records/arch/duplicate-code.md) against locality of behaviour is the one pair a rule resolves, by asking whether a sameness is semantic or merely textual.

A1·a The principle architecture: the four core layers, the observe and feedback arrows across them, and the two domains beneath.

```mermaid
flowchart TB
subgraph core["The four core layers"]
direction TB
computation["COMPUTATION · stateless · data flows through, outputs are frozen"]
resource["RESOURCE · stateful · owned, tracked, explicitly released"]
execution["EXECUTION · how computation and resources interact"]
structural["STRUCTURAL · applies to all code · observes itself"]
end
human["HUMAN FACTORS · cognitive and discipline constraints"]
evolution["EVOLUTION · change over time"]
resource -- observe --> computation
computation --> execution
resource --> execution
execution -- feeds --> structural
structural -- feedback --> execution
structural --> human
structural --> evolution
```

A1·b Stateless against stateful: each pair is resolved by scope, and the edge names the boundary that separates them.

```mermaid
flowchart LR
subgraph stateless["COMPUTATION · stateless"]
direction TB
s1["Statelessness"]
s2["Immutability"]
s3["Explicit Invalidity"]
s4["Deliberate Under-Specification"]
s5["Homoiconicity"]
end
subgraph stateful["RESOURCE · stateful"]
direction TB
r1["State-Before-Mutation"]
r2["State Over Code"]
r3["Fail Fast"]
r4["YAGNI"]
r5["Single Owner"]
end
s1 -- data flows through · a resource is snapshotted before it changes --- r1
s2 -- computed data is frozen · resource state is mutable but managed --- r2
s3 -- a computation uncertainty is marked · a resource invariant halts --- r3
s4 -- interfaces stay open · implementation is not built ahead --- r4
s5 -- definitions are shared freely · runtime resources have one owner --- r5
```

A1·c Inside a boundary against across boundaries: the distributed pairs, each labelled with the mechanism that resolves it.

```mermaid
flowchart LR
subgraph inside["INSIDE ONE BOUNDARY"]
direction TB
i1["Consistency"]
i2["Asynchronous Communication"]
i3["Canonical Model"]
i4["Normalisation"]
i5["Do Not Repeat Yourself"]
end
subgraph across["ACROSS BOUNDARIES"]
direction TB
a1["Availability"]
a2["Immediate consistency"]
a3["Bounded context autonomy"]
a4["Query performance"]
a5["Locality of behaviour"]
end
i1 -- traded · strong inside a transaction, eventual across autonomy boundaries --- a1
i2 -- traded · synchronous inside a trust boundary, asynchronous across autonomy boundaries --- a2
i3 -- traded · one model where contexts share meaning, a translation where they do not --- a3
i4 -- by scope · the canonical store is normalised, derived read models are denormalised --- a4
i5 -- by rule · semantics are centralised, incidental co-occurrence stays local --- a5
```

## Links to

- [The loop](https://banes-lab.com/disciplined-methodology/start/the-loop.md)
- [Human Factors](https://banes-lab.com/records/layer/human-factors.md)
- [Statelessness](https://banes-lab.com/records/arch/statelessness.md)
- [Immutability](https://banes-lab.com/records/arch/immutability.md)
- [Fail Fast](https://banes-lab.com/records/arch/fail-fast.md)
- [Homoiconicity](https://banes-lab.com/records/arch/homoiconicity.md)
- [Consistency](https://banes-lab.com/records/arch/consistency.md)
- [Asynchronous Communication](https://banes-lab.com/records/arch/asynchronous-communication.md)
- [Transaction Boundary](https://banes-lab.com/records/arch/transaction-boundary.md)
- [Autonomy](https://banes-lab.com/records/arch/autonomy.md)
- [Canonical Model](https://banes-lab.com/records/arch/canonical-model.md)
- [Bounded Context](https://banes-lab.com/records/arch/bounded-context.md)
- [Anti-Corruption Layer](https://banes-lab.com/records/arch/anti-corruption-layer.md)
- [Normalization](https://banes-lab.com/records/arch/normalization.md)
- [Do Not Repeat Yourself (DRY)](https://banes-lab.com/records/arch/duplicate-code.md)
