【译】重写,重构,还是重新设计? - 软件重写启示录

1,884 阅读39分钟

原文:Rewrite, refactor, or reinvent?

作者:Herb Caudill

重新审视这个老生常谈的问题:你是否应该从头开始重写你的应用程序,亦或是说这是 "任何软件公司都可能犯的最糟糕的战略错误"?事实证明,在处理一个成熟的代码库时,有很多不同的选择。

大概二十年前,Joel Spolsky 在他那篇具有里程碑意义的文章《Things You Should Never Do》中痛斥了网景公司重写代码库的行为。

基于以下两点,他得出的结论是:一个正常运行的应用程序永远都不应该从头开始重写。

  1. 应用程序代码库中的复杂代码往往蕴含着来自边角案例和诡异bug的来之不易的经验。
  2. 重写是一项冗长的工作,它会使你无法持续更新迭代现有产品,而在此期间,你面临的竞争会越来越激烈。

对许多人来说,Joel 的结论成了一种信条;它对我当时的思想产生了很大的影响。

在接下来的几年里,我陆续读到一些与之相反的观点,认为在某些特定情况下,从头开始重写是非常有意义的。比如说:

  • 有时,遗留的代码库确实被搞得无法修复,即使是一个简单的变更也需要对代码的其他部分进行一连串的修改。
  • 原来的技术选型可能会妨碍你进行必要的改进。
  • 或者,原来的技术可能已经过时了,导致很难(或很贵)招聘到高质量的开发者。

当然,究竟是逐步重构遗留代码更好还是把它全部扔掉从头开始更好,很多时候都得结合实际情况,具体问题具体分析。

但这并不是唯一的选择。从下面的六个故事中,看看我们得到到什么启示。

image.png

Netscape

Netscape ... 🡒 4.0 🡒 📝5.06.0 🡒 7.0 🡒 ☠
                                     ⤷ Mozilla 1.0 🡒 ☠
                                           📝Firefox 1.0 ---------- 🡒
                                           
Key:  📝 = rewrite ☠ = dead end

Netscape 灾难性的 5.0/6.0 重写是“永不重写”的经典案例。

定义了早期商业互联网的网景导航者(Netscape Navigator)于 1994 年首次发布。不到两年时间,该公司进行了 30 亿美元的首次公开募股(IPO),开启了互联网泡沫时代。

1996年,Netscape 第一个真正的竞争对手,微软的 Internet Explorer 问世。

到了 1998 年初,Netscape 仍然是市场份额最高的浏览器,但仅仅是勉强保持领先。Netscape 的零售价格为 49 美元,而微软则免费提供 IE,并将其作为默认浏览器随 Windows 一同发布。

image.png

在Netscape 4.0 版本发布之后,该公司宣布将免费提供一个由该公司创建和资助的开源社区 Mozilla 进行开发的 5.0 版本。

这在当时基本上是前所未有的,Netscape 因为这一大胆的举动赢得了很多的好感。然而,事实却是,这个社区并没有真正形成。该浏览器最早的开发者之一 Jamie Zawinski 解释说:

事实上,Mozilla 项目的贡献者包括约一百名全职的 Netscape 开发人员和约三十名兼职的外部开发者,这个项目仍然完全属于 Netscape。

该团队总结出来外部开发者没有兴趣为他们的开源项目做出贡献的一个原因就是现有的代码库混乱不堪。

代码过于复杂和混乱,导致任何改动都非常困难,这也是为什么社区开发者不愿意参与...这也是为什么我们决定转向新的布局引擎。一个更加简洁的全新设计的代码库,从理论上讲,更容易被人们理解并参与贡献。

从头开始

于是在一年之后,团队决定放弃 5.0 版本的工作,并且从头开始开发 6.0 版本。

又过了两年,Netscape 6.0 才终于发布;即使过了这么长的时间,很明显它都还是在没有完全准备就绪的情况下发布的。根据《纽约时报》的评论员 David Pogue 的说法,光是启动浏览器就需要整整一分钟!而且它会占用大量内存。此外,前一代浏览器上的一些简单易用的功能也不支持了:

打印预览功能没了,也无法通过拖动网站地址栏图标直接进入书签菜单。你再也不能通过右键点击地址栏复制或粘贴网址了。每次开始浏览时都必须调整浏览器窗口大小,因为导航器不记得上次运行程序时窗口的大小。最令人担忧的漏洞是,你无法通过一次点击来高亮整个地址栏。

最重要的是,在 Netscape 停滞不前的三年里,Internet Explorer 已经占据了所有剩余的市场份额:

image.png

