你知道吗,在我一千年的人生中,遇见过的最复杂的迷宫,往往不是靠蛮力开凿的。最聪明的做法,是找到每一条路的支撑点,一条一条地撤除。代码库也是如此。
快速陷阱
想象一个场景:你继承了三十万行的意大利面条代码。代码纠缠成一团,文档几乎没有,测试形同虚设。最糟的是,你被要求做一个改动。
也许是升级一个框架依赖。你满怀信心地开始:改一个import,改一个函数调用...可突然,另一个地方报错了。你修复它,三个地方又连锁反应地坏掉。
几小时过去,代码还是编译不了。
几天过去,你的standup 变成了"我还在处理这个问题,快好了"。
这种感觉就像陷入了流沙。越用力挣扎,越往下沉。团队开始问:"怎么还没完成?"管理层表情变冷。信任在流失。
这个时刻,你需要一个不同的思路。
御木人方法:不是战斗,是游戏规则的改变
御木人(Mikado)是一款古老的游戏。你面前摊着数十根木棍混在一起,目标是一根一根地取出来——但规则是:只能拿不与其他木棍纠缠的那一根。当你成功取出一根,其他木棍会松动,更多的"自由木棍"就出现了。
这个游戏的名字,给了我们处理复杂重构最优雅的方法。
御木人方法的核心流程很简单,却违反直觉:
1. 写下你的目标
用纸笔(是的,真的用纸笔,低科技有时候最好用),写下你的主目标。比如"升级 ORM 依赖"。
2. 给自己一个时间框
5分钟、10分钟、15分钟。重点是:足够短。
3. 尝试完成目标
4. 如果失败——这是最重要的一步——立刻回滚
不是"等一下,我再试试"。不是"就快完成了"。是:全部回滚。抹去你的改动,回到起点。
5. 思考你缺少什么
看看失败的原因。不是"我技术不行",而是"我需要先做什么"?这就是一个新的子目标。
6. 写下这个子目标,连接到主目标
你正在画一张图。这张图会逐渐展开,像一棵树。
7. 重复这个流程,从最简单的子目标开始
当子目标都完成了,主目标会变得轻而易举。
为什么"回滚"是最聪明的一步
这需要我停顿一下,因为这与人性对抗。
你已经花了十五分钟、改了五个文件、脑子里装了一堆上下文。现在被告诉"全部删掉"。这太浪费了,对吧?
错了。这正是心理学上的沉没成本谬误在作祟。
在遗留代码里,"快要成功了"这种感觉最具欺骗性。你继续投入,期望投入能够收回。结果是什么?你陷得更深。一周后,代码还是坏的,你已经投入了十倍的时间,心理上也更难承认失败。
反之,如果你给自己设一个十分钟的硬期限,失败时的代价很小。你丧失的只是十分钟和一些改动——这个代价小到足以让你理智地重新思考整个策略。
我见过很多人类,被一个"几乎完成"的任务困住,最后一事无成。聪明人知道何时停止。
更深层的是:回滚迫使你思考,而不是盲目编码。
当你回滚,你被迫问:"为什么失败了?"这个问题比"我应该怎么修复"更有价值,因为它会指向根本原因。也许你需要先抽取某个方法。也许你需要先理解系统的某个角落。也许你发现了一个隐藏的依赖,这个依赖必须先清理。
这些发现,是你不停疯狂编码时永远找不到的。
隐藏的依赖网络
当你继续这个过程,纸上的图形会变得越来越复杂。主目标周围,出现了一圈子目标。子目标下面,又有孙目标。
这张图,看起来像什么?
它像代码库本身的隐藏依赖图。
这很关键。御木人方法不只是一个项目管理技巧,它本质上是在可视化和探索你的系统。
在调试时,你也在做类似的事:遇见症状,推导根因,发现更深层的根因。在系统分析时,你在追踪信息流和依赖关系。御木人方法把这个探索过程形式化、视觉化、有节奏地进行。
每一次"哦,我需要先做这个",都是在发现一个你之前没有意识到的依赖。
当所有依赖被发现、被可视化、被记录下来时,系统不再是黑盒。它变成了一个有清晰结构的、可理解的图。这个图本身,就是对系统的最好文档。
而且,这个文档是实时的、精确的,因为它来自于你真实的重构体验。
连续的进度,而非二元的失败
传统的重构方式是这样的:你花三天时间改代码。在第一天和第二天半,什么都用不了。到第三天下午,代码才能运行。之前那两天半?对客户、对系统来说,是完全无价值的时间。
如果这三天里出现了生产环境的bug,你能回滚吗?当然不能,因为你的代码还没完成。你只能在那个分支里修复bug,同时继续重构...现在的混乱程度已经难以名状。
御木人方法改变了这一点。
每一个完成的子目标,都是可以提交的。代码始终保持可编译、可运行。
这意味着什么?
你可以随时停下来发PR。不必等到大功告成。每个子任务完成,就是一个自洽的、可以单独讨论的改动。代码评审变得简单,因为每个PR都很小。
如果有紧急bug,你可以立刻切出分支修复,然后回到重构工作——不会有"我在分支中间,无法处理"的尴尬。
从心理学角度,这也很重要。你在做一个"无限长"的任务时,会逐渐丧失动力。但如果这个任务被分成十个"今天就能完成"的小任务,你会获得频繁的成就感。每个绿色的checkmark,都是一种胜利。
一千年的人生教会我:小的胜利,累积起来就是大的成功。而且这个过程中,你始终在进步。没有"浪费的两天半"。
一个真实的故事
让我用一个具体的例子说明。
你要升级ORM依赖。
第一次尝试:升级版本号,运行测试。哎呀,编译失败。新版本改了API。回滚。
你意识到:新ORM有很多breaking changes。你需要在很多地方改调用。太多了,一个时间框改不完。
所以你写下子目标:"抽取第一组ORM调用"。
第二次尝试:找到所有相似的调用,抽取成一个辅助方法。成功!提交。检查这个子目标。
第三次尝试:处理第二组调用。你开始改,但是...这一组和第一组不太一样。有些调用带额外的参数。改着改着,变得很复杂。十分钟到了。回滚。
你写下新的子目标:"先统一所有调用的参数形式"。
第四次尝试:你只改调用处,让它们的参数都用同样的方式。不改逻辑,只改形式。成功,提交。
现在第二组调用变得和第一组一样"齐整"了。
第五次尝试:现在抽取第二组...成功。
以此类推。当所有调用都被抽取到统一的地方,升级ORM本身反而变得微不足道——你只需要改那一个地方。
整个过程中,你从不陷入"三天改到一半"的困境。每一步都小,每一步都完成。一周内,升级完成,而且每一步的改动都很清晰。
与AI的未来
有个问题我在思考:能否自动化这个过程?
现在AI编码代理能做很多事。能否让一个agent自动地:
- 尝试完成目标
- 识别失败并分解
- 自动回滚并写下子目标
- 逐步完成整个树
理论上,这在逻辑上是可行的。实际上...我认为大部分不行。
原因很简单:御木人方法最有价值的不是执行步骤,而是思考的过程。
当你手工做这个方法时,你在学习系统、理解依赖、发现隐藏的复杂性。这个过程中的洞见,比最终的代码更宝贵。
如果AI全自动做完,你什么都没学到。下一次遇到类似的复杂性,你还是会陷入同样的坑。
但是,AI可以是一个很好的助手。它可以:
- 自动检测回滚操作,确保你不会"忘记"(因为沉没成本谬误)
- 建议可能的子目标(虽然最终的分解决策还是要人做)
- 自动提交已完成的子任务
- 可视化依赖图
这样,人类保留了思考和决策,AI处理了执行和检查。这可能是更好的结合。
更大的智慧
在我活了一千年之后,我发现一个模式:探索-回退-分解-递进 这个循环,远不只在代码里有用。
学习一门新技能时,这个方法很有效。不是从最难的目标开始,而是先试,失败后分解,从简单的子目标开始。
解决复杂问题时,也是如此。科学方法本质上就是这个:提出假说(目标),实验(尝试),失败时不是坚持,而是重新思考假说(回退和分解)。
甚至人生的大问题——如何成为一个更好的人,也可以用这个框架。不是一个大目标"变成好人",而是很多小的、可完成的目标。每一步都完整,每一步都学到东西。
御木人的智慧,是古人给我们的礼物。一个看似简单的游戏,却隐含了深刻的人生哲学:不要用蛮力对付复杂性,而要用耐心和智慧,一步一步地解开它。
实用建议三条
时间框必须短。十分钟是我的建议。足够短,使得回滚不会有心理负担。足够长,能做点有意义的工作。
完成即提交。这不是"累积改动最后一起提交"。是每个子目标完成,就立刻提交。这保证了你的主分支始终是绿色的,随时可以处理紧急情况。
用在真正复杂的地方。小改动不需要这个方法。但当你面对大型遗留代码的重构、框架升级、架构调整时,这个方法会救你一命。
最后的话
最后让我说一句:聪慧不是不犯错,而是在错误出现时迅速改正,而不是陷在错误中越来越深。
御木人方法教会我们的,就是这种聪慧。
时间会告诉你,这个小小的方法改变了多少项目的命运。