研发效能提升最佳实践的探索

GIAC(GLOBAL INTERNET ARCHITECTURE CONFERENCE)是长期关注互联网技术与架构的高可用架构技术社区和msup推出的,面向架构师、技术负责人及高端技术从业人员的年度技术架构大会,是中国地区规模最大的技术会议之一。

第六届GIAC,将从互联网架构最热门的前沿技术、技术管理、系统架构、大数据和人工智能、移动开发和语言、架构相关等领域,分享有典型代表的技术创新及研发实践的架构案例。

在团队协作专题,腾讯研发效能资深专家茹炳晟发表了题为《研发效能提升最佳实践的探索》的主题演讲。

研发效能提升最佳实践的探索

茹炳晟,TEG-基础架构部-研发效能中心专家工程师,业界知名实战派软件质量和研发工程效能专家,腾讯云最具价值专家TVP,中国商业联合会互联网应用技术委员会智库专家,畅销书《测试工程师全栈技术进阶与实践》和《高效自动化测试平台:设计与开发实战》作者,InfoQ极客时间《软件测试52讲-从小工到专家的实战心法》作者,曾参与DevOps能力成熟度模型国家标准的编写,也参与设计了DevOps企业教练的国际认证课程。

以下为演讲实录:

很荣幸受GIAC全球互联网架构大会的邀请担任了本届大会“测试前沿技术“的出品人,同时也受邀发表了研发效能提升的主题演讲。这里我把本次演讲的精华部分做了一个简单的梳理,希望能够给关注研发效能提升的同学带了启发和帮助。以下是主要内容回顾,欢迎大家拍砖。

研发效能提升最佳实践的探索

现代的软件行业已经不再是以前“大鱼吃小鱼“的时代了,而是转变成了”快鱼吃慢鱼“的时代。对于很多大型传统软件企业,原本“大“是其优势,现在却陷入了”大船难掉头“的尴尬。对于大量小而美的互联网软件项目,当创意和细分领域被确认之后,各大友商比拼的就是研发能力,具体来讲就是从需求转化成软件或者服务的能力,这其中研发效能的高低对于需求转化速率起到了至关重要的作用。同时,如何有效降低研发和运维的成本也是研发效能需要关注的重要课题,尤其是大型互联网项目,当某个环节哪怕只有少量优化的时候,由于其规模效应(比如集群规模,用户流量等)的放大作用,最终节省的成本也会是相当可观的。

研发效能提升最佳实践的探索

和敏捷的概念类似,到底什么是研发效能其实很难精确定义。其实很多复杂概念不是定义出来的,而是逐步演化出来的,是先有现象再找到合适的表述。要理解这类复杂的概念,最好的方法是理清发展脉络,回到历史中,回到诞生的时间,漫步一遍它的发展历程,才能真正理解其本质。但是由于时间关系,本次演讲我们没有足够的时间带着大家重走一遍历史,所以我准备先通过几个案例让大家能够先直观的感受一下“研发效能提升之美“。

研发效能提升最佳实践的探索

先来看第一个例子,很多时候我们在做产品原型设计的时候都需要借助产品原型工具来实现产品GUI界面的设计,以此作为沟通的基础去开展后续的工作。但是你会发现即使已经有了类似Axure和Modao等原型工具,但是“画界面“的成本依然很高。这里介绍一种可以将图片GUI设计稿,甚至是手画GUI设计稿转化成目标平台代码的一键自动化生成方案。

在上面的例子中,先手绘GUI界面设计,然后通过Sketch2Code可以直接转换成目标平台的代码,如果你指定的目标平台是Web,那就直接生成html,如果你指定的目标平台是iOS,那就会生成XCode的项目,通过编译打包后就可以直接在iPhone上安装执行了。这种方式的引入将大幅提升原型构建环节的效率。

研发效能提升最佳实践的探索

