聊一聊在阿里做了 8 年研发后,我对打造大型工程研发团队的再思考

(里程碑管理)

里程碑是宏观层面比较重要的一个工具,我们主要靠它来设定方向、框定产品大图。如果没有里程碑设计的话,我们很容易突然迷失方向,陷入各种日常需求和问题中。

我们一般会把里程碑做得很大,或者说设计得很远。比如,未来两年一个比较粗的时间点要完成的事情都放入里程碑管理。

我们 Erda 设计的里程碑,大概就是这个样子:

前面我们提到了里程碑工具,要想支撑里程碑的完成,还得靠日常的具体需求和问题,这里先一起聊聊需求。实际观察下来,很多开发同学其实不懂什么是真正的需求,也不懂如何接需求。

下面举个例子。

需求方:Erda 能不能支持从 Excel 中导入数据?(初一听,这确实是个需求,就是要支持从 Excel 这种很常见的文件里导入数据。稍微思考多一点的同学,就可以继续追问。)开发:为什么要从 Excel 导入数据,具体的场景是什么?需求方:Excel 表格上填写这些数据很方,我习惯先在表格上把这些工作做好,再导入进 Erda。

追问到这里,其实已经能够发现。需求方的真正的痛点是 Erda 这个功能不如 Excel 方便好用,导致用户绕了一个弯路。所以,我们真正要做的需求是优先解决这个不好用的痛点。(至于有些人就是要这个功能,那是我们另外要讨论的事情了。)

最常见的需求就是,能不能加个 XX 功能。(这里大家可以细品一下。)

综上,我们要求产品和开发同学对于任何需求都要不断思考,多追问几个为什么,拿到用户最原始的需求。始终要记住,用户给你的极有可能是他认为的方案,而不是原始需求。

需求管理对了,后面的开发才会少走弯路,需求是起点、是根本。

迭代队列

(迭代管理)

那么,这个队列为什么是迭代队列,而不直接设计成需求队列,开发直接取需求而不是取迭代呢?

需求队列会存在两个很大的问题:

  • 第一,迭代是用来严格定义一个版本的时间周期,如果没有迭代,版本的时间周期节奏会变得很乱,会进入一种比较随意的状态。

  • 第二,当前实际开发中的需求如果要延期解决的话,这个延期的需求重新排到哪里去?难道重新放到需求队列的末尾吗?放到末尾显然不合适。如果是迭代,就可以严格规定放到下一个迭代或者下下一个迭代。

开发过程

(需求任务管理)

除了关键指标以外,开发过程的管理,主要是基于任务来协同的,每个需求在开发前都已经被拆分成了合理的任务,也就是说一个需求会关联完成这个需求的所有任务,开发同学只需要每天按照优先级完成,并及时更新反馈任务的情况和进度即可。(这里提到了及时反馈,反馈又是一个异步工作的关键机制。)

很多研发主管都喜欢有事没事在钉钉、微信里询问一下具体的工作进度,或者拉个会议对一下进度,所以 “已读 + ding 一下“ 对他们来说是一个很好的功能。我们非常不鼓励这种依赖即时通信工具或会议的方式来沟通、了解开发进度,这种方式非常同步,就和同步调用一样。正确的做法,应该是开发同学每天根据自己的情况及时在项目管理工具对自己的任务进行进度更新和总结反馈,研发主管自己按需关注任务的研发进度和情况,彼此没事不要相互打扰。

CI 流程

在今年年初我们决定将 Erda 开源后,就把整个团队的日常迭代开发全部转移到 GitHub 上执行了,因此 CI 主要是基于 GitHub 的 Action 来做的,会把常规性的检查任务全部放到 CI 中来完成,比如:单元测试、代码质量检查、规范等。这个部分比较常规,没有什么特别的。但 GitHub Action 太慢了,我们后续计要把 GitHub Action 迁移到 Erda 的 CI,这样我们可以实现 CI 并发更高、跑得更快、效率更高。

本地+云端

一个很大的产品就是一个很大的软件工程,这样大的工程要完全放到个人笔记本电脑上进行本地调试开发,是一件难度不小的事情。就像一个中间件、一个框架、一个 webserver 等,都可以很轻松地放到本地电脑上开发调试,但要把整个淘宝装到本地电脑就有点为难了,当然我们也正在向这个方向努力。

