keeping-one-source-of-truth
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseKeeping one source of truth
保持单一数据源
REQUIRED BACKGROUND: the skill.
principal-engineering必备背景知识: skill。
principal-engineeringOverview
概述
Every fact about the system is described in exactly one place, and everything else reads it. This outranks convenience: a second copy is a future contradiction, and the copy that drifts is always the one nobody remembers exists. When two places can hold the same truth they will eventually disagree, and the system then looks healthy while serving wrong data.
系统的每一项事实都仅在一处进行定义,其他所有内容都从该处读取。这比便利性更重要:第二份副本终将导致矛盾,而出现偏差的副本往往是没人记得存在的那一个。当两处可以存储同一事实时,它们最终会出现不一致,此时系统看似正常运行,实则提供错误数据。
The doctrine
原则细则
- Before adding data, find who already owns it. Extend that owner; do not start a rival. The five minutes of finding the owner is cheaper than the eventual incident of two owners.
- Derive rather than store. If the platform or an existing source can answer it at read time, read it there; do not copy the answer into a second home where it can go stale.
- Absorb duplicates you find on the way. Touching code that hardcodes what a file already knows (or the reverse) means folding the two together as part of the work, not leaving a third variant behind.
- A missing entry fails loud (see ): the single source is only authoritative if absence from it is an error, never a silent default.
handling-failures - Mark generated versus hand-edited, and never edit generated output. Every artifact states which it is; edits to derived files are lost work plus a divergence.
- Vocabulary is typed, not stringly. Identifiers, kinds, states, and names that code branches on are constants, enums, sealed types, or registry entries; a free string spelled twice is two sources of truth with a typo between them.
- When two sources disagree, say so. One of them is stale; surfacing the contradiction is the fix. Silently following either one launders the disagreement into whichever answer you happened to read first.
- 添加数据前,先找到已有数据的所有者。 扩展该所有者的范围,不要创建新的独立数据源。花五分钟寻找所有者,比后续因两个数据源引发故障的成本更低。
- 推导而非存储。 如果平台或现有数据源可以在读取时生成所需内容,就直接从该处读取;不要将结果复制到第二个存储位置,以免数据过期失效。
- 合并途中发现的重复项。 当遇到代码硬编码了文件中已有的内容(反之亦然)时,需将两者合并,而不是留下第三种变体。
- 缺失条目需触发明显错误(参见 ):只有当单一数据源中缺少条目被视为错误而非静默默认值时,它才具备权威性。
handling-failures - 标记生成内容与手动编辑内容,且绝不编辑生成的输出。 每个产物都需标明自身类型;编辑派生文件不仅是无效工作,还会导致数据分歧。
- 词汇需类型化,而非字符串化。 代码分支依赖的标识符、类型、状态和名称应是常量、enums、sealed types或注册表条目;同一拼写的自由字符串出现两次,就意味着存在两个可能因拼写错误而不一致的数据源。
- 当两个数据源不一致时,需明确指出。 其中一个数据源已过期;暴露矛盾本身就是修复的一部分。若静默遵循任意一方,会将分歧隐藏在你碰巧先读取到的答案中。
Boundaries
边界说明
- Caches and read models are legitimate derived copies when their derivation is automatic and their staleness is bounded and observable. The rule bans hand-maintained copies, not architecture.
- Test fixtures may freeze a copy of reality on purpose; a fixture is a snapshot, labeled by being a fixture.
- Documentation follows the same rule (an index routes, never decides); the technical-writer plugin carries that side where installed.
- 当缓存和读取模型的推导过程是自动的,且其过期状态是可控可观测的时,它们属于合法的派生副本。本原则禁止的是手动维护的副本,而非此类架构设计。
- 测试 fixture 可故意冻结一份真实数据的快照;fixture 本身就是快照的标识。
- 文档同样遵循此原则(索引仅做路由,不做决策);若安装了 technical-writer 插件,该原则也适用于文档领域。
Common mistakes
常见错误
- Copying a threshold, URL, or mapping "temporarily". Temporary copies have the same lifetime as the TODO above them.
- Creating beside
thing-v2instead of editing in place. The second file is a fork of the truth, and both will receive different fixes.thing - A default value in code that shadows the config file's value. When someone changes the config and nothing happens, this is why.
- Two enums in two services spelling the same states. The day one gains a state, the boundary between them becomes a silent filter.
- 「临时」复制阈值、URL或映射关系。临时副本的生命周期和其上方的TODO注释一样长(即永远不会被清理)。
- 在 旁创建
thing而非原地编辑。第二个文件是对真实数据源的分叉,两者后续会收到不同的修复更新。thing-v2 - 代码中的默认值覆盖了配置文件中的值。当有人修改配置却没有效果时,往往就是这个原因。
- 两个服务中存在拼写相同状态的两个enums。当其中一个服务新增状态时,两者之间的边界会成为一个静默过滤器。