再来看第二例子。API接口测试过程中,输入参数临界值没有妥善处理的问题很常见,比如某个输入参数是String类型,但是代码实现中没有考虑String变量取值为NULL等情况。这类问题通常都会在后期API集成测试或者联调阶段才会集中被发现,此时发现再去修复的成本通常都会比较高,而且修复之后还要考虑回归测试的成本。所以我们可以引入一种机制,去主动扫描获取API输入参数的类型,然后根据参数类型生成容易出错的取值,用这些取值自动调用API,如果发生500错误或者抛异常就是发现了问题。(比如,对于String类型的输入参数就可以生成NULL,超长的字符串,包含非英语字符的字符串,SQL注入字符串等等。)进一步我们可以把这个方案和CI流水线集成,在CI执行过程中主动执行此类测试,以求问题更早地被暴露。

研发效能提升最佳实践的探索

上面两个例子都是由技术主导的。接下来的例子就和技术没有太大关系了,而是由流程主导的。上面图中厨师做三明治,左边图中由于各个食材摆放没有特定的顺序,造成厨师必须不断来回走动才能完成任务,而右边图中食材按使用顺序摆放,厨师可以站在原地轻松完成三明治的制作,大大节省了不必要的走动时间,从而大幅度提升了效率。由此可见,效率的提升既可以由技术来驱动,也可以由流程来驱动。

研发效能提升最佳实践的探索

看完了上面的例子,我想你已经对研发效能提升有了一个非常感性的认识了。接下来,我们来看一下研发效能的本质。如果要用一句话来总结研发效能的话,我会用“顺畅、高质量地持续交付有效价值的闭环“。解释一下其中几个关键概念:

  • 顺畅:价值的流动过程必须顺畅,没有阻碍

  • 高质量:如果质量不行,流动越快,死的也会越快

  • 持续:不能时断时续,小步快跑才是正道,不要憋大招

  • 有效价值:这是从需求层面来说的,你的交付物是不是真正解决了用户的本质问题。(关于本质问题我想多说一句,女生减肥不是本质问题,女生爱美才是,可以自己体会一下。)

  • 闭环:强调快速反馈的重要性

 在这个概念的引导下,我觉得五个持续(持续开发,持续集成,持续测试,持续交付和持续运维)是这个概念能够落地的必要实践。与此同时,我们还需要从流动速度,长期质量,客户价值以及数据驱动四个维度来对研发效能进行有效的度量。

研发效能提升最佳实践的探索

上面是从概念层面描述了研发效能,是不是感觉有点教条,其实我也觉得。所以下面我准备用通俗的例子来说说我对研发效能的理解。

左手边的图是所谓的“方*“效应。在前面使劲拉车的是老板,在后面使劲推车的是员工,老板关注的是大趋势和方向,是向前看的,很难发现车的*是方的,拉车的员工可能看到了方*,但是鉴于老板在前使劲拉,所以丝毫不敢停下脚步,只能硬着头皮使劲推。而在边上提议换个圆形*的同学被无情地忽略了,换个圆*的确要额外的停顿,殊不知那是为了让后面可以跑得更快更久。(题外话:突然脑中闪过一个酒店的slogan,知停而行)。你可能已经联想到了,这里的圆*其实就是工程效能。

 右手边的图根据事情的重要程度和紧迫程度分成了四个象限。我们这里只讨论A象限和B象限。A象限是重要但不紧迫,通常是一些基础性长期重要的事情,比如抢占市场的新产品规划,基础设施建设,流程优化,人才培养等,我喜欢把这个象限称为“未雨绸缪象限“。B象限是既重要又紧迫,通常是一些必须立马处理的事情,比如系统故障,线上缺陷修复等,我常把这个象限称为“救火象限“。 

理想情况下更多的时间占比应该放在“未雨绸缪象限“,少量的时间用于“救火象限“。

“未雨绸缪象限“做好了,“救火象限“事件的概率会变小。如果一个公司大部分时间在救火,通常说明这两个象限的时间分配失衡或者倒挂了,需要关注投资那些长期重要但不紧迫的事情。

对于软件研发而言,“未雨绸缪象限“中最重要的一环就是研发效能。

