跳到正文
产品开发 · 阅读约 6 分钟

如何挽救一个陷入困境的软件项目(以及什么时候应该推倒重来)

Gleb Sosnovskiy

技术负责人

要挽救一个陷入困境的软件项目,请先停下新功能,收回代码和各类账号的访问权限,再请第三方做一次独立审计,明确哪些保留、哪些修复、哪些重写。在大多数情况下,修复现有代码比推倒重来更快,也更省钱。

只有当底层结构阻碍了每一项重要改动时,重写才划算。即便如此,也很少需要一次性全部重写。

本文一步步讲解项目救援的过程:如何识别一个正在失败的项目、第一周该做什么、审计如何进行,以及如何在修复和重写之间做出选择。

要点

  • 首先停下新功能。在不稳定的基础上每多加一个功能,救援成本就更高一分。
  • 在做任何事之前,先确保您掌握代码仓库、服务器、域名和应用商店账号的访问权限。
  • 审计会给出诚实的结论:哪些保留、哪些修复、哪些重写,并根据真实代码给出报价。
  • 全部重写很少是最好的选择;通常更好的做法是分阶段替换最薄弱的部分。
  • 上线之后,明确所有权、里程碑和文档,让产品再也不会依赖某一个人。

如何判断一个软件项目正在失败?

项目很少在一天之内失败。它会慢慢偏离轨道,而每一个信号单独看都很容易找到理由。但当这些信号叠加在一起时,就很难再忽视:

  • 交付日期一再推迟,而且每次的理由都不一样。
  • 每修一个问题就会弄坏别的地方,同样的缺陷反复出现。
  • 没有人能清楚地说出产品什么时候上线。
  • 开发者或外包公司回复越来越慢,甚至不再回复。
  • 您无法访问代码、服务器或各类账号。
  • 新来的开发者说,这套代码“不先重写一遍就没法改”。

出现其中一个信号是警告。出现三个或更多,通常说明项目需要的是一次救援,而不是又一个截止日期。

例如,一家初创公司的自由职业开发者已经不再回复,而服务器密码只有他知道。即使代码本身没有问题,这个项目也需要救援。

项目出问题时,第一步该做什么?

第一周为之后的一切打下基础。在任何技术工作开始之前,有四个步骤:

  • 暂停新功能。在不稳定的基础上继续开发,会让之后的每一次修复都更贵。
  • 收回访问权限。确认您掌握代码、服务器、域名,以及产品所依赖的每一项服务。
  • 记录承诺了什么、实际有什么。收集方案书、合同、设计稿,以及一份如今真正能用的功能清单。
  • 暂缓与交付成果无关的付款。如果按里程碑付款,在有明确计划之前,先暂停下一笔。

不要从追究责任开始。是谁让项目走到这一步、为什么会这样,远不如另外三个问题重要:现在能做什么、需要多少钱、产品什么时候能正常运行。

如何收回代码、服务器和账号的访问权限?

访问权限往往是创始人在最需要的时候最缺的东西。请逐项核对下面的清单,并记下每一项目前由谁掌握:

  • 包含完整历史记录的代码仓库,而不是最新版本的压缩包。
  • 托管和服务器账号,包括数据库和备份。
  • 域名注册商和 DNS 设置。
  • 如果有移动应用,还包括应用商店的开发者账号。
  • 第三方服务:支付、邮件、数据分析、地图、AI 接口。
  • 设计文件以及现有的所有文档。

如果代码仓库在别人的账号下,请对方把仓库转移给您。GitHub 的文档说明了仓库转移时,历史记录、issue 和 pull request 会如何保留。

如果有人不配合,就先从您这一侧收回能收回的部分:域名和托管往往是用您的银行卡付款,或用您的邮箱注册的,这就是一条收回的途径。

项目救援时需要收回的账号和资源清单
在任何技术工作开始之前,先弄清楚每一项由谁掌握。

代码审计包括哪些内容?

审计是对产品实际状况的一次系统检查,而不是按上一家服务商的描述来看。一次有用的审计应涵盖以下方面:

  • 架构。各个部分如何连接,以及这套结构能否支撑您需要的功能。
  • 代码质量。可读性、重复代码,以及每次修改的风险有多大。
  • 安全。常见风险,例如 OWASP Top 10 中列出的问题,以及密钥和个人数据是如何存储的。
  • 基础设施。托管、部署、备份和监控。
  • 测试和文档。已有什么、缺什么,以及补齐需要多少成本。

审计的结果应当是对产品每个部分的明确结论:保留、修复或重写,并且每一项都有理由。只有到这一步,才能给出一个反映代码真实状况的报价。

在 Sakura,我们严格按照这个顺序工作:先审计,再报价。只有这样,救援的报价才不会建立在代码兑现不了的承诺之上。

项目救援的五个步骤:权限、审计、结论、稳定与上线、交接
五步完成救援。审计决定计划,计划决定价格。

您的项目现在卡住了吗?告诉我们发生了什么。我们会从权限和审计开始,诚实地告诉您哪些部分还能挽救。

应该修复代码,还是推倒重来?

