uncomplect

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Uncomplect

Uncomplect

Treat the current system as a functional prototype. Preserve proven behavior and evidence. Do not preserve accidental structure.
将当前系统视为功能性原型。保留已验证的行为和依据,不要保留偶然形成的结构。

Read first

先做调研

Read the nearest project instructions, decisions, source, tests, runtime receipts, and current incidents before proposing a replacement.
For state-machine code, inspect the machine, persisted state, restoration path, invoked actors, guards, and transition tests.
For effect-system code, inspect the project's pinned version and existing service, error, retry, and transaction boundaries. Do not prescribe APIs from memory.
Completion: every recommendation names its source fact, preserved behavior, and deleted complexity.
在提出替代方案前,先阅读最相关的项目说明、决策文档、源代码、测试用例、运行时记录以及当前事件。
对于状态机代码,检查状态机本身、持久化状态、恢复路径、调用的参与者、守卫条件以及过渡测试。
对于效果系统(effect system)代码,检查项目固定的版本以及现有的服务、错误、重试和事务边界。不要凭记忆指定API。
完成标准:每一项建议都要说明其依据的事实、保留的行为以及删除的复杂性。

Hickey: separate what was braided

Hickey:拆分交织的部分

Build a complection table.
ConcernWhat is braided together?Independent valuesSeparation move
Look for:
  • value mixed with time;
  • identity mixed with changing state;
  • behavior mixed with storage or transport;
  • policy mixed with mechanism;
  • current truth mixed with historical facts;
  • lifecycle state mixed with domain data;
  • retry policy mixed with business failure;
  • one generic status hiding distinct facts.
Prefer immutable values and pure functions. Keep historical facts true without granting them permanent authority.
创建一张复杂性交织表。
关注点哪些部分交织在一起?独立的价值项拆分措施
寻找以下交织情况:
  • 价值与时间混合;
  • 标识与变化的状态混合;
  • 行为与存储或传输混合;
  • 策略与机制混合;
  • 当前事实与历史记录混合;
  • 生命周期状态与领域数据混合;
  • 重试策略与业务失败混合;
  • 单一通用状态掩盖了不同的事实。
优先使用不可变值和纯函数。保持历史记录的真实性,但不要赋予其永久的权威性。

Ousterhout: make the interface deep

Ousterhout:打造深度接口

Judge complexity by change amplification, cognitive load, and unknown unknowns.
For every proposed type, state, service, interface, or configuration value, ask:
  1. What complexity does this element remove?
  2. Does it hide a hard problem behind a small interface?
  3. Can the API define an accidental error or special case out of existence?
  4. Does it pull complexity into one deep module, or spread policy across callers?
  5. What can we delete after adding it?
Reject infrastructure that adds names without removing more dependencies or obscurity.
For consequential replacements, design it twice. Sketch two materially different interfaces. Compare caller burden, hidden knowledge, dependencies, failure semantics, and deletion count before choosing.
通过变更放大率、认知负荷和未知的未知项来判断复杂性。
对于每一个提议的类型、状态、服务、接口或配置值,询问:
  1. 该元素消除了哪些复杂性?
  2. 它是否将一个难题隐藏在简洁的接口背后?
  3. 该API能否消除偶然错误或特殊情况?
  4. 它是将复杂性集中到一个深度模块中,还是将策略分散到各个调用方?
  5. 添加它之后,我们可以删除哪些内容?
拒绝那些只增加名称但未减少更多依赖或模糊性的基础设施。
对于重要的替代方案,要设计两次。绘制两个本质不同的接口。在选择之前,比较调用方负担、隐藏的知识、依赖项、失败语义以及可删除的内容数量。

Young: optimize for deletion

Young:为删除优化

Greg Young's The Art of Destroying Software argues for small programs that can be replaced when their model stops fitting reality.
Ask:
  1. Could this module be rewritten from its contracts, tests, and receipts within about one week?
  2. If not, which dependency, hidden invariant, or shared state makes it dangerous to replace?
  3. Can a new implementation shadow the old one behind the same seam?
  4. Does the proposed boundary preserve proven behavior without preserving the current model?
  5. What old implementation becomes deletable after cutover?