最后用一个更形象的例子做个比喻,相信大家都听过鹅生金蛋的故事。是不是鹅生的金蛋越多,效能就越高呢?其实不是,一味地让鹅全日午休地生金蛋早晚会把鹅累死,这不是可持续的长远战略。真正的效能应该是让鹅生鹅,鹅再生鹅,让更多的鹅一起来下金蛋。

研发效能提升最佳实践的探索

研发效能提升最佳实践的探索

腾讯TEG内部快速发展中的智研平台,阿里已经走向产品化的云效平台,百度基于工程效能白皮书来落地的效率云等等都是研发效能领域的标杆,可是你有没有想过,为什么最近几年各大行业龙头企业都纷纷开始在研发效能领域发力,而且步调如此一致,我认为背后的原因有以下这么三点:

  1. 就像“中台“概念一样,现在很多大企业的产品线非常广,其中存在大量重复的*,如果我们关注业务上的重复*,那么就是业务中台;如果我们关注数据建设上的重复*,那么就是数据中台;如果我们关注研发效能建设上的重复*,那就是研效平台,其实研效平台在某种程度上也可以称之为”研发效能中台“,其目标是实现企业级夸产品夸项目的研发能力复用,避免原来每条产品线都在做研发效能所必须的”0到1“,没人有精力去关注更有价值的”1到n“。现在的研效平台会统一来打造组织级别通用研发能力的最佳实践平台。

  2. 从商业视角来看,现在toC产品已经趋向饱和,过去大量闲置时间等待被APP填满的红利时代已经一去不复返了,以前业务发展极快,那么用烧钱的方式(粗放式研发,人海战术)换取更快的市场占有率达到赢家通吃是最佳选择,那个时代关心的是软件产品输出,研发的效率都可以用钱填上。而现在toC已经逐渐走向红海,同时研发的规模也比以往任何时候都要大,是时候要勒紧裤腰带过日子了,当开源(开源节流中的开源)遇到瓶颈了,节流就应该发挥作用。这个节流就是研发效能的提升,同样的资源,同样的时间来获得更多的产出。

  3. 从组织架构层面看,很有企业都存在“谷仓困局“,就像上面第二张图展示的,研发各个环节内部可能已经做了优化,但是光环节的协作可能就会有大量的流转与沟通成本,从而影响全局效率。基于流程优化,打破各个环节看不见的墙,去除不必要的等待,提升价值流动速度正是研发效能试图解决的一大类问题。

研发效能提升最佳实践的探索

这页Slides是从软件开发、测试和发布的视角罗列了各个阶段研发效能提升需要关注的问题。其主线是围绕CI/CD的一些列实践。由于篇幅原因,我这里就不一一展开了,只举几个例子让大家有个感性的认识。

  1. 可以通过All-in-one的开发环境降低每位开发人员开发环境准备的时间成本,同时又能保证开发环境的一致性。更高级的玩法是使用云端IDE,实现只要有浏览器就能改代码。

  2. 可以借助基于AI的代码提示插件,大幅度提升IDE中代码的开发效率。同样输入一段代码,不借助AI代码提示插件,需要敲击键盘200次,启用插件可能只需要50次键盘敲击。

  3. 代码的静态检查没有必要等到代码递交后由CI中的Sonar流程来发起,那个时候发现问题再修复为时已晚,完全可以通过Sonar Lint插件结合IDE实时发起本地的代码检查,有问题直接在IDE中提示,直接修复。

  4. 单元测试比较耗费时间,可以借助EvoSuite之类的工具降低单元测试的开发工作量。

  5. 对于规模较大的项目,每次修改后编译时间比较长。可以采用增量编译,甚至是分布式编译(Distcc和CCache)提升效率。

  6. 前端开发可以借助JRebel和Nodemon之类的工具使前端开发预览的体验更流畅。

  7. 选择适合项目的代码分支策略对提升效率也大有帮助。

  8. 构建高度自动化的CI和CD流水线将大幅提升价值的流转速率。

  9. 选择合适的发布策略也会对效能和风险之间的平衡起到积极的作用。比如架构相对简单,但是集群规模庞大,优选金丝雀,如果架构比较复杂,但是集群规模不是太大,可能蓝绿发布更占优势。