大多数情况下,应该修复。已经在生产环境中运行的旧代码,积累了多年针对真实问题的小修正;重写会把这些修正和糟糕的部分一起丢掉。

Joel Spolsky 在他著名的文章 Things You Should Never Do 中讲过这一点。他把从零开始重写代码称为“软件公司可能犯下的最严重的战略错误”,并以 Netscape 为例:重写花了将近三年,而竞争对手在这段时间里遥遥领先。

当然,也有一些情况下,重写才是诚实的答案。下表展示了我们如何权衡:

信号倾向于修复倾向于重写
核心流程大体能用,但有缺陷完全不能用
架构能支撑计划中的功能阻碍每一项重要改动
安全问题可以修复问题出在结构本身
技术栈仍有维护,容易招到人已被放弃,或招不到人
规模较大,有真实用户和数据较小,几乎没有真实使用

即使最终决定重写,也很少需要一次性完成。Martin Fowler 的 Strangler Fig 模式描述了如何逐步替换一个系统:新模块在旧模块旁边逐渐成长,直到旧代码可以下线。

决策矩阵:陷入困境的软件项目应该修复还是重写
大多数信号都指向修复。只重写阻碍产品的部分,并且分阶段进行。

救援期间如何与原团队合作?

如果原来的开发者或外包公司仍然联系得上,一次简短、平和的交接能节省时间和金钱。请对方提供三样东西:所有权限、已知问题清单,以及一次一小时的讲解,说明产品是如何部署的。

让沟通围绕事实展开。人在不觉得被指责时会说得更多,而他们记得的代码细节,比任何关于谁该负责的争论都更有价值。

如果原团队不配合,也不必等待。先收回您掌握的账号,用现有的东西开始审计,并以书面形式记录您在什么时候提出了哪些要求。

如何从救援走向上线?

有了结论之后,就要严格按顺序推进。先上线,再改进:

  • 稳定。修复会导致产品崩溃、丢失数据或阻断支付的严重缺陷。
  • 完成上线所需的流程。只完成产品上线必需的部分,其余的都往后放。
  • 配置部署和监控。让发布成为日常操作,并在用户反馈之前就发现问题。
  • 上线。真实用户会告诉您,剩下的问题里哪些才真正重要。
  • 改进。按照对业务的影响程度,逐项处理清单上的其余事项。

每周交付一个您可以亲手点开的版本,能让救援保持透明。项目已经出过一次问题之后,您应该每周亲眼看到进展,而不只是听别人汇报。

例如,一家初创公司的外包公司错过了好几次交付日期。审计后他们可能会发现,产品的大部分功能其实能用,阻碍上线的只是三个有问题的流程。先修好这三个流程,产品就能上线,其余的待办事项可以根据真实的使用数据来安排。

挽救一个项目要花多少钱?

这取决于审计发现了什么,所以诚实的报价出现在审计之后,而不是之前。不看代码就给救援报价的人,只是在猜。

审计完成后,到上线为止的工作通常可以按固定范围报价。这样您就能得到一个清晰的上线费用,与之后的改进工作分开计算。

如果您在比较不同服务商的救援报价,适用的规则和其他项目一样。我们关于固定价格还是按小时计费的指南,说明了每种模式各自适合什么情况。

如何避免再次陷入这种局面?

一个被挽救的项目,正是补上第一次缺失的那些保障措施的机会:

  • 所有权。代码仓库、托管、域名和应用商店账号都登记在您公司名下。
  • 文档。在开发过程中同步编写,让产品再也不会依赖某一个人。
  • 里程碑。付款对应可以验证的成果,例如一个能通过测试链接打开、可以正常使用的版本。
  • 变更流程。新需求在有人动手之前,先经过评估和确认。
  • 上线后的支持。为修复和更新制定清晰的计划,例如一份按月的支持方案。

如果您要为下一阶段选择新的团队,我们关于如何选择开发外包公司的指南,整理了能在签约前识别不靠谱合作方的问题。

如果您希望产品重新动起来,发给我们一份简短的需求简报。我们会从权限和审计开始,让您在做出任何重大投入之前,清楚了解项目的现状。

常见问题

如果代码真的很糟糕,项目还能挽救吗?

大多数情况下可以。审计会说明是修复现有代码更省钱,还是重写其中一部分更省钱,并为每一条建议给出理由。

如果我们没有服务器或代码仓库的访问权限怎么办?

这种情况很常见。先从登记在您公司名下的账号入手,例如域名和托管,再请原团队把其余部分转移过来。

一次代码审计需要多长时间?

这取决于产品规模和可用的访问权限。审计的范围和时长会提前约定,让您知道什么时候能拿到结论。

全部重写会不会更好?

很少会。全部重写会丢掉多年积累的修正,并推迟上线;分阶段替换最薄弱的部分,通常更快也更安全。

救援完成后,我们还能继续和贵公司合作吗?

可以。开发和支持可以由同一个团队继续进行,也可以连同完整的文档,把项目交接给您自己的团队。

关于作者

Gleb Sosnovskiy

Sakura Agency 技术负责人,负责 Web 与移动端项目的开发。

不确定需要哪种方式?

sakura