科技界的大多数新生事物都只是一波又一波的潮流:说话和做事的模式来了又走,没有留下永恒的印记。微内核,IA-64 架构,对象请求代理,20 世纪 90 年代的神经网络,这些东西都已经不复存在,也不会再回来了。时间已经证明了哪些东西是昙花一现,为了说明问题,我们必须追溯到很久以前。
今天的我们很难想象,在鼎盛时期,那些技术有多么的受欢迎。它们有很多极具魅力、真诚且聪明的倡导者,倡导者们得到了看似合理的基本原理论证的支持,这些论证证明了他们选择的技术必然会取得胜利。这些潮流催生了运动、宣言、会议和公司。但请不要把这些潮流与蓄意欺诈混为一谈,后者要少见得多。推动这些技术潮流的动机是发自内心的真诚,不管它们以何种方式出场,二者产生的结果是完全不同的。
另一方面,一些重要的新技术是革命性的:它们强大而持久的变化为技术采用者带来了长期的优势。面向对象编程、硬件虚拟化、万维网、公有云、CI/CD 和 20 世纪 90 年代的神经网络(深度学习的重生)现在成了计算机世界永久的组成部分,而它们曾经“混迹”在潮流之中,难以区分。我们被技术浪潮所包围,在它们展露头角之前,我们并不知道如何用它们来获得成功。
与其他科技公司一样,Slack 希望在正确的时间采用革命性的技术,避免把过多的精力浪费在追逐潮流上。Slack 采取了什么样的战略来确保做到这一点?这篇文章介绍了 Slack 用来解决这个问题的方法。
我们不能依靠个别领导者的直觉来区分哪个才是赢家。相反,我们要积极地探索新事物,虽然我们也知道这些尝试大部分都不会有任何回报。但为了让我们的投入偏向于有用的新事物,避免踩太多潮流的坑,我们应该在早期就要无情地扼杀那些没有价值的实验。我们希望每件事都去尝试一下,这意味着我们仍然要与潮流为伍。我们希望最终能够乘着潮流到达彼岸,我们与潮流打交道的经验不断为我们提供积极的回报。
我们创建了一个描述性的新技术采用曲线模型。
这是一条典型的 S 曲线,描述了技术的采用随时间变化的情况。S 形反映了技术采用的变化。一开始,当只有几个实验者在做实验时,我们别无选择,只能慢慢地接受。稍后,当情况变得清晰的时候,就会有更多的人参与进来,我们会在中间陡峭向上倾斜的部分快速地将新技术应用到生产中。当大多数有成果的试验圆满完成,就会剩下寥寥无几难啃的“硬骨头”。于是,在周期接近结束时,采用速度又慢了下来。
我们把这三个阶段画出来:
我们并不是第一波发现技术采用遵循这种 S 型曲线的人。Everett Rogers 在 1962 年的《创新扩散理论》(diffusion of innovation)一书中就已提出了这一模型。不过,Rogers 并没有提到 Erlang 或者 MongoDB,因为他是一位农村社会学家,他观察的是农业技术采用的模式。但事实证明,计算机领域与人类活动的其他领域并没有太大的不同。
为了让这个抽象的概念更具象一些,我们将例举一些已经在 Slack 经历了探索、扩张和迁移阶段的技术。
从 2015 年发布第一个稳定版本以来,React 席卷了前端开发领域。虚拟 DOM 和单向数据绑定让它成为开发 Slack 桌面用户界面的一项引人注目的技术。
在服务器端,我们从 2016 年开始从 PHP 迁移到 Hack。这次迁移的一个关键部分是在我们的 PHP 代码中逐步引入类型:
Vitess 是一个用来进行 MySQL 水平扩展的集群系统,在进行数据分片策略演化过程中,我们选择了它。
与以上那些经历了各个采用阶段的技术相比,我们的跨平台 C++ 客户端库并没有走到第三阶段,并且最终停止了。
到最后我们并没有进行全面的迁移。我们将从 LibSlack 中学到的东西以各种方式应用到移动和桌面客户端开发工作中。代码工件并没有被长期采用,但这个项目让我们学会了应该如何构建客户端以及如何组织我们的工程团队。
需要注意的是,这个模型是描述性的,而不是说明性的。我们并不是想要强迫人们接受这个 S 型曲线,尽管我们想要这样。实际上,这是一个自然的过程。早期的探索阶段不可能像中期阶段那样迅速地进行,最后的阶段也不可能像中期阶段那样迅速地进行全面采用。这三个阶段并不是任何里程碑、过程、工具或 Slack 工程人员作用的结果。它们是技术变革的一部分,不管我们有没有注意到它们,它们都会存在。
现在,我们已经注意到了它们,我们可以利用它们,让我们的努力更加卓有成效。每个阶段的战术和战略是不一样的。
第一阶段是无门槛进入。当工程师第一次开始调研他们感兴趣的技术时,不需要任何许可授予过程或仪式。在 Slack,这样的事情一天可能会发生几十次:有人发现了新技术,或者发明了新东西,然后就开始研究它们。他们可能是因为读过关于 Elixir、Cassandra、WebAssembly 或 TCR 的博文,或者下载了一些软件,编译打包,四处看看,浏览一些介绍性的材料,还可能尝试把它们应用到日常工作中。
大多数的探索工作都在这个阶段进行。在这个阶段,为了避免在不必要的事情上花费太多精力,我们要懂得放弃掉一些东西。不过确实还是有一些东西被用到了实际的工作流程和代码库中。有时,工程师可以直接应用某些解决方案,因为它们解决了一些局部问题。有时候会出现更加令人兴奋的结果:某些解决方案也解决了其他团队所面临的问题。这个阶段的工程师相信他们知道一些其他人不知道的东西:一些事情可以用更好的方式来做。一旦他们的工作开始影响到其他人,我们就进入了第二阶段。
进入第二阶段,工程师就有点可怜了!因为他们现在正试图改变其他工程师的行为,这将涉及沟通、说服,如果一切进行得顺利的话,他们还需要做大量的技术工作。对于大多数项目来说,第二阶段是最困难、最耗时、最令人沮丧的阶段。在技术周期中,这是“产品与市场匹配”阶段,很多进入该阶段的项目无法成功地走完这个阶段。
在 Slack,用户团队可以自由选择是否要依赖你的系统,很少有例外。如果你习惯了“基础设施驱动”的公司,那么我们的情况可能会让你大吃一惊。在其他公司,领导层会在第二阶段产品市场适应得出结论之前就选出了赢家和输家。他们之所以这么做,是为了提供清晰的信息(比如未来会怎样、我们应该采用哪个系统)和降低成本,因为在这一阶段需要支持更多的做事方式。
虽然这些都是合理的目标,但 Slack 并没有选择这种方式。我们优先考虑的是适应潮流的能力,而不是适应的速度。因此,我们(有意地)将促进其他团队采用新技术的主要负担放在了小部分人身上。虽然这可能会让这些人感到沮丧,但我们知道没有其他更好的办法。为了清除这一障碍,我们不得不选择更加有效的方法。如果新技术真的像我们所希望的那么美妙,那么它们应该能够帮助依赖它们的团队顺利完成工作。反过来,这种结果会促使他们采用和推广这些新技术。
第二阶段的一些工作更像是产品工作,而不是工程工作。你需要研究用户,以便确定哪些问题是重要的。你需要按照用户所期望的方式将你的解决方案的价值与之前的实践联系起来。你需要想办法缩小当前实践与你正在做出的改变之间的差距,让用户更容易接受。
在第二阶段取得的成功最终会导致一些自发式的采用,用户可以自由地选择是否采用新技术。当新系统成为事实上的标准,第二阶段就接近尾声了。偶然性地遇到这种采用情况是很不寻常的,因为这真的很难,而且并不是每个工程师都具备相关的技能。
自发式的采用最终会逐步减少,最后剩下一些顽固的人,他们似乎很抵制新的做事方式。一些后台运行的系统尤其没有动力去做出改变,因为它们的开发度不够活跃。在某些情况下,我们到了后期才发现一些旧系统在某些方面按照旧有方式运行会更好。最后,总是会有一些顽固的用户坚持使用老方法。
虽然我们一直在讨论“技术采用曲线”,但实际上在第三阶段会出现一个分岔口。即使非常成功的项目也不可能彻底采用全新的技术。例如,在 Slack,我们已经广泛地采用 gRPC 作为内部的 API 技术。但是,我们不太可能构建一个全新的基于 gRPC 的 memcached。memcached 的自定义协议很不错,并得到了客户端的良好支持。这种例外并不意味着采用 gRPC 是失败的。
对于其他一些情况,采用多种技术的成本(工程师的认知负担、运行旧系统的负担)太高,所以我们有必要彻底采用新技术。对于这样的项目,我们需要制定一个应对顽固派的计划,不同的情况需要采用不同的策略。长时间没有发生改动的系统可能需要使用代理,并逐步对其进行迁移。如果顽固派的存在是因为新系统缺乏必要的功能,那就需要增强新系统,或者对新系统进行封装,模拟旧系统的功能。
对于对旧系统产生了情感依恋的情况,进行面对面的沟通通常比高风险的公开辩论有效得多。请温柔些,如果你的新系统足够成功,总有一天它也会成为旧系统。
作为 Slack 的工程师和工程负责人,我们对彼此的期望是什么呢?
如果有疑问,请记住:你要对技术采用的成功与否负责,而从长远来看,这是由你的产品的用户来决定的。
领取专属 10元无门槛券
私享最新 技术干货