研发效能提升最佳实践的探索

从上面的描述我们可以看到,研发效能的提升涉及的面很广,既有基于技术的,也有基于流程的,那么在实际工程实践中,我们又该如何来落地研发效能提升呢?我主张的观点是“用MVP(Minimum Viable Product)的思想来提升研发效能“。

MVP这个概念来自于Eric Rise的《精益创业》一书,核心思想是是指以最低成本尽可能展现核心概念的产品策略,即是指用最快、最简明的方式建立一个可用的产品原型,这个原型要表达出你产品最终想要的效果,然后通过迭代来完善细节。

这个思想特别适用于研效平台的建设,我们必须在识别出待解决的研效问题之后,先给出最简单的解决方案,然后在后面的实践中不断优化和迭代,如果我们试图关起门来打造一个研效平台,指望等所有功能都完美了再推给业务线团队使用,那必然是死路一条。

研发效能提升最佳实践的探索

还有必要特别指出一下MVP的常见误区。实现了某一个功能但是暂时对客户没有实际价值,而要等后面功能出来后才能对客户有用,这个不是MVP。MVP追求的是“麻雀虽小五脏俱全“,也就是实现的功能点可以很小,可以比较简陋,但是对客户有价值是必需的。用上图的两个三角形来说的话,”横切“不是MVP,”竖切“才是MVP。

所以放到研发效能这个领域,我们要保证我们的做的研效工具一定是能解决实际痛点的,虽然一开始的方法可以比较简陋。从产品的视角来看,研发平台本身和一般的软件产品没有本质区别,也需要不断迭代和持续改进。

研发效能提升最佳实践的探索

这里开始是本次分享最硬核的部分,这也是我自己对如何推行研发效能提升的一个阶段性总结。

常有人问我说,你之前主导的研效提升项目都获得了成功,如果请你过来,几年可以做好?这个其实是一个无解的问题。一定程度上,投入大,周期就会短,但是,实施周期不会因为投入无限大而无限变短。我们可以避开很多曾经踩过的坑,尽量少走弯路,但是,适合自己的路子还是要靠自己走出来,拔苗助长只会损害长期利益,买了一辆跑车,你就能成为赛车手吗?鉴于此,我结合自己缴过的学费、踩过的坑总结了上图中的8个建议供大家参考。接下来我会挨个做解读。

研发效能提升最佳实践的探索

 第一点是“从痛点入手“。很多时候,当我们手上拿着锤子的时候,看什么都像钉子。但是研发效能提升恰好是反过来了,我们要先找到哪些是最碍眼的钉子,然后用体系化的方法论去打造合适的锤子。

所以在推行研发效能的早期阶段,我们通常会采用自下而上的策略,从一个个工程实践中的实际痛点(钉子)入手,从解决问题的角度打造研效提升的亮点,此时我们追求的是”短平快“,问题点逐个击破的原则。比如下面这些场景:

  • 本地编译耗时长:提供增量编译和分布式编译能力

  • 本地测试困难,测试环境准备复杂且耗时:基于K8S的Pod提供一键搭建测试环境的能力

  • 自动化测试用例数量大,执行回归时间过长:采用并发测试用例执行机制,使用几百几千台测试执行机并行执行用例,实现用硬件资源换时间

  • 自动化测试用例维护成本高:测试用例采用模块化和分层体系,实现低成本的自动化用例维护

  • 测试数据准备困难:引入统一测试数据服务(Test Data Service)能力

  • 研发后期阶段,代码递交集中,缺陷井喷:推行测试左移,鼓励研发自测,推行”谁开发,谁测试,谁上线,谁Oncall“

  • 性能缺陷在研发后期发现,修复重测成本高居不下:从性能测试转变为性能工程,让性能融入软件研发的各个环节,而不是最后的一锤子买卖

  • 安全问题频现:将安全测试能力纳入研发的全生命周期,实现DevSecOps,而不是早期的SDL

  • 集群规模庞大,发布过程耗时过长:各个层级的并发部署能力,集群内节点的并发,集群间的并发等

  • 项目的过程数据都是后期集中填充,失去度量意义:项目过程数据由工具自动填充,不再依赖工程师手工输入。比如开发完成时间不再依赖于开发人员手工填写,而是由Jenkins构建完成后自动填写,以保证所有过程数据的真实有效性,从而为后面的度量和改进提供可靠的信息输入。