在不能完全将整个 Erda 轻装到本地电脑前,我们采用了本地 + 云端联合的方式来进行开发调试。云端本身是一个已经部署好的 Erda 全平台开发环境,包含所有能够正常工作的组件;然后使用 telepresence 打通本地和云端 K8s 之间的网络:

  • 本地可以直接使用 K8s 容器网络内的 DNS,同时支持短域名的 search 机制。

  • 本地启动一个服务,劫持 (intercept)云端 K8s 集群内的 Pod,当 K8s 集群内其他服务访问该 Pod 时,流量会转发到本地。

  • 实现将云端 K8s 集群 Pod 中的环境变量全部自动导出到本地。

  • 实现将云端 K8s 集群 Pod 中挂载的 volume 通过 sshfs 映射到本地的文件系统。

简而言之,本地起一个服务,可以随意访问 K8s 集群内的任意 service;同时,本地的服务也能被 K8s 集群里的其他服务访问到。这样一来,确实可以大幅度提高开发调试效率,开发人员不用在复杂环境上来来回回的折腾。

集成环境

虽然 Erda 给上层的业务应用提供了很强大的持续集成、部署和运维监控等能力,但 Erda 在很长一段时间内却不能通过自己部署自己,也就是不能实现 Erda On Erda,所以那段时间一直没有真正的自动化集成环境,研发质量和效率也不太高。

由于 Erda 整个工程项目比较庞大,代码从构建到部署更新,再加上所有的自动化测试跑一遍,整个流程需要数小时,耗费时间长。所以,我们的集成环境主要采用每天夜间定时运行自动化集成 + 测试,次日上班就可以看到集成结果。集成出来的错误结果,当天内必须 fix 掉,这是持续保证集成效果的关键。

API 设计和自动化测试

集成环境能够有效工作的关键是什么呢?很显然,必定是自动化测试了。

自动化测试分为自动化的单元测试、接口测试、性能测试、安全测试、UI 测试等等。日常开发过程中,效率影响最大,最频繁的显然是单元测试、接口测试、UI 测试。

  • 单元测试比较简单,我们放到了 CI 流程中,每一个 PR 就驱动完成了单元测试。

  • 接口测试非常关键,我们需要覆盖那些全链路场景的接口,从最顶层的接口出发完成整个系统的功能自动化测试,所以接口的自动化测试就放到了整个集成环境中完成,因为集成环境有最新、最稳定的代码,以及异步执行等优势。

  • UI 的自动化测试成本相对比较高,我们目前还在尝试阶段,没有完全达到成熟。我一直希望从智能测试的角度,用 AI 算法的思路去解决 UI 的自动化测试。

这里先介绍一下接口测试。接口就是 API,要想编写出好的接口测试用例,必须得先有 API 的设计。API 的设计从哪里来呢?我们当然不希望从开发工程师的口中来,所以自研了 API 管理平台,从 API 的设计到测试进行全覆盖。开发工程师在完成需求前,首先在平台上完成 API 的设计工作;然后将 API 的设计和需求关联上,这样一来,测试工程师就自主从需求里获取到具体的 API 信息,完成接口测试用例的编写。

(基于场景的自动化自动化测试流程)

手工测试

有了自动化测试,为什么还需要手工测试?手工测试显得似乎没有那么高级了。

对于没有前端 UI 的系统,自动化掉所有的测试理论上是可行的;一个有着复杂前端 UI 的系统,自动化起来还是会有很多难点,大多数做 UI 自动化的,基本也都是集中在几个核心的流程上,很难覆盖边边角角的全部场景。

在专业测试工程师眼里,手工测试也是很重要的一部分,需要有工具、有方法来支撑的。每一个版本,手工测试用例也是要能够被回归的,因此这些手工用例也要被记录下来。

(答疑问题管理)

项目的工单列表在每周五需要进行 Review,将那些比较简单、能够快速解决的工单问题梳理出来,然后一键复制到迭代队列中。这里有两个很关键的点:

  1. Review 先挑选的是那些简单的、能快速解决的问题。

  2. 放入到迭代队列,而不是需求池。

软件系统的 bug 总是解决一个少一个,越跑越稳定,所以简单的问题要快速解决、0 容忍对待。难的问题需要专项对待、专项解决,不对的时间节点或者资源有限的情况去死磕难题,大概率不是一个好想法。

