Loading...
Loading...
Compare original and translation side by side
Think of it as a "to-do list on steroids" — a living graph that is simultaneously your plan, your progress tracker, and your communication tool.
你可以把它理解为“升级版待办清单”——它是一个动态的依赖图,同时充当你的规划方案、进度追踪器和沟通工具。
| Term | Meaning |
|---|---|
| Goal | The root node. What you ultimately want to achieve (e.g., "Encapsulate DB", "Extract Interface"). Circle it twice so it doesn't get lost. |
| Prerequisite | A dependency that must be resolved before its parent node can be done. Becomes a child bubble in the graph. |
| Leaf node | A node with no further prerequisites. Safe to implement immediately without breaking anything. |
| Mikado Map / Graph | The full tree of goal + prerequisites. Your "save game" for the refactoring. |
| Revert | Undoing all changes to return to a stable, compiling/passing state. The map survives; the broken code does not. |
| 术语 | 含义 |
|---|---|
| Goal | 根节点,你最终想要达成的目标(例如“封装数据库”、“提取接口”),给它画两个圈避免遗漏。 |
| Prerequisite | 必须在父节点完成前解决的依赖项,会成为依赖图中的子节点。 |
| Leaf node | 没有更多前置依赖的节点,可以立即安全实现,不会破坏任何现有功能。 |
| Mikado Map / Graph | 包含目标和所有前置依赖的完整树结构,是你重构过程的“存档”。 |
| Revert | 撤销所有改动,回到代码可编译、测试全通过的稳定状态。依赖图会保留,破碎的开发代码不会保留。 |
1. SET GOAL → Write the goal as the root node. Circle it twice.
2. BE NAIVE → Attempt to implement the goal directly in the code.
3. OBSERVE BREAKS → Compiler errors, failing tests, or broken behavior = prerequisites.
4. MAP → Add each prerequisite as a child bubble connected to the current node.
5. REVERT → Undo ALL changes immediately. Return to green/stable state.
6. PICK A LEAF → Choose any leaf node (no children) and repeat the loop from step 2 on it.
7. COMMIT LEAF → Once a leaf is implemented cleanly without breakage, commit it.
8. PRUNE THE GRAPH → Remove the committed leaf. Reveal new leaves. Continue upward.1. SET GOAL → 写下目标作为根节点,给它画两个圈。
2. BE NAIVE → 尝试直接在代码中实现目标。
3. OBSERVE BREAKS → 编译器错误、测试失败、功能异常 = 前置依赖。
4. MAP → 将每个前置依赖作为子节点添加到当前节点下。
5. REVERT → 立即撤销所有改动,回到测试全过的稳定状态。
6. PICK A LEAF → 选择任意一个叶节点(没有子节点),从步骤2开始针对这个节点重复循环。
7. COMMIT LEAF → 当叶节点被干净实现、没有引入任何破坏时,提交代码。
8. PRUNE THE GRAPH → 移除已提交的叶节点,暴露新的叶节点,继续向上推进。FileDatabaseDatabaseInterfacegit stashgit checkout .git stash dropFileDatabaseDatabaseInterfacegit stashgit checkout .git stash dropExample graph execution order:
Goal: Replace FileDatabase with DatabaseInterface
├── Extract DatabaseInterface ← implement 3rd
│ ├── Move FileDatabase to impl/ ← implement 1st ✓
│ └── Update all import paths ← implement 2nd ✓
└── Add constructor injection ← implement 4th
└── Rename constructor param ← implement 1st ✓依赖图执行顺序示例:
目标:将FileDatabase替换为DatabaseInterface
├── 提取DatabaseInterface ← 第3个实现
│ ├── 将FileDatabase移动到impl/目录下 ← 第1个实现 ✓
│ └── 更新所有导入路径 ← 第2个实现 ✓
└── 添加构造函数注入 ← 第4个实现
└── 重命名构造函数参数 ← 第1个实现 ✓"Extract: DatabaseInterface from FileDatabase""Extract: DatabaseInterface from FileDatabase"graph TD
G(["🎯 GOAL: <goal name>"]) --> P1["Prerequisite A"]
G --> P2["Prerequisite B"]
P1 --> L1["🟢 Leaf: step 1"]
P1 --> L2["🟢 Leaf: step 2"]
P2 --> L3["🟢 Leaf: step 3"]graph TD
G(["🎯 GOAL: <goal name>"]) --> P1["Prerequisite A"]
G --> P2["Prerequisite B"]
P1 --> L1["🟢 Leaf: step 1"]
P1 --> L2["🟢 Leaf: step 2"]
P2 --> L3["🟢 Leaf: step 3"]git checkout .git checkout .| Mistake | Correction |
|---|---|
| Fixing errors in place instead of reverting | "Revert now. Add these errors as prerequisite nodes instead." |
| Building on top of broken code | "This violates the core rule. Revert to green before continuing." |
| One giant commit with multiple changes | "Split into one commit per leaf node." |
| Skipping the graph for "small" refactors | "Start with even a 3-node graph. It prevents scope creep." |
| Using mocks to avoid test data setup pain | "This creates Mock Hell. Use Test Data Builders as Mikado leaf nodes instead." |
| Long-lived refactoring branches | "Work on main. Only commit leaves that don't break anything." |
| 错误行为 | 纠正方式 |
|---|---|
| 原地修复错误而不是回滚 | “现在回滚,把这些错误作为前置依赖节点添加到依赖图中。” |
| 在破碎的代码之上继续开发 | “这违反了核心规则,继续前先回滚到稳定状态。” |
| 包含多个改动的巨型提交 | “拆分为每个叶节点对应一次提交。” |
| 认为“小型”重构不需要画依赖图 | “哪怕只有3个节点的依赖图也可以避免范围蔓延,先画出来。” |
| 用Mock规避测试数据准备的麻烦 | “这会导致Mock地狱,用Test Data Builder作为Mikado叶节点替代。” |
| 长期维护重构分支 | “在主干分支上开发,只提交不会破坏任何功能的叶节点代码。” |
MIKADO LOOP
───────────
① Write goal (root) → circle it twice
② Attempt naively in code
③ Every error = a prerequisite bubble
④ REVERT (always, immediately)
⑤ Pick a leaf → repeat from ②
⑥ Leaf passes cleanly → commit → prune
⑦ Repeat until goal is reached
RULES
─────
• Never build on broken code
• One atomic change per commit
• No behavior changes in refactoring commits
• Leaves only touch one concern
• The map is the work — protect itMIKADO LOOP
───────────
① Write goal (root) → circle it twice
② Attempt naively in code
③ Every error = a prerequisite bubble
④ REVERT (always, immediately)
⑤ Pick a leaf → repeat from ②
⑥ Leaf passes cleanly → commit → prune
⑦ Repeat until goal is reached
RULES
─────
• Never build on broken code
• One atomic change per commit
• No behavior changes in refactoring commits
• Leaves only touch one concern
• The map is the work — protect it