研发效能提升最佳实践的探索

第二条是“从全局切入“。很多时候我们会尝试去优化某个具体的环节,而忽略了全局优化的可能。

 举个例子,我们去医院看病,通常是挂号排队半小时,实际挂号可能就两分钟,接下来又是漫长的排队等待等待医生就诊,好不容易排到了进去可能不到五分钟就被要求去验血…。整个过程中实际有效时间的占比很小。如果这个时候我们还试图去优化挂号本身的时间,而不去关注优化各个环节的等待时间显然是错误的方向,所以效率提升既要关注单个步骤的优化,也要专注减少步骤与步骤之间的无用等待。这一点体检中心就比公立医院做的好太多了,你很少会见到体检中心每个科室门口都大排长龙的情景,因为体检中心出于经济利益的考虑会关注吞吐量,会通过全局排队调度优化来实现更高的盈利。

回到软件研发领域,你会发现类似上面医院这种不合理的排队现象随处可见,比如软件缺陷的流转,软件需求的实现与交付,软件制品包发布等待等等。这些也是研发效能提升需要重点关注的领域,需要从全局理清楚全流程,识别出等待浪费的时间,通过流程再造与优化实现全局效率提升。

研发效能提升最佳实践的探索

第三条是“用户获益“。对于研效提升,有一点我们必须牢记,那就是成功的标准不是研发效能平台的成功,而是客户成功。只有客户获益才是检验研效项目成功的唯一标准。这里我谈以下三点:

伪需求:伪需求是指研团队自己臆想出来的,是属于典型的“手里拿着锤子,看什么都像钉子”的典型案例。那么如何识别伪需求呢?识别标准其实很简单,就看客户是不是愿意和你分摊成本,如果业务线已经开始做了,或者想要开始做,那就说明那是业务线的刚需,如果研效平台能帮助提供方案,那研效平台的接入就是水到渠成的事情。我就见到过很多这类刚需的例子,比如微服务架构下集成测试环境的搭建就是其中的典型。 

结构问题:著名商业顾问刘润说过“结构不对,什么都不对“。比如两个和尚分粥的故事想必大家都听过,一碗粥两个和尚要均分,但是分粥的和尚总想多喝点粥,那怎么才能做到无监管情况下的公平呢?教育分粥的和尚说出家人“以少吃为怀”吗,显然一旦没有了监管,他就会给自己多分点,解决这个问题的最好办法就是一个和尚分粥,另一个和尚选粥,那么这个*就决定了分粥的均匀性。所以好的策略是承认每个人都是自私的,但是你的策略能够在人人都是自私的基础上获得全局利益的最大化,如果你的全局利益最大化是建立在要求每个人都是大公无私的,那就是失败的设计,因为这必然会导致失败。回到研效提升这个问题上,我们必须抱着”不是我们的研效平台有多好,而是业务线用了以后有什么提升“来定位自己,才能从结构上获得成功的筹码。

服务意识:理解了上面的观点,理解服务意识就很自然了。在研效平台落地过程中我们需要和业务线互助实现双赢,业务线收获现成可用的方案,研效平台收获最佳实践的沉淀,这些最佳实践的沉淀是至关重要的,为后期的批量成功复制提供了技术基础。

另外还有一个小经验可以和大家分享,有时候为了让研效平台尽快能够在业务线落地,让业务线愿意成为我们的研效平台的试验田,我们有时还必须能承担起主动背锅的义务,这点如果大家感兴趣也可以和我私下交流。

研发效能提升最佳实践的探索

持续改进是研效平台自身发展的必经之路。很多问题的解决在一开始的时候,我们关注的是如何快速简单地解决问题,但是当规模起来之后,我们还更需要关注解决方案的普适性和通用性。如果一开始就试图寻找完美方案,必然会让得不偿失。