The one-week horizon is a pressure test, not doctrine. Do not turn it into arbitrary service splitting. Small replaceable programs can live in one process and one repository.
Greg Young的《The Art of Destroying Software》(软件销毁的艺术)主张编写小型程序,当其模型不再符合现实时可以被替换。
询问:
  1. 是否可以在大约一周内根据其契约、测试和记录重写这个模块?
  2. 如果不能,是哪些依赖项、隐藏的不变量或共享状态使得替换它变得危险?
  3. 新实现能否在同一个接口后替代旧实现?
  4. 提议的边界是否保留了已验证的行为,而不保留当前的模型?
  5. 切换完成后,哪些旧实现可以被删除?
一周的时间范围是压力测试标准,而非教条。不要将其转化为任意的服务拆分。小型可替换程序可以存在于同一个进程和同一个代码仓库中。

DDD: put authority in the right boundary

DDD:将权威性置于正确的边界内

Name the bounded contexts and their trust boundaries. Use domain language, not storage language.
Identify:
  • the aggregate that owns each invariant;
  • immutable facts versus current decisions;
  • commands, events, policies, and projections;
  • upstream and downstream contract ownership;
  • translation at context boundaries;
  • terms that hide several domain meanings.
A projection may report domain truth. It must not become authority over the aggregate that produced it.
Model a workflow as a command plus current facts producing explicit events. The pure workflow returns events. Publishing and persistence are separate effects.
命名限界上下文及其信任边界。使用领域语言,而非存储语言。
识别:
  • 拥有每个不变量的聚合;
  • 不可变事实与当前决策;
  • 命令、事件、策略和投影;
  • 上游和下游契约的所有权;
  • 上下文边界处的转换;
  • 隐藏了多种领域含义的术语。
投影可以报告领域事实,但不得对生成它的聚合拥有权威性。
将工作流建模为命令加上当前事实,生成显式事件。纯工作流返回事件,发布和持久化是独立的效果。

Typed effects: keep the pure core pure

类型化效果:保持纯核心的纯粹性

Use the project's effect system for effects, not for making pure rules look sophisticated.
  • Keep domain decisions as pure functions and tagged values.
  • Decode untrusted input at boundaries.
  • Put database, network, filesystem, clock, configuration, and provider work behind named services.
  • Use typed expected errors. Keep defects distinct.
  • Retry only typed transient failures with proven idempotency.
  • Keep provider calls outside authoritative database transactions.
  • Do not introduce an incompatible effect-system version inside one workflow.
If the project does not already use a compatible effect system at this boundary, plain language-native code is better than a framework migration disguised as a simplification.
将项目的效果系统用于处理效果,而非让纯规则看起来复杂。
  • 将领域决策作为纯函数和标记值;
  • 在边界处解码不可信输入;
  • 将数据库、网络、文件系统、时钟、配置和提供商操作置于命名服务之后;
  • 使用类型化的预期错误,区分缺陷;
  • 仅对类型化的临时失败进行重试,且需具备已验证的幂等性;
  • 将提供商调用置于权威数据库事务之外;
  • 不要在同一个工作流中引入不兼容的效果系统版本。
如果项目在此边界处尚未使用兼容的效果系统,那么原生语言编写的普通代码比伪装成简化的框架迁移更好。

Lifecycle: make essential time visible

生命周期:让必要的时间可见

Use an explicit state machine when modes have different allowed events, cancellation, retries, resumability, or child work. Do not use one for pure migration, parsing, or validation.
  • States represent modes with different allowed events.
  • Context holds minimal actor data, not duplicate state labels.
  • Guards are pure and synchronous.
  • Effects live in invoked actors or boundary services.
  • Persisted state must be normalized before it receives current authority.
  • A transient computation does not need a new durable state.
  • Restoration tests must cross version and deployment boundaries.
Prefer a smaller machine fed by validated domain values over a machine that interprets raw database rows.
当不同模式具有不同的允许事件、取消、重试、可恢复性或子任务时,使用显式状态机。不要将其用于纯迁移、解析或验证。
  • 状态代表具有不同允许事件的模式;
  • 上下文包含最少的参与者数据,而非重复的状态标签;
  • 守卫条件是纯同步的;
  • 效果存在于调用的参与者或边界服务中;
  • 持久化状态在获得当前权威性之前必须被规范化;
  • 临时计算不需要新的持久化状态;
  • 恢复测试必须跨越版本和部署边界。