筛选出来的工单问题千万不要放到需求池中,一定要直接进迭代规划。进了需求池,就不知道什么时间才可以排上号了,明确放入迭代、明确好解决时间,快速收敛问题最重要。

发版经理

我们在一个迭代周期内,会轮值一个“发版经理” 的角色,发版经理要做的事情核心就是协调 + 跟踪。当然,发版经理不是去协调团队内的你我他的事情,也不是去跟踪某个人有没有划水。而是和 PD 一起确定迭代要做的需求内容,参与需求是否延期到下一个迭代的决策,确认新版本周期内几个关键时间节点的产物并做好验收,以及统一负责冻结代码分支等事情。总之,“发版经理”需要为新版本的效率和质量负责。

工具优先给谁用

最后,这里再聊聊工具的推行使用问题。我个人在做整个研发管理过程中,有一个深切体会:工具的推行一般来自于上级,上级推行这个工具的出发点当然是为了效率;但是,你经常会发现很多研发主管在关注工具的时候,一般都是从自己的管理视觉出发,而不是真正从一线员工使用工具的视角出发。

比如,项目管理类工具的第一核心究竟应该是定位给 PM 或研发主管用,还是应该定位成工程师间的协同使用?如果你要将团队打造成更高效的异步协同团队,那么这类管理工具一定是先给一线员工使用的,真正做到让团队内的每个人在工具上协同起来,通过工具平台来连接你我他。

架构设计

这里谈架构设计,不是想聊 Erda 的架构,我们还是聊一下工程效率这件事情:从架构层面如何做一些效率上的保障,让大规模研发团队可以更加从容迭代。

微服务化

早期版本,Erda 也是一个大的单体应用,团队规模就几号人,和我之前在阿里团队经历的差不多,协同起来非常高效,添加功能和解决问题也很快。但随着人数的逐渐增多,过程中出确实现了很多协作问题、效率问题,反正最后就是拆分成了微服务。当然,微服务也有微服务的问题。

讲微服务设计方法论的分享有很多,可以自行搜索参考。

组件化协议

Erda 团队的前后端比例,在最高时能达到 1:7,也就是一个前端要对接多个团队的多个后端,产品开发迭代的瓶颈被前端资源限制住了。

为了解决这个问题,我们思考并探索出了一套组件化协议框架,前端提供组件库和交互定义,专注于丰富组件的功能和改善交互体验,如何拼装组件和提供数据来实现业务功能,就交给后端来做,由于前端可以不关注业务逻辑和对接沟通 API 定义,中间能节省掉许多沟通成本,从而提高了整体的产品开发效率。

db migration

对于 Erda 来说,快速迭代产生的众多版本必须保证能够顺利升级。对我们来说,升级最难的其实是数据库的 migration,针对这样的一个情况,我们自己开发了一个 dbmigration 的管理框架,然后基于第一个产品版本定义好数据库的基线,后续的每个版本都在前一个版本的基础上开发 migration 逻辑放入到框架集中管理。Erda 的升级必须是从发布的版本按顺序一个一进行 migration 升级。

开发一个软件可能比较容易,开发一个能够持续升级的软件相对来讲困难度就比较高了。针对 migration 和升级,我们在测试阶段也会反复验证这件事情。

写在最后

研发管理这件事情本身管理的是技术,而不是人。我所接触到的很多人,还是会觉得研发管理是安排一个 PM 去盯着整个研发过程,甚至拿着“鞭子”去抽那些走得慢的人。这个意识和认知肯定是不对的,只有把管理动作拉回到技术本身这件事情上,才能真正激发团队的热情。

另外,任何人设计的任何一个工程流程和管理,在实际落地执行的时候,都不要去追求完美、100% 的精确,这是一件不现实的事情,有误差才是符合自然规律的,我们要做的事情就是将误差控制在足够小的范围即可。能够接受不完美,是研发 TL 的自我修养。

关于 Erda 如果你有更多想要了解的内容,欢迎添加小助手微信(Erda202106)进入交流群讨论,或者直接点击下方链接了解更多!

  • Erda Github 地址:https://github.com/erda-project/erda

  • Erda Cloud 官网:https://www.erda.cloud/

本文文字及图片出自 InfoQ

本文文字及图片出自

余下全文(1/3)
分享这篇文章:

请关注我们:

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注