这里举个具体的例子,比如我们需要在Jenkins中通过hook机制去触发一些操作(比如代码静态扫描,单元测试等),最简单的做法就是在hook中实现操作的具体步骤,这种实现在一开始效率很高,也非常容易实现,但却不是最优的方案,因为hook中的代码只会被执行一次,而且hook越来越多以后,各种实现都散落在各个地方,难以维护,同时但凡有新的需要(比如要加入慢SQL扫描),都需要改hook实现,而且这种做法也违背了IaC(Infrastructure as Code)原则。

更好的做法是引入研发效能的消息中心(MQ)通过下游操作的订阅模式来实现未来的可扩展性。但是如果你从一开始就是建MQ,实现的难度和成本都会大增,业务线有可能就等不及你的方案,从而研效提升就无法如期落地。所以我的观点是研效落地可以遵循“先圈地,后改进“的策略。

研发效能提升最佳实践的探索

这页Slides说的是研发效能提升的落地,光靠自下往上和光靠自上往下都是行不通的,而是应该双管齐下,两边从中间挤才是切实可行的方案,由于篇幅原因,这里就不详细展开了。

研发效能提升最佳实践的探索

这里我提出来两个概念:“唱戏的“和”搭台的“。刚开始做研发效能的时候,我们既是搭台的又是唱戏的,在研平台(搭台)的基础上提供各业务线的解决方案(唱戏),但是当业务线接入规模不断扩大的时候,各个垂直领域的多样化需求越来越多,此时我们已经很难应对各家的个性化非通用需求了(每家要唱的戏都不同),所以此时研效平台的开放能力就成为了关键,研效平台的建设必须能够应对这种多样性,研效平台的职责转变成搭建规范的平台,让业务线能够在此平台上实现各自的个性化需求,所以研效平台本身的技术架构设计必须考虑可扩展性和灵活性。

 举个例子,平台就是Jenkins,灵活性就是上面各种plugin。

研发效能提升最佳实践的探索

掩耳盗铃是我们在落地研效过程中经常会犯的错误。上图给出了研发效能的“最差实践“,你可以心里默默数数被砸中几条。

研发效能提升最佳实践的探索

另一种掩耳盗铃的例子是普遍采用虚荣性指标来做度量效能。那到底什么是虚荣性指标呢?虚荣性指标是指那些不能直接用来指导后续行动的指标,我们需要的是可以指导我们行动的可执行指标。这么说还是比较抽象,我举几个例子你就很容易明白了。 

  • “接入Sonar的工程数“就是虚荣性指标,与之对应的可执行指标是” Sonar问题的增长趋势“和” Sonar问题的修复时长“;

  • “系统用户数“就是虚荣性指标,与之对应的可执行指标是” DAU单日活跃用户数“和” MAU月活跃用户数“;

  • “接入研效平台的项目数“就是虚荣性指标,与之对应的可执行指标是”百分之多少的项目使用过研效平台来完成开发测试和发布流程的;

我们需要的是雪中送炭,而不是锦上添花。

研发效能提升最佳实践的探索

最后一点大家都容易理解“做自己研效平台的第一个用户“,研效平台本身的研发必须通过自己的平台走,这样才能站在用户的角度看待自己的方案,才能和业务线用户”共情“。

研发效能提升最佳实践的探索

最后是对研发效能行业未来发展方向的展望,由于篇幅原因就不再一一展开阐述了,我后续计划会专门写篇文章来谈谈这块的内容,敬请期待吧! 

推荐一些衍生阅读,其中《测试工程师全栈技术进阶与实践》和《高效自动化测试平台设计与开发实战》分别是我2019年和2020年写的书,主要关注在软件测试效能的提升上,同时也推荐朱少民教授的《全程软件测试(第3版)》。

研发效能提升最佳实践的探索

预热一下我和吴骏龙老师正在写的《软件研发效能提升之美》,如果一切顺利会在2021年和大家见面。

后台回复关键词【GIAC】可获取本次大会嘉宾PPT。