当重写开始时,Netscape 在微软的 Internet Explorer 面前迅速失去阵地。三年后,新版本终于发布,但它存在很多问题且运行速度缓慢;同时,Netscape 的市场份额已经几乎消失。(图表摘自维基百科

1999 年,重写正在进行中时,AOL 以 100 亿美元的交易价格收购了 Netscape。

在 Netscape 6.0发布两年后,AOL 内部的 Netscape 团队解散了。

Mozilla,这个 Netscape 创建的开源社区,在 2002 年发布了 Firefox 浏览器 —— 这是 Firefox 浏览器的又一次重写。Firefox 确实设法从微软那里夺回了一些市场份额。

但是,作为一家公司的 Netscape 已经消亡了。(讽刺的是,微软在 2012 年与 AOL 达成了一项协议后,最终获得了 Netscape 的知识产权的残余部分。)

在赢得那场战争后,微软撤回了对浏览器技术的投资。2001 年发布的 IE6 在接下来的五年里没有任何升级,这在一些人看来是一种故意的策略,以防止网页成为应用程序的平台。

感悟

有人认为,长远来看,这次重写并不是一场灾难,因为这个项目最终导致了 Gecko 引擎和 Firefox 浏览器的出现。

但在等待新的浏览器崭露头角的同时,我们都不得不忍受 IE6 无休止的、令人窒息的垄断,这导致网络技术多年停滞不前;而且最终结束 IE6 时代的并非 Firefox,而是谷歌的 Chrome。

无论如何,眼下的问题不是重写是否对互联网有益,而是从做出决策的公司的角度来看,这是否是一个明智的决定。

虽然 Netscape 的没落并非完全是由重写导致的,法院也认同微软存在故意滥用垄断权力的行为。

但是重写确实是一个关键因素,最终结果是一家价值数十亿美元的公司倒闭,数千名员工失业。因此,我同意 Joel 的观点,这次重写的后果是灾难性的。

Basecamp

Basecamp Classic --------------------------------------------- ->
            📝Basecamp 2 ------------------------------------- ->
                        📝Basecamp 3 ------------------------- ->

21 世纪初,芝加哥的一家名为 37signals 的网页设计公司,通过创始人 Jason FriedDHH 独树一帜的博客的影响力积累了一大批追随者。

我最开始关注他们的时候,还是一个刚开始做网页设计的新人,那时他们对像谷歌和 PayPal 这样的网站进行了一系列未经请求的重新设计,这些网站被称为 37better

image.png

image.png

近 20 年后,37signals 对联邦快递(FedEx)的运输表单的重新设计(上图)仍然比实际运行的产品(下图)要好。

2004 年,他们将内部使用的项目管理工具作为一款 SaaS 产品推出市场,他们将其命名为 Basecamp。

当时,订阅软件还是一种新鲜事物。项目管理工具以盒装产品的形式销售,价格高昂,附带繁琐的操作手册,主要用于建模关键路径和生成复杂的甘特图。

Basecamp 售价为 50 美元每月,它拥有超级简洁的界面和专注于沟通的特点,给人一种焕然一新的感觉。

几年后,Basecamp 拥有数十万名稳定的用户,每个月都有丰厚的收入进账,但 Jason 和 David 却开始变得感到焦躁不安。

几年前我在软件商务大会上听 David 分享了这个故事。他说,他不仅被 Joel Spolsky 说服了重写软件会毁掉整个公司,还受到了敏捷开发运动的影响,这使他产生了一种自以为是的想法

我完全沉浸在那种超前软件理念中......代码是无限可塑的。遗留代码有无限的价值。任何软件、任何代码都可以轻松地进行重写......如果不能,那就是你的责任。你需要反思自己的不足,并努力提升自己的编程技能。

然而,在他所谓的“七年的黄金时期”之后,他们陷入了困境——与技术债毫无关系

金手铐

他们注意到自己不再像之前那样充满热情。他们不仅没有动力去开发自己的旗舰产品,甚至他们自己都不怎么用这个产品。

他们有很多关于如何从根本上改进产品的想法,但是随着成千上万的人在 Basecamp 创建工作流,他们所做的每一个改变都会对很多很多人造成破坏。改变的障碍不是混乱不堪的代码库,而是他们的用户。

他们专注于保持现有客户群的满意度,这使得产品在时间上处于被冻结的状态,无法再吸引新用户。这对企业来说不是一个直接的问题,但它构成了一个长期的威胁。DHH 用了一个堵住漏水的水桶的比喻:

你可能堵住了所有的漏洞、修复了所有的 bug、升级了所有现有客户抱怨的功能,你以为这样就滴水不漏了——但水总是会漏的。随着客户工作的不断推进,他们不再使用你的软件,即使他们[热爱它]。但你仍然可以自欺欺人:“你看,水桶一大半是满的。那只是一个微不足道的漏洞,从那里渗点水出来是很自然的。”但是,如果这个状态持续的时间足够长,水桶里最终会一滴水都不剩。

问题的部分原因在于:你听到的永远是现有用户的声音,但你听不到未来客户的声音。

你觉得我们什么时候会收到那些几年后访问 Basecamp 首页,却因为我们的想法不够好而选择不购买的人群的反馈?永远都不会。我们听到的永远都是现有客户的声音,这部分用户最希望的是我们的产品保持现有的稳定性和可靠性,我们只要持续修补一些小漏洞就好。

他们开始将自己的盈利产品视为一副金手铐:

首要的事情是确保现有的用户仍然感到满意。这样每个月都会有源源不断的现金流。但与此同时,你必须向他们保证:“Okay,我再也不会改变我的软件了。”

image.png

剧透:他们花了大概一年的时间从头开始重写了 Basecamp,结果非常理想,新用户注册量在 Basecamp 2 发布后立马翻了一番。

我认为,他们的这次重写能取得成功,得归功于两件事情:

首先,他们没有试图重新构建他们现有的产品ーー因为他们对于如何解决他们最初打算解决的问题有了新的想法。

我们真的狂妄到坚信我们在 2003 年所提出的理念,到了 2011 年仍然是最好的吗?曾经,很多人批评我过于自负,然而在 2008 年左右我都不这么认为了。

因此他们把 Basecamp 2 作为一个全新的产品推出,并且不向后兼容 Basecamp Classic。加入了很多新功能,删掉了一些老功能,还有很多东西和之前完全不一样了。

这个决策给予了他们一定程度的自由。这种自由度激发了团队成员的内在动力。他们可以放开手脚去做更多的事情。

不必支持原始产品的每一个使用案例也为他们节省了大量时间。例如,原来的 Basecamp 允许用户在自己的 FTP 服务器上托管文档。剔除这个功能以及其他类似的功能(这些功能在过去可能具有商业意义,但现在已不再适用),使得他们能够在合理的时间内推出新产品。

“日落”是有害的

但是那些成千上万的抱怨他们的利益受到侵害的现有用户怎么办呢?

这就引出了他们做的第二件事情,那就是他们没有放弃现有的产品

David 对软件“日落”这个概念进行了一番演绎:

有人在某个角落编造了一个优美的委婉说法——“日落”。让我们以“日落”来形容终结软件的过程。用户们沐浴在海滩上,注视着他们的数据逐渐消逝,那将是一幅多么美丽的画面啊!

然而,唯有那些称之为“日落”的人才会相信其中的美妙。那些真实经历过软件下线的用户并不会回过头来发出“美不胜收”的感慨。相反,他们会愤怒地质问:“艹!我在这个软件中付出了这么多年的心血!现在你们就这么把老子当成“日落”了?”

他指出,当你强迫用户迁移时,那就是犯下了“有史以来最糟糕的战略错误”。因为你会让整个重复购买的用户群体开始思考是否要继续使用你的软件,或者彻底转向其他选择。

“Basecamp 真的还是我想要的吗?如果我必须迁移所有的数据,或许我可以顺便尝试一下其他的选择。如果我必须将所有东西打包装箱,然后装上卡车,这辆卡车就没有必要非得回到出发的原点。搬家真正麻烦是将我的所有东西打包起来。它是回到 Basecamp 还是搬去别的什么地方,就不那么重要了。”

image.png

David 将 Basecamp Classic 比作徕卡 M3 相机:尽管它自 1967 年以来就不再生产,但徕卡仍然致力于它的售后和维修服务,只要他们还在营业。(图片来源:Dnalor 01

相反,Basecamp 承诺“尊重他们的历史数据”:他们尽可能简化用户的升级操作,但并不要求用户放弃 Basecamp Classic。不仅如此,他们还承诺将无限期地继续托管、支持和维护 Basecamp Classic。

出乎意料的是,四年后,Basecamp 团队再次进行了类似的操作:Basecamp 3 在 2015 年发布,这是一个全新的重写版本,移除了一些功能,新增了一些功能,许多元素都进行了改动。和之前一样,旧版本的用户可以轻松地升级,但他们也可以选择继续使用 Basecamp Classic 或 Basecamp 2 “直到互联网世界的尽头”。

Basecamp 3 不会使任何版本消失。无论是 Basecamp 2,还是 Basecamp Classic。任何一个版本都可以很好地为您服务。请继续使用它们直至互联网的尽头!我们会确保它们快速、安全且始终可用。

但是,但是,但是,那不是很昂贵吗?那不是很困难吗?安全问题呢?遗留代码库呢?是的,那又怎样?对我们来说,照顾好每一个客户——即使他们对按照我们的时间表进行升级不感兴趣——是我们的职责所在。

image.png

感悟

个人而言,我觉得这个模型非常令人振奋。

每次重写都让 Basecamp 有机会重新审视设计决策,并构建出他们希望在上一次构建时就能实现的产品。

对用户来说,这是最好的两全之选:那些不喜欢变化的人不会失去他们熟悉的环境,而那些遇到产品限制的人则能使用一个新的、经过深思熟虑的应用程序。

无限期维护多个版本的产品并不是没有代价的,但正如 David 所说:

这并不是没有代价的。你为什么会有这种期望呢?这件事情是非常有价值的,所以当然不会是 0 成本的。但它值得我们这么去做。

image.png

Visual Studio 和 VS Code

VS 97 -> 6.0 -> .NET -> ... -> 2015 -> 2017 -> 2019 ------- ->
                                 📝VS Code ------😎------- ->

Key: 😎 = street cred

微软开发 VS Code 的目的是为了吸引那些在其他平台上工作的开发者。

想必你还记得,在很长一段时间里,使用微软的工具意味着要全盘接受其生态系统。如果你使用 Visual Studio,就得使用 .NET,反之亦然。这将软件界分成了两个庞大的、互相排斥的阵营,这对所有人来说都是不利的。

接触新时代开发者

这种分裂甚至在 Steve Ballmer 的时代就开始了——还记得当 ASP.NET 团队决定复用 jQuery 时,引起了多大的轰动吗!

吸引那些在微软封闭生态之外的开发者,是微软 CEO Satya Nadella 明确提出的使命之一。

但正如《The Changelog Podcast》中的嘉宾、Visual Studio 副总裁 Julia Liuson 所说:

我们之前没有任何一款面向这一类开发者(现代化、面向 Web、以 Node 和 JavaScript 为主的开发者)的产品,我们无法与你们沟通。你们是我们无法吸引的开发者群体。

因此,开发 VS Code 的动机就是要打破这个障碍,告诉你们:“实际上,我们确实有一款适合你们使用的工具。”

Visual Studio 是一款从各个方面来说都相对庞大的产品:安装可能需要半小时甚至更长时间。它必须支持企业客户所依赖的各种复杂用例。因此,使用 Visual Studio 本身作为起点,并通过添加功能来吸引其他平台的开发者是没有意义的。而且可以想象,开发适用于 Mac 或 Linux 的 Visual Studio 版本的想法是行不通的。

因此,微软选择在不保证向后兼容的前提下从零开始。

实际上,并非完全从零开始:微软已经有一些重要的组件可供使用,比如基于浏览器的 Monaco 编辑器。而且由于 VS Code 是一个 Node.js 应用(使用 TypeScript 编写并在 Electron 中运行),他们能够利用丰富的JavaScript 生态。

VS Code 是一款开源的、轻量级的、快速可扩展的产品;而且令人惊讶的是,作为一款微软产品,它已经成为了新时代开发者的首选编码环境。

8.jfif

根据 2018 年《JavaScript 现状调查报告》的数据显示,VS Code 已成为 JavaScript 开发者的首选文本编辑器。

这两款产品仍在积极开发中,并没有迹象显示微软打算停止支持 Visual Studio。

感悟

与 Netscape 的经历形成鲜明对比,微软成功地围绕 VS Code 建立了一个活跃的开源社区。这个社区使得开发团队的努力获得了事半功倍的效果。

9.png

巧合的是,在 GitHub 的所有开源项目中,Visual Studio Code 的 star 数排名第 13 位,恰好排在 Linux 下面!

当然了,并不是每个人都有一个能够支持将核心产品完全开源的商业模式。

但如果开源是你的开发策略的一部分,对比研究这两个案例,了解微软是如何做出与众不同的举措从而让整个社区蓬勃发展的,可能会对你有所裨益。

另一个促进因素是,微软为 VS Code 提供了稳定可靠的可扩展性模型,其结果是社区编写了近 10,000 个扩展插件。

尽管对于如今工具集的复杂性存在诸多担忧,但事实上,JavaScript 生态系统在过去几年中已经发展成为一个可复用、模块化的开源代码理想国。从这个角度来看,这是一个具有历史意义的前所未有的时代。

10.jpeg

Gmail 和 Inbox

Gmail ----------------------------------------------------- ->
                    📝Inbox for Gmail ------ ↗ -- ↗ -- ↗  🌇
                    
Key: 🌇 = sunset

Inbox for Gmail 最初是作为 Gmail 的一种简化 UX 而推出的,旨在专注于真正重要的事项。它与原始的 Gmail 在功能上并不完全一致,并引入了如邮件捆绑、置顶邮件、延迟消息等新功能。

包括我在内一些人,对 Inbox 表示热情的接受。我一直认为 Inbox 是 Gmail 的先行预览版,愿意容忍其中缺乏一些 Gmail 的细节,并期望它们最终会出现在 Inbox 中。

两套界面,一个服务

无论是 Inbox 还是 Gmail,它们都使用相同的后台服务。实质上,它们只是同一服务的不同用户界面,你可以随意切换使用。这种做法有其优点也有缺点:如果 Inbox 缺少某个功能(比如自动回复假期邮件),你可以切回到 Gmail,在那里完成你需要的操作。但在来回切换时,难免会有一些奇怪的情况发生。

然而,过了一段时间,Inbox 的改进停滞不前,很明显 Google 已不再投入任何资源。果不其然,在 Inbox 推出四年后,Google 宣布停止支持 Inbox

11.png

起初我感到非常恼火,但在花了一些时间使用最新版本的 Gmail 后,我发现许多我在 Inbox 中喜欢的功能都已经被移植到了原始产品中:智能回复、悬停操作、内联附件和图片。Gmail 的多个收件箱可以很好地替代 Inbox 的捆绑功能。

但并不是所有功能都被移植过来,比如延迟发送功能,它是许多人处理电子邮件的重要方式,而 Inbox 的消失让他们失去了这个功能。

感悟

Inbox 为 Gmail 团队提供了一种尝试新功能且不会干扰那些选择不切换的绝大多数用户的工作流程的方式。

然而,让两个版本使用相同的后端,严格地限制了 Gmail 的创新能力。

谷歌再次因关停一个受欢迎的服务而受到诸多批评。当然了,谷歌一直不断地关停产品,我们能有什么办法呢。

在这个案例中,谷歌最初对 Inbox 的宣传让我们相信我们提前看到了 Gmail 的未来。诚如 DHH 所说,这并不是一次美丽的“日落”;对很多人来说,不得不回到旧产品并失去 Inbox 的创新工作流程是操蛋的。

我认为如果在关停之前,Gmail 能够完全达到与 Inbox 功能的平衡,那么可能会减少一些不满的情绪。

12.png

FogBugz 和 Trello

FogBugz ------------------------------------ 😟
                     📝Trello --------------------------- -> 🤑
                     
Key: 😟 = sad decline 🤑 = money money money

FogBugz 是一个特别有趣的案例,因为它正是由 Joel Spolsky 创造的产品。它让我们看到了从实际产品角度来看,永不重写原则是如何发挥作用的。

在 Jira 和 GitHub Issues 出现之前,有一款名为 FogBugz 的基于 web 的 bug 跟踪产品。它发布于 2000 年,是 Joel 与 Michael Pryor 共同创立的 Fog Creek 软件公司的首个产品,并且在超过十数年的时间内都是他们的旗舰产品。最初,他们只是将其作为装箱软件销售,供用户安装在自己的服务器上,后来又推出了托管式订阅版本。

FogBugz 非常流行,特别是在像我这样的开发者(关注 Joel 的博客并将他的建议奉为圭臬)。我司多年来一直使用它,它是当时非常优秀的一款产品。

FogBugz 最初是用 ASP 编写的,运行在 Windows 服务器上。当 ASP.NET 发布时,Joel 解释了为什么他不急于升级

为了能够在 Linux 服务器上安装 FogBugz,一名实习生编写了一款名为 Thistle 的编译器,用于将 ASP 转换为 PHP。到了 2006 年,Thistle 发展成为一门内部编程语言—— Wasabi,它可以编译成 ASP、PHP 和客户端 JavaScript。

Wasabi 奇谭

现如今,开发一种内部专有的编程语言和编译器可以说是一个反常的选择。所以,请允许我稍作偏离主题的简要介绍。

在一篇博文的结尾,Joel 随意提到了 Wasabi,描述了它的存在。但显然有些人认为他就是随口一说,因此他特别进行了澄清,表示自己是认真的。这使同为博主的 Jeff Atwood 极为震惊

编写自己的编程语言绝对是不可思议的举动。这是一个有害的决策,与 Joel 之前在软件开发方面提供的出色的、理性的建议完全相悖,以至于很多人都认为他是在开玩笑。

Joel 坚持认为这是有商业意义的:当然,如果你从零开始,你不会去开发自己的编程语言。但如果你逐个考虑一路过来的每个决策,考虑当时的技术环境和他们当时的代码库,你就会明白为什么会走到那一步。

在一篇名为《Technical Debt and Tacking Into the Wind》的文章中,前 Fog Creek 工程师 Ted Unangst 将开发 Wasabi 的过程比作一场没有地图的旅行:

设想一下,你身处佐治亚州的萨凡纳,怀揣着前往英国伦敦的梦想。但你没有地图,只有一个模糊的方向感...在你面前的是一片浩瀚的大海,你无法直线前行,除非你自己造一艘船。然而,在你的东北方向,延伸着一片宜人的沙滩,指引着你心中向往之处。你毫不犹豫地踏上旅程。岁月不居,时节如流。你知道自己并没有径直走向目的地,但你每迈出一步都在向它靠近。

最终,你在波士顿或者新斯科舍的某处停下来思考你的选择。也许这并非通往伦敦的道路。从高高在上的看客中传来阵阵嘲笑声:“哈哈哈,看看这群白痴,根本分不清英格兰和新英格兰的区别,给这群傻子弄一张地图吧。”但这正是问题所在,你没有地图。地图往往是由那些不知道自己要去往何处的人绘制的。

无论如何,正如前 Fog Creek 开发人员 Jacob Krall 作出的解释,这个决策是以当下的开发速度为代价,换取未来的可维护性 —— 这正是技术债的定义 —— 到了 2010 年,这笔技术债的账单开始到期了。

我们没有将 Wasabi 开源,因此任何投入都必须由我们自己承担,而这会损害我们主要的收入来源产品。我们需要雇佣全职的开发人员,对于我们这样规模的公司来说这并不便宜。有时,它会在对人类来说完全合理的代码上出现问题。它的编译速度很慢,而且无法轻松地在 Visual Studio 中进行编辑或连接到 FogBugz 调试器上。对于所有新员工来说,不论他们之前的经验如何,他们都需要花费大量时间来学习 Wasabi。此外,我们并不是生活在一个封闭的环境中。其它编程语言在不断改进。开发人员开始感到我们小小的 Wasabi 世界限制了他们的杰出想法。

转折点

十年后,FogBugz 已经成为一个成熟稳定的产品。Joel 与 Jeff Atwood 一起创建了 Stack Overflow 作为他们的副业项目(可能此时 Joel 的头脑终于恢复正常了)。

然而,FogBugz 并未引起热烈反响,并且显示出了它的老化迹象。尽管 bug 跟踪器市场仍然存在碎片化的情况,但是 Atlassian 公司在 FogBugz 问世之后几年才推出的 Jira 成为了(尤其是对于较大的企业用户而言)首选产品。

我对 Fog Creek 历史上的这个转折点非常着迷。就像 Basecamp 一样,他们拥有一款盈利且成熟的产品。这款产品已经不再具有吸引力,可能对于开发人员来说也不太令人兴奋。不论好坏,他们都代表了多年来技术变革和解决特定问题领域的不断发展的思想。

当然,针对这种情况,可以采取像 Basecamp 那样的策略:利用 Fog Creek 在缺陷跟踪方面的经验,从零开始重新构建 FogBugz,重新设计产品。

但我猜这个策略并不会被采用——因为那是“永远不要做的事情(《Things You Should Never Do》)”,“最糟糕的战略错误”......

我最近看到了一篇撰写于 2009 年的文章,当时 Joel 在为《Inc.杂志》撰写月度专栏——《Does Slow Growth Equal Slow Death?》。与他通常自信而夸大的口吻截然不同:这篇文章更加内省、犹豫和充满怀疑。他对 Atlassian 的快速增长感到担忧,思考在缺陷跟踪市场中是否只有一个产品能存活下来。

我不得不思考。市面上,有一家竞争对手似乎比我们增长得更快。该公司正在与大型企业客户签订重大交易。明明我们的产品更好,我们也是一家管理良好的公司,但这似乎并不重要。为什么呢?

因此,他决定采取两个行动。首先,给 FogBugz 添加大量的功能:

我们开发团队在 2010 年的使命就是:消除顾客因为一些他们自认为绝对无法离开的细节功能而购买竞争对手垃圾产品的任何可能。坦率地说,我认为这并不难。

其次,建立一支企业销售团队。Joel 也承认这是他不擅长且厌恶的事情。

我不知道这两个计划的具体执行情况。Joel 在他的博客上最后一次提到 FogBugz 只是几个月后发布了一则次要版本的简短公告

新希望

事情是这样的:

在 Fog Creek 成立十周年之际,我开始思考,如果我们想让员工在接下来的十年里保持激情和动力,我们得需要一些新项目。

因此,他们将团队分成了两个小组,每个小组负责提出和原型化一个新的产品。

获胜的小组受到 Kanban 的启发——这是一种在软件开发中常用的物理工具,通常包括将便利贴按列贴在白板上。

Joel 将其描述为一种可以在比 FogBugz 更高层次上管理工作的工具:

老实说,在那么多花哨的“项目管理”软件中,我从未找到一种能够有效追踪谁应该做什么工作的方法。……作为两家公司的创始人,每天走在走廊上看到那么多人坐在电脑前领着薪水,却不知道他们是否在做正确的事情,或者可能他们认为重要的事情实际上并不重要,这让我开始感到分心了。

14.png

13.jpeg

通过构建 Trello,Fog Creek 的开发人员有机会尝试使用最新的技术:

我们使用前沿技术。然而,这通常也意味着我们会遇到一些挑战。我们的开发人员在使用 MongoDB、WebSockets、CoffeeScript 和 Node.js 时可能会面临一些困难。但至少他们享受其中的过程。在当今竞争激烈的就业市场中,优秀的程序员对他们将要从事的工作有很大的影响力。如果能给他们一个令人兴奋的产品……他们会乐在其中,对自己的工作也会充满热爱。

Trello 还在一开始就支持第三方插件,这样可以使内部开发团队的努力成果倍增:

API 和插件架构是我们最重视的部分。如果有可能,我们会通过提供基本的 API 让那些高价值用户为我们开发功能。在 Trello 团队中,任何可以由插件实现的功能都必须由插件提供。

毫无疑问,程序员们立刻就看到了 Trello 的实用性;但工具本身并没有特定针对软件开发的功能。Joel 称其为适用于“任何需要与一群人共同维护列表的事物”。很快,Trello 开始被用于组织各种事务,无论是今天吃什么婚礼计划还是动物收容所,都能发挥其作用。

相比于 FogBugz 作为一个针对特定利基市场的纵向产品,Trello 则是一个横向产品,可以被任何人用于任何事情。Joel 认为在这个时刻,对于 FogBugz 来说,“产品横向化”是正确的选择。

打造一个在任何领域都有用的广泛应用产品几乎是不可能的。你无法收取过高的费用,因为你要与其他广泛应用产品竞争,它们可以将开发成本分摊到大量用户身上。这是高风险高回报的策略,对于一个年轻的自资助初创公司来说并不适合,但对于像Fog Creek这样成熟稳定的公司来说,这是一个不错的想法。

为了快速扩展用户,Trello 最初是免费的。后来又推出了付费的“商务舱”计划。

2014年,Trello 被分拆成一家独立的公司。三年后,拥有超过1700 万用户的 Trello 以 4.25 亿美元的价格售出。讽刺的是,买家正是 Fog Creek 的宿敌 Atlassian。

与此同时

Fog Creek 继续研发另一个新产品,一款叫做 HyperDev 的协作编程环境,后来改名为 GoMixGlitch

与此同时,FogBugz 在默默无闻中萎靡不振。2017年,有人提出 FogBugz 这个名字太蠢了,于是将产品重新命名为 Manuscript。一年后,Fog Creek 将产品卖给了一家名为 DevFactory 的小公司,这家公司很快就把产品名改回了 FogBugz

在 CEO Anil Dash 的领导下,Fog Creek 成为了一家单一产品公司,并正式更名为 Glitch

感悟

对这一切,我感受颇多。

打造一个舒适的工作环境是我们的首要目标。我们提供私人办公室、头等舱机票、每周40小时的工作时间,还给员工提供免费午餐、Aeron 座椅和顶级的电脑。我们向全世界分享了我们的巧妙公式:良好的工作环境 → 优秀的程序员 → 出色的软件 → 利润!

理解整个故事的关键在于,Fog Creek 一直致力于赋予程序员更多权力,而不仅仅是关于缺陷跟踪:

以这个“公式”为基础,或许我们可以构建一个连贯而鼓舞人心的故事:Fog Creek 以开发者的幸福感为基中心打造了一个企业。这既体现在公司的产品上,也体现在其内部的“运营系统”中。其第一代产品,一个缺陷跟踪工具,为推出一个以更广泛适用方式解决类似问题的新产品提供了基础。

我认为这真正有意思的地方在于,根据 Joel 讲述的 Trello 的起源故事,与其说 Joel 在寻找新的商机,不如说 Joel 在寻找一种让 Fog Creek 的开发者保持快乐和投入的方式。创造出一个价值数十亿美元的产品,只是一个愉快而意外的结果。

对于 FogBugz 的最终命运,我也无法不感到些许悲伤。我想,在 Fog Creek 最后的日子里,产品可能并不会给开发者带来太多的快乐。

显然,所有参与其中的人都有更重要的事情要忙:Stack Overflow、Trello 和 Glitch,每个都比 FogBugz 更加有价值;而每个人在有限的时间内只能投入有限的精力。因此,我不能对任何个别人对 FogBugz 失去兴趣感到怨恨,毕竟它拥有着二十年历史的代码库和竞争激烈的细分市场。至少,它的忠实用户找到了一个良好的归宿,而不是被当成“日落”对待!

然而,我内心深处的情感还是希望能够以更好的方式“铭记”所有那些多年来为它做出贡献和使用它的人们的“遗产”。

15.png

FreshBooks 和 BillSpring

FreshBooks ------------------------------------------------ ->
                   🕵️‍📝BillSpring ------- ↗

Key: 🕵️‍♀️ = undercover operation

这篇文章已经比我预期的要长得多,但我不能漏掉这个有着精彩转折的故事。请务必继续读下去。

除非你之前听过这个故事

21 世纪初,Mike McDerment 开了一家小型设计机构。他认为传统的会计软件对他的需求来说过于复杂,决定使用 Word 和 Excel 来制作发票。

这套系统一开始非常好用,直到逐渐不再满足需求:Mike 是一名设计师,而非程序员,但他和其他两位联合创始人设法拼凑出一个足够好用的工具,以每月 10 美元的价格吸引了一些用户。他们花了近四年的时间才赚到足够的积蓄,让 Mike 能够搬离父母家的地下室。

有一天,我意外地覆盖了一份重要的客户发票,这让我达到了崩溃的边缘。我意识到必须有更好的解决方案,于是我花了两周时间编写了现在成为 FreshBooks 基础的代码。

在产品成立 10 周年之际(听起来有点熟悉了吧?),FreshBooks 已经稳定盈利,拥有超过 1000 万用户和 300 名员工。

只有一个问题:当他们最终雇佣了“真正的”程序员时,他们已经有了一百万行的“创始人代码”。一位外部分析师审查了他们的代码库,并得出这样的结论:

“好消息是,你们解决了最困难的问题。你们找到了如何经营一家企业的办法,并且拥有一款深受人们喜爱的产品。坏消息是,你们的代码就是一堆『屎山』。”

然而,更重要的是,他们有一些新的想法,而现有产品无法满足这些想法的实现:

公司成立已经超过十年了;随着世界潮流的变化和我们对于为自由职业者提供服务的深入了解,我们积累了许多打造产品和满足自由职业者需求的经验。自由职业者及其团队是劳动力市场中庞大且不断增长的一部分... 为了能够与时俱进并在未来五年内更好地为他们提供服务,我们必须要采取行动。

McDerment 已经对从零开始的常识有了深入的了解:

对于软件公司来说,没有比重写更大的风险了。很可能你甚至无法完成项目。它会比你想象的时间更长,花费更大。当你这样做时,顾客可能会对其不太满意。并且,你并不能确保通过构建一个新平台就能得到一个更好的产品。在软件领域,有一个首要的规则,就是不要重新构建你的软件。

因此,他们尝试在不重写的情况下进行优化,但最终发现“边开车边换胎”是不可能的。

令人咋舌的操作

McDerment 最终决定秘密地打造一款 FreshBooks 的竞品。

他在特拉华州注册了一家名为 BillSpring 的新公司。这家新公司有自己的网址、品牌和 Logo。为了确保这两家公司之间没有关联,他让一位外部律师起草了新的服务条款。

开发团队采用了 Jeff GothelfJosh Seiden 所著的《精益UX:与敏捷团队设计出色产品》作为他们的行动指南,并引入了敏捷实践。McDerment 告诉他们要把自己视为初创公司,将他视为风险投资人。

"你们还有四个半月的时间。如果到时候你们能进入市场,我们将提供更多资金支持。否则,我们会退出项目。”

在第一年结束时,他们开始向 BillSpring 的客户收费。而这个新产品的验证方式却出乎意料

在截止日期前几天,团队成功开发出了最小可行产品(MVP)。他们购买了 Google AdWords 来增加新网站的流量。首年他们提供免费账户,很快就获得了真实用户,并开始快速迭代以完善产品。

“有人给我们打电话取消了 FreshBooks 订阅,并告诉我们,他要转用这个新公司的产品。” McDerment 说:“那天是个好日子。”

不久之后,他们公开了这个秘密:向 BillSpring 的客户宣布产品现在变为 FreshBooks,同时告知现有的 FreshBooks 客户将很快推出新版本。

逐渐地,“FreshBooks Classic”的客户被邀请尝试新的升级版本,但这并非是强制性的,如果他们愿意,他们随时可以迁回到更为熟悉的版本。

感悟

FreshBooks 的秘密重写并不便宜:McDerment 估计他们在这个项目上花费了700万美元。在经历了十多年的自主成长后,他们刚刚筹集到了 3000 万美元的风险投资;所以他们有足够的现金。并非每个人都有这么多的资金可以投入。

据《福布斯》估计,2013 年 FreshBooks 的收入为 2,000 万美元。在完成升级后的 2017 年,他们的收入达到了 5,000 万美元。他们没有透露这种增长中有多少来自新产品,但是重写似乎并没有减缓公司的增长速度。

McDerment 报告称他们现在能够更快、更容易地添加功能。更重要的是,他们拥有了一个能够实现他们最好创意的产品来迎接未来的挑战。

除了他们所陈述的目标之外,他们发现这一经历以一种积极的方式改变了公司文化。他们在扮演初创企业的角色期间,变得更像一家初创企业。他们实验的“精益”实践方法传播到整个工程团队中。客户密切参与到了新功能的开发过程中。

FreshBooks 采取了非常极端的措施来避免重写可能带来的潜在风险:通过创新地使用一个临时品牌,开发人员可以完全重新思考事物,并承担更大的风险。这样,最坏的情况就是他们可能再次陷入僵局,但至少在这个过程中不会损害他们现有的品牌。

这种做法可能有些极端,也许没有必要像他们那样做得那么彻底。但这也提醒我们,重写的风险有多高。

写在最后

众所周知,关于重写软件的常识是,通常情况下应避免重写,而是进行渐进式重构——除非出于某种特殊原因确实不可行。

就目前而言,我同意这一观点。

然而,这个建议的前提是最终目标是在原有产品的基础上增加一些新功能。

但如果你是想删除某些功能呢?又或者你想以完全不同的方式解决某个使用场景呢?如果你的产品使用经验给你带来了对一种全新方案的想法呢?

我从这些故事中得出的结论是:一旦你认识到当前版本的产品与你所想象的最佳版本之间存在一定的差距,那么正确的方法不是用新版本替换你的软件,而是在保留现行版本的同时,重新构建一个新项目。

因此,如果你在正在考虑是否应该进行重写,或许你可以审视一下你的产品,然后问问自己:我能否创造出自己的竞争对手?如果我的产品是 FogBugz,那么我的 Trello 会是什么?如果它是 Visual Studio,我的 VS Code 会是什么样子?

如果你回头再重读 Spolsky 关于 Netscape 的帖子DHH 关于 Basecamp 的帖子的话,你会发现他们在一件事情上的看法是一致的:你已经创造的东西是有价值的。

好消息是,你不必为了创新而放弃这种价值。