# Definitions own what, code owns how

> This section covers the split between definitions and code.

Page: Architecture · Model
Canonical: https://banes-lab.com/software-architecture#definitions-own-what

This section is stop 53 of 102 in the learning route. Previous: [01 - A system is a graph](https://banes-lab.com/software-architecture/model/a-system-is-a-graph.md). Next: [03 - The layer spine](https://banes-lab.com/software-architecture/model/the-layer-spine.md). It builds on [01 - A system is a graph](https://banes-lab.com/software-architecture/model/a-system-is-a-graph.md), [22 - One home](https://banes-lab.com/disciplined-methodology/build/one-home.md).

This section covers the split between definitions and code. A registry declares what variants exist and the code discovers them, a schema declares what a record carries and the code validates against it, and a manifest declares what a module is for and the code derives its surface. The split runs through every fact a tree carries, as shown in [B1·a derivation or restatement](https://banes-lab.com/software-architecture#definitions-own-what-panel-a) and typed in [B1·b the model typed](https://banes-lab.com/software-architecture#definitions-own-what-panel-b), and its practice is described in [one home](https://banes-lab.com/disciplined-methodology/build/one-home.md) on the methodology page.

### One declaration, derived everywhere

Code that restates a definition looks complete on the day it is written and becomes a second truth the day the definition moves. A registry lists twelve variants, a switch in the composer handles eleven, and the twelfth exists everywhere except where it is dispatched, because the switch was a second declaration that was never recognised as one. Restating a definition in code is cheaper than reading it at the moment of writing, and the cost only arrives when one of the two copies changes and the other keeps the old truth.

For this reason definitions own what, code owns how, and a fact with two declarations and no derivation between them is a fracture. The definition is read at the site rather than restated there, even where reading costs more on the day. In practice, every fact is assigned to the side that owns it. A fact about what exists goes into a definition the code reads, and the code derives the rest from it, such as the list of variants, the shape of a record and the surface of a module. Where a fact already has a definition, the copy in the code is deleted. Where the code holds a fact nothing declares, the declaration is written and the code derives the fact from it, because a fact that lives only in behaviour cannot be checked without running the behaviour.

To check this, take any fact the system carries and count the places it is stated. The target is one statement plus derivations. Two statements with no edge between them will disagree, and the only open question is when the disagreement is noticed. A definition declares what and never how. A schema that carries a validation routine, or a manifest that carries a build step, has crossed into code and gained a second implementation of something the code already does. The split holds only while each side stays on its own side.

### The patterns that keep the split

The split is [single source of truth](https://banes-lab.com/records/arch/single-source-of-truth.md) stated for a whole system rather than for a database. [Declarative configuration](https://banes-lab.com/records/arch/declarative-configuration.md) states what is wanted and leaves the how to whatever reads it. [Manifest-based design](https://banes-lab.com/records/arch/manifest-based-design.md) puts what a module is for into data beside the module, so its surface is derived rather than described. [Metadata-driven design](https://banes-lab.com/records/arch/metadata-driven-design.md) lets the description drive the behaviour.

[Code as data](https://banes-lab.com/records/arch/code-as-data.md) is where the split pays off, because a definition that is data can be inspected, transformed, validated and generated from, while a definition that is code can only be run. The [registry pattern](https://banes-lab.com/records/arch/registry-pattern.md) with [auto-discovery](https://banes-lab.com/records/arch/auto-discovery.md) applies the same idea to variants. The registry declares that variants exist, the tree holds one file per variant, and a [glob-resolvable tree](https://banes-lab.com/records/arch/glob-resolvable-tree.md) lets the code find them without a list that must be edited when one is added.

[Convention over configuration](https://banes-lab.com/records/arch/convention-over-configuration.md) is the complement. A convention is a definition too, written once as a rule the reader derives from rather than a value the reader looks up.

### The model as a type

The graph model is what makes the split checkable. A declaration is a node, a derivation is an edge, and a fact with two nodes and no edge between them is the [dual write](https://banes-lab.com/records/arch/dual-write.md) in the graph's own terms. Written as a type, the model is small.

A component carries an identity, a concern and a layer. A relation carries its two ends and a kind from a [closed vocabulary](https://banes-lab.com/records/arch/closed-vocabulary.md), so a new relation kind is a vocabulary edit rather than a new field. The schema carries the invariants and one evaluation over the graph, and [schema validation](https://banes-lab.com/records/arch/schema-validation.md) is that evaluation run over every record that claims the shape. Health is one derivation, in which the schema is evaluated against the system's description of itself, and an empty finding set means the system is healthy.

### Where the line sits

A definition may say a record has a name and a kind from a closed set. It may not say how the kind is checked, because checking is behaviour. A manifest may say a module publishes three entry points. It may not build them. Either crossing produces the same defect, a truth held in two places with no edge between them.

B1·a derivation or restatement

```mermaid
flowchart LR
definition["A definition · what exists"]
code["Code · how it behaves"]
derived["A derivation · read from the definition"]
restated["A restatement · written twice"]
definition --> derived --> code
definition -. never .-> restated
restated -. disagrees the moment either copy moves .-> code
```

B1·b the model typed

```typescript
export interface Component {
readonly id: ComponentId;
readonly concern: Concern;
readonly layer: Layer;
}

export interface Relation {
readonly from: ComponentId;
readonly to: ComponentId;
readonly kind: "imports" | "exports" | "registers" | "consumes" | "emits" | "subscribes" | "interfaces";
}

export interface Schema {
readonly invariants: readonly Invariant[];
readonly evaluate: (graph: SystemGraph) => readonly Finding[];
}

export interface Propagation {
readonly reaches: (change: ComponentId, graph: SystemGraph) => readonly ComponentId[];
}

export interface SystemGraph {
readonly components: readonly Component[];
readonly relations: readonly Relation[];
readonly schema: Schema;
readonly propagation: Propagation;
}

export const derivable = (graph: SystemGraph, described: SystemGraph): boolean =>
graph.schema.evaluate(described).length === 0;
```

## Links to

- [One home](https://banes-lab.com/disciplined-methodology/build/one-home.md)
- [Single Source of Truth](https://banes-lab.com/records/arch/single-source-of-truth.md)
- [Declarative Configuration](https://banes-lab.com/records/arch/declarative-configuration.md)
- [Manifest-Based Design](https://banes-lab.com/records/arch/manifest-based-design.md)
- [Metadata-Driven Design](https://banes-lab.com/records/arch/metadata-driven-design.md)
- [Code as Data](https://banes-lab.com/records/arch/code-as-data.md)
- [Registry Pattern](https://banes-lab.com/records/arch/registry-pattern.md)
- [Auto-Discovery](https://banes-lab.com/records/arch/auto-discovery.md)
- [Glob-Resolvable Tree](https://banes-lab.com/records/arch/glob-resolvable-tree.md)
- [Convention over Configuration](https://banes-lab.com/records/arch/convention-over-configuration.md)
- [Dual Write](https://banes-lab.com/records/arch/dual-write.md)
- [Closed Vocabulary](https://banes-lab.com/records/arch/closed-vocabulary.md)
- [Schema Validation](https://banes-lab.com/records/arch/schema-validation.md)

## Linked from

- [One home](https://banes-lab.com/disciplined-methodology/build/one-home.md)
- [The four parts, measured](https://banes-lab.com/anatomy/reading/the-four-parts-measured.md)

## Evidence in the code

- [types](https://banes-lab.com/anatomy/tree/folder-types.md)
- [renderBlock](https://banes-lab.com/source/tree/presentation/renderers/block.renderer.ts.md)
