小编有话说
市场的变幻,政策的完善,技术的革新……种种因素让我们面对太多的挑战,这仍需我们不断探索、克服。
今年,网易数帆将持续推出新栏目「金融专家说」「技术专家说」「产品专家说」等,聚集数帆及合作伙伴的数字化转型专家天团,聚焦大数据、云原生、人工智能等科创领域,带来深度技术解读及其在各行业落地应用等一系列知识分享,为企业数字化转型成功提供有价值的参考。
今天是第4期,由网易研发效能技术专家于旭东和大家分享研发效能改进实践,如自动化基础设施、降低规模加快流动、打破筒仓自主发布、持续快速质量反馈、产品学习、团队协同、持续改善等实践活动。
基于这些实践活动,网易数帆提供敏捷研发平台,助力业务提升研发效能。
01 自动化基础设施
在研发过程中,无论是开发自测,测试验收,无论是手工测试还是自动化测试等,都依赖测试环境,环境是整个交付流水线的基础。尤其在微服务架构下,随着应用数量的持续增加,一个完整的环境往往意味着成百上千个应用的组合。
另一方面针对某一个需求,需要修改的应用代码往往是有限的,通常就是1~2个应用。仅仅修改了一两个应用,为了测试需要搭一个完整的环境,而完整的测试环境却需要成百上千个应用,臣妾做不到啊。这对于原来手工、静态维护环境的方式带来了巨大的挑战:
- 不能:新人学习成本极高,需要了解框架以及开发&PE支持
- 时间成本高:重新搭建一套环境需要较长的时间,平均约8个小时
- 环境竞争:搭建成本高,静态环境,导致环境争抢,频繁切换部署应用分支
- 环境不稳定:环境无“复位”,测试结果不可靠
- 机器成本高:静态方式使用机器,利用率不高
- 不透明:哪些环境?多少机器?哪些应用?什么分支?什么状态?
从研发个人角度看,我在浪费生命,幸福感极低;从组织的角度看,研发时间没有花在刀刃上,浪费巨大(从精益的角度上看没有直接产生客户价值的活动称为浪费)。
微服务架构下自动化环境管理解决方案是在基准回归环境的基础上,根据版本或需求涉及到的应用,可以动态按需搭建各自的测试环境,包括申请机器,构建部署相关应用,修改Nginx等。各个测试环境的基础服务依赖于基准环境,而彼此之间是隔离的。由于在不同环境里存在同一应用的多个实例,技术上需要解决各个测试环境间服务调用隔离:1、同步调用,如RPC,REST接口等;2、异步调用,如kafka消息等。
在自动化环境管理的支撑下,研发团队从最初静态环境争抢中解脱出来,可以按需自动化的创建环境,分分钟就可拥有一个可用的测试环境,大大提高了研发人员的效率和幸福感,同时为持续交付奠定了基础。
需求规模往往是一个组织需求交付周期的指证性指标。如下图(系统思考中的CLD图)所示需求规模越大,研发周期越长,交付周期越长。交付周期越长则加剧了产品经理需求上不了车的恐惧(如果这次计划中没有安排上,下一次可能就是很久之后了),这导致产品经理在需求计划排期的时候增加需求的冲动,进而导致需求规模变大,这是一个增强的恶性循环。另一方面交付周期变长,期间的变化增多,进而进一步加长了研发周期,这是另一个增强的恶性循环。
当然交付周期不可能无限延长。显性的原因是交付周期延长,将导致客户满意度降低,反过来客户满意度降低会增加产品生存压力,进而促进企业采取措施缩短交付周期,这样在客户满意度和交付周期之间形成一个平衡回路。隐性的原因是交付周期延长,将降低产品收入,延长产品学习周期,这都会增加产品的生存压力,进而促进企业采取措施缩短交付周期,这样也形成一个平衡回路。
需求规模取决于两个因素:需求批量和需求大小,这也是改进的关键点。我们在不需要大幅度改变现有流程的情况下,可以通过降低需求批量和需求大小,增加需求的流动效率,降低需求的交付周期。曾经辅导过的一个团队降低需求规模之后,发布频率从原来的固定2周1次提升到1天多次。当然将一个大需求拆分成多个独立的,可测试的,有价值的,合适大小的需求,是一个技术活,需要不断的练习。
也许你会说“为什么自找麻烦?我们的客户不需要每周发布。”我们需要需要知道短周期带来的“湖水和岩石效应”。这是一个比喻,湖水深度代表需求规模,周期长度等,当水位很高的时候,很多岩石(代表组织的弱点或者说低效点)就被覆盖了,形不成改进的动力。当水位变低,这些岩石就会暴露出来,组织无法接受每个短周期内都会遇到同样的问题,进而推动改变的发生。
比如曾经辅导的一个团队,在2周交付周期时可以忍受花费8个小时搭建一套测试环境测试本周期内计划交付的需求,但无法接受线上Hotfix时花费同样的时间搭建测试环境,因为通常是修改代码1小时,环境4小时,测试1小时,发布1小时,价值效率极低(1/7,约14%)。
传统研发模式下,开发完成代码编写,提交工单到运维,运维根据工单选择合适时间部署发布,通常有固定的发布日,此时发布的人力成本,时间成本,协调成本都很高。这里存在的一个冲突是从产品学习的角度看开发希望更快更频繁的发布到线上,进而加快产品的学习。
另一方面从系统稳定的角度看运维希望线上发布的频率低一点,慢一点。需求交付的频率往往限制组织响应变化的灵活性。从组织整体上看我们希望更快更频繁更有质量的发布,从而更快更频繁的收集客户反馈进行产品学习。
为此我们需要面向用户,打破职能筒仓,转换运维研发职责意识,从运维集中发布模式转向研发按需自行发布模式。
正如亚马逊CTO所说:“You build it,You run it。”这样的模式转变依赖于应用标准化建设,端到端交付流水线标准化自动化建设以及高效的质量保证活动,降低发布成本以及发布风险。模式转换完成后,团队的发布频率将有10倍速提升。
在发布职责从运维转到研发以及发布频率增加的情况下,对质量保证工作提出了更高的要求。一方面我们希望在需求的交付过程中能够做到尽早快速的质量反馈。另一方面在频繁的发布过程我们希望降低质量保证的成本,让单次需求发布的成本降下来,加快需求流动。
1)实例化需求
最早发现缺陷的地方应该是需求阶段。Gojko Adzic曾经在《实例化需求》这本书里写到:“在过去的十年里,软件开发社区致力于使用正确的方式构建软件,关注使用技术实践和思想来确保质量。但是,正确的构建软件和构建正确的产品是两码事,我们要二者兼顾才能取得成功。
”曾经做过一个调查分析,把所有的内部缺陷分成三类:需求遗漏错误,需求理解错误,需求实现错误,结果是将近70%的错误是前两类需求错误。实例化需求的目标是以终为始,避免前两类错误。开始开发之前,业务方,开发,测试三个火枪手在一起充分讨论澄清需求。
业务方由需求文档传递需求方式转变为需求讨论,开发可以学习领域知识共同设计产品,测试人员可以获得他们需要的第一手只是,也可以通过在讨论中建议某些重要的场景例子来影响开发和业务方。这里多说一句,实例化需求可以帮助测试从后置的发现实现问题转变为前置的预防问题,这是可以充分利用测试技能产生增值的地方。
通过实例明确需求的验收标准,容易发现理解不一致的地方,并保证相关人员对需求的理解是一致的。这些实例后续转化为测试用例,最后通过这些测试用例验收需求是否完成。如果更进一步,可以直接将这些测试用例转成自动化测试用例用于持续集成,加快质量反馈。
曾经遇到过一个以为简单并且已经代码实现完成的需求,我拉了对应的产品经理,开发,测试一起使用实例化的方式再次梳理了一下需求,结果是:产品经理遗漏了部分业务场景,开发部分功能可解实现错误,根本不需要测试,重新写代码。
发现缺陷最好的时候是当缺陷被引入的时候。缺陷被发现的越早,修复的成本就越小,浪费也就越少。实例化需求实践帮助我们发现需求引入的缺陷,持续集成实践帮助我们发现代码引入的缺陷。对于规模较大的研发团队通常需要建立多层次的质量反馈机制。
o 结对编程/Mob编程:两者都可以在编写代码的过程中提供代码质量的反馈。相比于结对编程,Mob编程引入了更多的角色一起合作完成需求的编写,测试以及上线。曾经做过一个对比两个差不多的需求,一个采用Mob编程的方式(开发,测试以及产品一起现场编程测试验收),一个采用传统的方式,开发独自完成代码的编写,提交测试,产品经理最后验收,结果是Mob编程2小时候结束后需求发布上线,另外一边花了一天的时间第二天提测后好几处的问题需要进一步修改。
o 代码层面:代码提交到中央仓库触发,静态代码扫描,单元测试,安全扫描,JAR包扫描等不依赖于测试环境的快速测试,反馈代码质量;
o 需求层面:代码部署到测试环境触发,与该需求相关的接口自动化测试,反馈需求实现质量;
o 产品层面:代码合并Master分支部署到回归环境触发,与该产品相关的接口自动化测试,反馈待上线产品质量;
o 线上发布:应用发布上线时触发,线上快速接口自动化测试,反馈当前发布的线上产品质量;
o 线上巡检:自动化定时触发,通常是执行时间比较长的自动化测试,尽量降低当天的发布对线上产品质量的影响。
曾经辅导的一个团队在开发编写代码的同时测试人员完成接口自动化测试代码开发,结合持续集成,开发提测时保证持续集成结果通过,极大的提升了产品质量,缩短了开发测试周期比,从原先的1:1到4:1。
持续集成依赖于完善的自动化体系建设,分支管理策略等,是一个复杂的技术实践,需要付出艰苦的努力才能看到效果。
成功的实现一个对客户毫无价值的产品是产品失败的致命原因。做实例化需求辅导的时候经常有人问我通过实例化需求可以保证做出正确的产品么?实例化需求期望保证的是业务,开发,测试三个火枪手对产品的需求设计理解是一致的,可以降低做错误产品的可能性,但并不能保证此时达成一致理解的产品需求是正确的(对客户有价值),这是两码事情。
Brooks在《没有银弹》这篇论文里写到,软件开发的本质是复杂的,其中最难的不是产品代码的实现,而是对产品概念和逻辑的验证。在真正的将产品交给用户得到反馈之前,一切对产品的判断,对客户价值的判断都是假设,对客户的每一次产品交付可以被视为一次产品实验:在一个清晰的假设前提下,预测将要发生的事情,埋点并采集实验的数据,交付后分析实验的结果,完成一次经验证的学习。
研发效能的本质上并不在于我们开发交付了多少产品特性,而在于我们的努力换来了多少经证实的认知,交付了多少的客户价值。前面我们有一个指标是产品学习周期,我们的目标是以最大的速度加速产品认知学习。
这里有几个实践:
1、埋点,通过埋点构建产品实验需要的数据;
2、ABTest,通过ABTest方法来验证不同的想法;
3、产品需求价值回顾,需求上线之后通过复盘产品数据,验证实验假设,完成产品学习,并据此调整下一阶段的产品需求。
组件团队是在大型产品研发中组织研发人员的一个比较常见的方式:程序员围绕系统组件组织团队。在此组织模式下需求涉及到多个组件团队时,需求拆分为组件任务,由对应的组件团队开发,这通常会产生以下一些影响:
- 组件团队缺少产品整体视角,关注组件交付而非需求的交付;常见的句式是:“我的任务做完了”。
- 组件团队通常资源共享,关注资源效率,而非价值交付效率。当一个组件团队服务多个业务方的时候,往往容易导致组件团队陷入公共绿地的困境,各个业务方拼命争夺组件团队资源,在整体信息沟通不顺畅的时候,一个潜在的结果是最会哭最会喊的那个业务方需求获得了资源,而不是对于公司或客户最有价值的业务方需求获得。
- 组件团队组织产品研发时也会采用项目制开发模式,从各个组件团队抽调资源,组建短期项目团队。不同的项目负责人,不同的团队成员,不同的做事风格,不同的项目复杂度,不同的完成标准,不否认有非常牛X的项目负责人带领非常牛X的团队完成非常牛X的项目。但整体上看,往往整个项目进度,质量,效率不稳定可控。同时在短期的项目团队里,人往往被视作实现项目目标的一个资源,成员工作动力不足,高效的团队是需要长时间磨合的。
- 项目制方式加上关注资源效率,通常产生的一个现象是团队/个人多任务并行。适当的并行可以提高团队的吞吐量,但同时会延长需求交付周期。当并行超出某一个限度的时候往往会导致整体效率下降。
- 跨组件团队沟通时需要非常清晰明确的公司策略,产品优先级等信息支持,才能更好的协调多个团队协作开发。但现实的情况往往是整个信息不够透明。另一方面团队都会有自己的屁股,有做大做强自己组件的冲动,往往导致跨团队沟通协调成本高。在沟通协调不顺畅的情况下,往往会产生强烈的项目管理需求。曾见过比较极端的case,一个人半天代码量的需求,前前后后花费了不同团队10个人讨论了3天(周期时间而不是实际讨论花费的时间),最后在外力(某团队负责人)的介入下才拍板。
- 客户价值匹配组件团队技能,而非团队技能匹配客户价值;当某一组件需求集中涌现的时候,容易产生扩大团队的冲动;当某一组件团队高优先级需求不足的时候,并不会缩小团队规模,后果是不断扩大的组件团队;在某些组织里经常会看到组织调整,一个原因就是不断扩大的组件团队,导致研发成本不断攀升,但研发成本攀升的同时并没有实现同等客户价值价值交付,投入产出比降低,所以需要动一动,也算是一种应对的方式,只是这种变化通常更剧烈一些。
- 当需求被拆分到各个组件团队后,带来的另外一个后果是后期集中集成,集中测试,反馈周期往往拉长,并且将风险留在最后,往往导致项目延期,交付周期变长。
另一方组织方式是特性团队,特性团队是:
- 长期稳定存在,长期的合作利于打磨高效团队,质量和效率稳定可预见。
- 跨职能,团队成员技能中包含前端,开发,测试等多种技能。
- 跨组件,团队覆盖的范围同时横跨多个组件。
- 团队能独立完成客户价值交付。
- 团队间协调合作从项目管理域转移到代码技术域,代码通常要比人简单些。
整体上特性团队对外更加关注客户价值价值,促进创新;对内打破团队边界,促进组织转型升级;对个人促进个人学习,提升个人技能。当然特性团队也带来了一些挑战:
- 每个人都需要掌握所有东西?不是的,而是整个团队需要掌握产品交付的所有技能,并在需求开发过程中不断学习扩大个人技能领域,这是一个长期的过程,取决于团队学习的能力。BTW:在现在以及未来的千变万化的社会中,无论是个人还是团队,学习能力将是一个非常重要的能力。
- 如何保证组件代码质量?需要工程实践上的配合,例如主干开发,持续集成,保证产品不被破坏;组件守护者,review组件相关修改,技能指导;不同人从产品交付的角度修改组件促进代码学习以及程序员社交。
特性团队往往会涉及到组织结构调整,是变革的深水区。
客户,市场,产品,研发以及组织本身是一个复杂系统。根据Snowden和Boone的Cynefin框架,在复杂系统中不可预测的成分大于可预测的成分,很难事先定义一个所谓正确的或最佳的方案。最适合的方法也许是:探索-感知-响应,这是一个经验主义过程。
在经验主义过程中,有三大支柱:透明,检验和适应。透明意味着相关人能看到过程中影响结果的方方面面。过程中的各方面必须做到经常性的检验,以确保及时发现过程中的重大偏差。如果发现过程中的一个或多个方面超出可接受范围,或者最终产品无法被接受,那么就必须进行调整。这是一个持续循环的过程。没有所谓的最佳实践,有的仅仅是合适的实践,合适的实践一定是工作在一定的场景里。
系统永远是动态变化的,并没有所谓的银弹可以一劳永逸的解决所有问题。重要的是建立全员能够持续关注提升变化响应能力,缩短交付周期,提高质量和客户价值的持续改善文化。这样我们可以不断的从一个状态进化到另一个状态。丰田体系概念的创导人大野耐一写到:“有一些事情称之为标准工作,但是标准是不断变化的。相反,如果你认为这些标准工作对你来说已经是最好的,那么一切都结束了。”无论如何,持续改善都是一个值得尝试的实践活动。
研发效能实践是一个复杂的系统活动,没有哪一个所谓最佳实践像描述的那样百分之百适合你的组织。我们只能拿我们认为可能产生影响的实践来驱动这个系统,然后静观其变。所有这些实践,也许是一个好的开始,但都需要对它做适当调整,使其更准确的适应于独一无二的组织情况,人员情况以及行业情况。
只有正确的创造活动才能帮助团队找到正确的适合他们的研发过程。当然还有很多的方法和实践,以上仅仅浮光掠影的简单聊了一些,希望是抛个砖,引个玉,如果能够引起你的一点点思考,也就足够了。
专家简介
于旭东 研发效能技术专家,网易云音乐敏捷教练。