关于

逆向工程的第一原则:先记录现实,再设计理想

我最早以为,逆向工程的起点是把代码读懂。

但真正接手一个存量项目之后,我先撞上的并不是某个复杂类或某条调用链,而是一份看起来非常完整的现状文档。

它有模块目录、入口说明、数据关系和流程图。接手者只要顺着目录往下读,很容易相信:当前系统已经被解释清楚,下一步应该直接开始设计理想方案。

可是当我把这份文档和当前实现放在一起对照时,几个很小的偏差开始冒出来:文档里的入口已经变过,配置里的默认值和说明不一致,某个流程在测试里只覆盖了一半,几条“应该如此”的描述却没有任何直接证据。

这些偏差单独看都不大。真正危险的是,它们会被完整的文档结构掩盖。文档越像一份完整说明,接手者越容易把推断当成现实。

所以我后来更认可的逆向工程第一步,不是设计理想结构,而是先记录现实。

接手之前,我先确认它是不是现实

一份文档可以拥有漂亮的目录、统一的标题和完整的章节,但这只能说明它“像一份文档”。

它还需要回答几个更硬的问题:

  • 这个入口现在真的存在吗?
  • 这条流程现在真的这样运行吗?
  • 这个字段是谁产生的,经过了哪些转换?
  • 这条规则是当前事实、历史决定,还是作者的推断?
  • 如果接手者不相信这句话,应该回到哪里核对?

如果这些问题回答不了,文档再完整,也只是一个容易被误用的假设集合。

相关公开资源

1. 一个“文档看起来完整”的匿名现场

把上面的情况还原成一个更具体的工作画面。

接手者准备修改一个旧业务入口。文档告诉他:这里有一个固定入口,入口下面分成几个模块,数据经过一条已经整理好的流程,最后由测试负责确认结果。

但真正把材料摊开之后,问题不是“少了几页文档”,而是两处关键归因出了偏差:

  1. 一个控制器入口被记录到了错误的责任边界下;
  2. 两类相邻的数据/配置操作在文档里使用了混淆的接口标签。

这两个问题都很小,甚至不会让文档立刻看起来崩掉。可一旦接手者按照错误归因开始设计下一版方案,后面的模块边界、调用关系和验证计划都会建立在偏差之上。

我后来把这次逆向过程拆成了三个动作:

动作看到的事实处理结果
对照入口文档归属和代码实际入口不一致修正入口责任归属
对照操作两类相邻操作的标签混淆修正操作标签和边界说明
对照标准原 Reality 结构完整,但没有充分解释当前状态按当前现实重新组织资料

这时最容易犯的错误,是继续补文档,把每个空白都填成一个确定答案。因为只要表格和流程图越来越完整,团队就会产生一种“现状已经被掌握”的错觉。

我后来先做了一个很笨、但更可靠的动作:把每条描述拆成“谁说的、能证明什么、还缺什么”。这一步的结果不是马上得到一份新设计,而是知道哪些地方可以直接依赖,哪些地方必须先验证,哪些地方现在还不能下结论。

2. 三类来源不能互相冒充

逆向过程中,我现在会刻意把来源分开。

意图材料

需求、产品说明或用户描述可以说明:希望解决什么问题、服务什么目标、有哪些约束。

但它不能证明当前实现已经按这个目标运行。

实现材料

页面、接口、代码、配置和数据可以说明:系统现在实际做了什么、对象如何流动、状态如何变化。

但它不能证明用户目标已经成立,更不能自动说明这是一个合理设计。

验证材料

测试、断言、检查脚本和运行记录可以说明:哪些行为已经被检查过。

但通过某个测试,不等于整个生产行为都已经被证明。

如果某类来源缺失,我不会用另一类来源把空白补掉。需求只能说明意图,代码只能说明实现,测试只能说明验证范围。

3. 我现在会按什么顺序重建现实

如果要把这个方法压缩成一条可执行路径,我会按下面的顺序走:

第一步:确定稳定入口

先找到用户目标、页面、接口、任务、命令或事件中最稳定的入口,回答“接手者从哪里开始理解”。

第二步:沿入口追实现和状态

从入口继续追到代码、配置、数据结构、状态变化和错误分支,不停留在目录名或模块名上。

第三步:建立边界账本

记录哪些内容属于这个入口,哪些内容只是相邻能力,哪些内容暂时无法归属。不能为了追求覆盖率创建一个含糊的“其他模块”。

第四步:给每条结论标证据类型

把事实、推断、未知和阻断显式写出来,并为关键判断保留可回查路径。

第五步:先修现实资料,再讨论理想设计

如果发现文档和现实不一致,先修正事实底稿、记录差异和验证依据,再决定哪些问题值得进入下一版设计。

4. 为什么“先记录现实”比“先设计理想”更重要

因为设计会主动填空。

当现状不清楚时,人和 AI 都会根据经验补全缺失部分。补全之后,方案看起来往往比现实更整齐:模块边界更清楚,流程更顺,字段也更完整。

但这种整齐可能只是把未知藏起来了。

先记录现实的价值,是把设计想象和当前事实分开。它允许我们说:

  • 这里已经确认,可以作为设计输入;
  • 这里只是推断,设计时需要保留弹性;
  • 这里还不知道,必须先补证据;
  • 这里暂时被权限或基线阻断,不能继续猜。

等这些边界清楚之后,理想设计反而会更快。因为设计不再需要同时承担“理解现实”和“改变现实”两项工作。

结尾:先让接手者知道系统为什么这样运行

逆向工程的第一成果,不是一份看起来完整的文档,而是接手者能够回答:

  • 从哪里进入;
  • 当前实现做了什么;
  • 关键边界在哪里;
  • 哪些判断有证据;
  • 还有哪些地方不能确定。

我现在越来越觉得,先把现实记录清楚,不是设计之前的低级准备,而是设计能够不从假设开始的前提。

如果一个项目的 Reality 还没有被建立,最应该做的通常不是继续设计更理想的系统,而是先承认:我们还没有足够准确地知道它现在是什么。

公开资料

Comments