优先选择由已验证的领域值驱动的小型状态机,而非解释原始数据库行的状态机。

Replacement pass

替代方案流程

Produce this sequence:
  1. Essential behavior: what the prototype proves and must preserve.
  2. Complection map: what is braided today.
  3. Domain map: contexts, aggregate, invariants, commands, events, projections.
  4. Deep seam: the smallest public operation that can hide unavoidable complexity.
  5. Effect boundary: pure core, typed failures, effectful adapters, transaction edge, retry owner.
  6. Lifecycle: the smallest state machine that still makes time explicit.
  7. Rewrite horizon: what prevents this module from being replaced within about one week.
  8. Deletion list: states, flags, exceptions, operator steps, and modules the replacement removes.
  9. Adoption path: tracer, shadow comparison, cutover, and rollback without dual authority.
  10. Unknowns ledger: known facts, known unknowns, unknown knowns, suspected unknown unknowns.
Use this sequence as a reasoning checklist, not a demand for ten headings. Combine adjacent items when one table or type definition carries the evidence. Keep the review proportional to the decision risk.
按照以下步骤执行:
  1. 核心行为:原型已验证且必须保留的内容。
  2. 交织复杂度图:当前哪些部分交织在一起。
  3. 领域图:上下文、聚合、不变量、命令、事件、投影。
  4. 深度接口:可以隐藏不可避免的复杂性的最小公共操作。
  5. 效果边界:纯核心、类型化失败、效果适配器、事务边缘、重试所有者。
  6. 生命周期:仍能使时间显式化的最小状态机。
  7. 重写范围:哪些因素导致无法在大约一周内替换此模块。
  8. 删除列表:替代方案将移除的状态、标志、异常、操作步骤和模块。
  9. 采用路径:追踪器、影子对比、切换和回滚,且不保留双重权威。
  10. 未知事项记录:已知事实、已知的未知项、未知的已知项、疑似的未知未知项。
将此步骤作为推理检查清单,而非要求必须包含十个标题。当一个表格或类型定义可以承载相关依据时,合并相邻的项。使评审与决策风险成正比。

Output

输出

Lead with one verdict:
text
More complicated locally, simpler overall
or:
text
More machinery, no net simplification
Then include:
  • source-grounded complection table;
  • proposed domain language;
  • one deep interface;
  • pure decision types;
  • effect and lifecycle ownership split;
  • old versus proposed state count;
  • rewrite horizon;
  • deletion list;
  • risks and one material question.
Do not praise the design. Show what becomes impossible, what becomes obvious, and what disappears.
首先给出一个结论:
text
局部更复杂,整体更简洁
或者:
text
增加了机制,未实现整体简化
然后包含:
  • 基于事实的交织复杂度表;
  • 提议的领域语言;
  • 一个深度接口;
  • 纯决策类型;
  • 效果与生命周期的所有权拆分;
  • 旧状态与提议状态的数量对比;
  • 重写范围;
  • 删除列表;
  • 风险和一个关键问题。
不要夸赞设计。展示哪些内容变得不可能,哪些内容变得显而易见,以及哪些内容消失了。

Compact invocation

简洁调用

text
Treat the current system as a functional prototype, not an architecture to preserve. Preserve its proven behavior. Find what is complected. Separate values from time, policy from mechanism, and facts from projections. Define accidental errors out of existence. Draw the domain boundaries and aggregate invariants. Keep effects at effectful boundaries and state machines on essential lifecycle. Optimize the seam for deletion instead of predicting future change. Propose the smallest deep replacement, show what it deletes, and name the remaining unknowns.
For the source map and the distinct job each lens performs, read references/source-map.md.
text
将当前系统视为功能性原型,而非需要保留的架构。保留其已验证的行为。找出交织的部分。将价值与时间、策略与机制、事实与投影拆分。消除偶然错误。划定领域边界和聚合不变量。将效果置于效果边界处,将状态机用于核心生命周期。为删除优化接口,而非预测未来变化。提出最小的深度替代方案,展示它将删除的内容,并列出剩余的未知事项。
如需了解来源映射以及每个视角的具体作用,请阅读references/source-map.md