老项目里最容易判断错的,不是某段代码怎么写,而是“这个入口现在长这样,所以它本来就该这样”。我这次在替换一段旧引导页时,差点把“换一个旧页面”做成“重写整套首进规则”,最后才越来越确定:老项目最危险的,不是代码旧,而是你太快相信自己已经看懂了它。
很多人做老项目改版时,第一反应都会是:
- 旧页面换成新页面
- 旧入口换成新入口
- 旧逻辑看起来别扭,顺手整理一下
这套思路在纯新项目里不一定有问题。
但到了老项目里,最容易出事的,往往就是这种“看起来很合理”的顺手整理。
因为你以为自己在做的是:
换一个旧页面
实际上你碰到的,可能是:
用户第一次打开 App 时,整套规则到底怎么决定他先看到什么
这两件事,完全不是一个风险级别。
先说我这次最深的教训
我这次碰到的场景,表面上特别简单。
项目里有一段旧引导页,要换成新版。
第一眼看上去,这种需求很像典型的 UI 替换:
- 找到原来跳旧页面的地方
- 把它改成跳新页面
- 跑一遍流程
- 收口
如果事情真的只有这么简单,那这篇文章也没必要写了。
问题就在于,老项目里很多“看起来只是页面”的地方,背后其实挂着一套已经在线上跑了很久的流程。
比如:
- 用户是不是第一次进来
- 隐私页有没有看过
- 某些入口要不要先走权限说明
- 后台有没有给不同用户不同首进版本
- 某些实验流量是不是还在分不同路径
这些东西在代码里不一定会整整齐齐地摆在一个文件里。
它们可能散在:
- 启动判断
- 本地状态
- 入口控制器
- 远端开关
- 历史兼容逻辑
所以你一旦只盯着“这个旧页面该不该换”,就特别容易误判。
老项目里最危险的误判:把“页面替换”做成“规则重写”
我后来越来越觉得,老项目里最危险的一类错,不是把代码写错了,而是:
你误以为自己在替换页面,实际上你已经开始改规则了。
这两者表面很像,真正的差别却很大。
页面替换
页面替换的意思是:
- 原来的判断先别动
- 原来这一步决定该去哪里,还是按原来的来
- 只是把过去承接这个位置的旧页面,换成一个新页面
它更像是:
路口不改,换个新的路牌和新的接待台
规则重写
规则重写的意思是:
- 你不再沿用原来的首进判断
- 你开始改“谁该先看到什么”
- 你开始改“什么时候算完成”
- 你开始改“哪些旧分支还要不要保留”
它更像是:
不是换路牌,而是直接把整个路口重新规划
老项目最可怕的地方就在这里:
你经常是在没有意识到自己已经越界的情况下,从第一页慢慢滑到第二页。
因为每一步都很像“顺手整理一下”。
为什么人会特别容易在这里判断错
我后来回头看,发现这种误判通常都来自同一个错觉:
你把当前分支里看到的样子,当成了这段逻辑本来就该有的样子。
这在老项目里特别危险。
因为你现在看到的,常常只是它今天留下来的样子,不是它当年为什么会被做成这样。
比如一个入口今天看起来很绕,背后可能是因为:
- 当年做过兼容
- 某些废弃代码没完全清掉
- 某个开关还在服务线上一小部分用户
- 某些判断后来被挪过位置,但职责没完全跟着挪动
如果你只看当前代码,很容易产生一种错觉:
这里本来就该由这个页面负责。
但真实情况可能是:
这个页面只是后来挂在这里的,真正稳定存在的是后面那套判断。
这也是为什么我现在越来越不敢只靠“当前看起来应该是这样”去碰启动相关逻辑。
真正该先确认的,不是页面,而是职责
如果你真的要动一个老项目的启动入口,我现在更建议先问 3 个问题。
1. 这一步到底在决定什么
不要先问:
- 这个页面是不是旧的
- 这个页面能不能换
先问:
这一层到底在决定什么?
它可能决定的是:
- 用户先看隐私说明还是先看功能引导
- 是直接进入主流程,还是先被挡在某个前置步骤
- 某类用户走 A 路,另一类用户走 B 路
也就是说,你要先看清楚它是“一个页面”,还是“一个判断点”。
2. 当前这段代码,真的是这件事的 source of truth 吗
老项目里一个特别常见的问题是:
你以为自己找到了入口,
实际上你只找到了“现在这里有一段跳转代码”。
这不等于它就是这段逻辑真正的核心位置。
真正该确认的是:
- 这段逻辑是不是后来补进去的
- 主分支现在是不是也这么走
- 历史提交里,这个位置以前承担的职责是什么
- 有没有别的地方才是真正决定首进路径的地方
说得更直白一点:
你看到跳转,不等于你看到职责。
3. 这一步周围还有没有别的门
很多人改老项目入口,最容易漏掉的是:
你看到的这个“门”,旁边可能还有别的“门”。
比如:
- 相机权限“门”
- 隐私确认“门”
- 后台给不同用户分不同版本的“门”
- 首次使用说明“门”
如果这些“门”没有一起看清楚,你就很容易把一段局部改动,做成整条入口的重新编排。
我后来是怎么把自己拉回来的
这次真正把我拉回来的,不是某一个灵感,而是两个动作。
第一个动作:回去看基线分支
我后来没有继续沿着当前分支往下猜,而是回去看主分支到底怎么走。
这一步特别重要。
因为老项目里很多阶段性分支,都会混进:
- 临时接入
- 试验性入口
- 联调用跳转
- 还没完全回收的旧逻辑
如果你只盯着当前分支,很容易把这些阶段性状态误当成系统真相。
第二个动作:回去看历史提交
我后来又往前翻了一下历史。
这一步不是为了考古,而是为了回答一个问题:
原来真正承担这段职责的,到底是谁?
看到那一步以后,我才真正意识到:
我差点改掉的,不是一个旧页面,
而是一整套线上还在生效的首进规则。
那一瞬间我其实挺后怕的。
因为如果我当时真的按“反正新版都上了,顺手一起整理得更顺一点”这个念头继续往下改,
我大概率还会觉得自己是在优化,
实际上我是在把原来那套还能工作的规则改坏。
这件事最后留给我的,不是一条技巧,而是一条判断
我现在再看这类老项目改版,脑子里会先过一条判断:
越是启动页、首进页、引导页、权限前置页这种地方,越不能只看表面。
因为这些地方最容易出现一种错觉:
你以为自己在改页面,
其实你已经碰到了系统怎么决定“谁先看到什么”的那套规则。
而这种地方一旦判断错,后面的问题通常不是:
- 某个页面样式不对
而是:
- 用户路径开始变得不一致
- 某些人突然少走了一步
- 某些人又被多挡了一层
- 你自己都很难说清现在到底是谁该先看到什么
这就是为什么我现在越来越觉得,老项目改版最危险的,不是它已经跑了很多年,而是你太快相信自己已经看懂了启动逻辑。
如果你也在动类似的地方
如果你最近也在碰老项目入口、引导页、首次路径这类改动,我很建议你先停一下,别急着写。
先做这 4 件事:
- 先确认你现在碰到的只是一两个页面,还是一整套页面,是否有逻辑关联
- 回主分支看这条路到底怎么走
- 往前翻一段历史,确认职责到底在哪
- 只在确认“原规则不动”的前提下做页面替换
很多时候,这 4 步做完,你会发现:
真正该替换的,往往只是一个承接位置;
真正不该顺手重写的,反而是后面那套你一开始最容易忽略的规则。
最后
老项目最难的,从来不只是代码量大。
真正难的是:
它有很多今天看起来不够漂亮的结构,但那些结构不一定是随便长成这样的。
有些是历史兼容,
有些是线上约束,
有些是你暂时还没看见的判断路径。
所以我现在越来越不把“看懂当前代码”当成已经理解一个老项目。
真正的理解,至少还要再多问一句:
它为什么会变成今天这样?
很多时候,这一句才是把你从“顺手重构”拉回“真正理解系统”的分界线。