把复杂系统写简单:一次重构记录

重构不是把代码写得更聪明,而是让下一个接手的人更容易理解。

为什么要重构?

这个项目并没有坏。它每天都在运行,新需求也能继续加进去。真正让人不安的是,每一次改动都需要先在脑子里装下半个系统:页面知道接口细节,接口层知道业务状态,工具函数又悄悄修改了共享数据。

当一个小需求需要同时触碰五个目录时,问题通常不是文件太多,而是边界已经消失了。

真正的问题不是代码太多,而是边界消失了。

我把这次重构的目标写成了一句话:让改动发生在它应该发生的地方。 它比“减少代码量”更具体,也更容易判断是否完成。

先把职责分开

第一步不是抽象,而是把混在一起的职责重新命名。我最终把流程拆成三个阶段:接收输入、生成领域对象、保存结果。每个阶段只接受上一步明确返回的数据。

export function createArticle(input: ArticleInput) {
  const normalized = normalize(input);
  const article = buildArticle(normalized);

  return saveArticle(article);
}

代码没有因此变得神奇,但阅读路径变短了。你可以从函数名知道流程,也可以单独替换其中任何一步。

不急着做通用层

以前的实现里有一个“万能服务”,几乎所有页面都依赖它。看起来复用率很高,代价却是任何修改都可能影响所有页面。我先允许少量重复存在,等两个场景真正稳定后再提取共同部分。

重复是一眼就能看见的成本;错误抽象的成本,往往要等需求变化时才暴露。

让改变可以被验证

重构最危险的部分,是“看起来应该没问题”。所以每拆开一层,我都会补一条围绕行为的测试,而不是围绕内部实现的测试。

  1. 旧输入仍然得到相同结果;
  2. 失败状态有明确出口;
  3. 新模块可以独立运行;
  4. 页面不再知道保存细节。

这些检查让提交保持很小,也让回退变得简单。重构结束时,总代码量只减少了不到一成,但新增功能涉及的文件从五个降到了两个。

最后留下什么

好的重构不一定带来漂亮的架构图。它更像是整理一间长期使用的工作室:常用工具回到手边,容易混淆的东西被贴上标签,下一次工作不必先清理现场。

我现在更愿意用三个问题判断一次重构是否值得:改动范围有没有变小?错误会不会更早出现?新同事能不能沿着名字读懂流程?如果答案都在变好,系统也就真的在变简单。

评论

条讨论

昵称和邮箱均可不填。发布后会公开显示由 IP 推断的省级属地,完整 IP 和邮箱不会公开。查看隐私说明

正在载入评论
    评论图片预览