Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

principle-model-the-domain

为领域建模

Encode the real domain in a data structure instead of scattering it across conditionals.

把真实领域编码进数据结构,别散落在条件判断里。

Why: Scattered booleans, repeated shape assumptions, and branching spread across files are accidental complexity. A structure that matches the domain makes invalid states unrepresentable and deletes branches. Choosing it at write time is cheap. Recovering it later reads as a refactor and gets deferred.

为什么: 散落的布尔、重复的形状假设、跨文件的分支是偶然复杂度。匹配领域的结构让非法状态不可表示,并删掉分支。写的时候选它便宜;事后找回像重构,容易被推迟。

Reach for structures like these:

优先考虑这类结构:

  • A state machine instead of scattered booleans, phases, or lifecycle checks.

  • A typed object/model instead of loose parameters or repeated shape assumptions.

  • A map, registry, lookup table, or discriminated union instead of branching spread across files.

  • A reducer or command/event model instead of ad hoc state mutations.

  • A module organized around one body of domain knowledge instead of a sequence such as load, validate, transform, and save. Execution order is not ownership.

  • A small module boundary that gathers repeated behavior, ownership, or invariants.

  • A queue, cache, index, graph/tree, or normalized collection where the data access pattern calls for it.

  • Any other structure that fits. When none fits, work out what the code must never allow and how the data gets read, then find the structure that encodes exactly that.

  • 状态机,代替散落布尔、阶段或生命周期检查。

  • 类型化对象/模型,代替松散参数或重复形状假设。

  • map、registry、查找表或 discriminated union,代替跨文件分支。

  • reducer 或 command/event 模型,代替临时状态变异。

  • 围绕一块领域知识组织的模块,而不是 load→validate→transform→save 那种序列。执行顺序不是归属。

  • 收拢重复行为、归属或不变量的小模块边界。

  • 数据访问模式需要时的队列、缓存、索引、图/树或规范化集合。

  • 其他合适的结构。都不合适时,先弄清代码绝不允许什么、数据怎么读,再找恰好编码这些的结构。

Do not force an abstraction. Prefer boring code if the current shape is already clear, local, and unlikely to grow. Be skeptical of an abstraction that adds indirection without removing branches, duplicated rules, invalid states, or lifecycle risk.

别硬塞抽象。当前形状已清楚、局部、不大可能长大时,宁可用无聊代码。对只加间接、却不删分支/重复规则/非法状态/生命周期风险的抽象保持怀疑。

The sign that you skipped this is a new feature that grows an existing if/else chain by one more branch, or a second boolean that must stay in sync with the first. Temporal decomposition is another sign. Phase-named modules repeat the same domain rules across steps.

跳过本原则的迹象:新功能给已有 if/else 再加一支,或第二个布尔必须与第一个保持同步。按时间切分是另一迹象。按阶段命名的模块会在各步重复同一套领域规则。