涛思数据创业初期,只有几个人,人人都是十倍程序员。但7年之后,随着组织的庞大以及代码的增多,研发效率大为下降,为此我痛下决心,在今年十月份重组了公司最重要的资产,研发部门。重组后,为提升研发效率和产品质量,我强调一个原则:一切都要代码化。今天我将公司的一篇内部博客分享出来,供广大的研发同学、研发管理人员参考。
公司为提升研发效率,提升产品质量,将整个研发部门进行了重组,并将以前的测试部门转为研发平台部,这背后的逻辑是什么呢?我在会上介绍过缘由,但其中一条就是坚决贯彻执行“一切都要代码化”。我想给大家多解释一下,为什么要这么做?为什么它能提升研发效率,进而提升产品质量呢?
研发效率低下的几大典型场景
软件开发,在人员规模就几个人的时候,人效往往很高。但随着项目本身的复杂度的增加,要处理的场景越来越多,代码量也越来越大。比如TDengine,第一个版本不到15万行代码,但现在已经是超过70万行代码,测试代码都接近一百万行了。到今天,TDengine这个软件已经不是几个人能搞定了。随着团队规模的增加,协同沟通的成本急剧上升。而且为保证品质,团队引入了各种质量控制的流程,整个研发节奏慢了下来,人效大为下降。具体可以表现在几个场景:1. 研发在客户现场解决了一个BUG,改了几行代码,客户急着上线,但研发因为各种环境依赖,无法在自己笔记本上Build一个新的可以交付的版本,只能递交PR,等着发版负责人发版,然后下载安装。一般情况下,这一操作需要等待几个小时,在现场支持的人只能干着急。2. 一位新入职的研发同学,至少要花上好几天时间才能自己独立的写程序、编译、测试,中间还需要不断的“骚扰”其他同事,问这问那。如果没有人协助,估计一周都搞不定。因此新人入职,我们美其名曰“熟悉环境”。3. 公司建有CI/CD系统,看上去很不错,但所有人递交的PR都需要过一遍整个流程,特别是测试流程。TDengine整个测试例已经超过1500个,跑完都要2个多小时,这样导致一个PR的递交,要等很长时间。如果递交的PR有问题,还需要再递交,因此让新代码的递交效率大大降低。4. 整个公司没有人能说出来到底有哪些场景的测试例在跑,虽然有测试设计文档,列出了哪些测试例,但实际跑的与文档上差别太大。而且很多情况下,测试例各写各的,虽然测试例的数量在不断增长,但测试有重叠,覆盖率依然不够。5. 要测试某个用户场景,无论是研发,还是售前、交付,第一件事情就是申请计算资源。虽然我们已经有2600多个核的测试机房,但这些机器都被人为的分配给了不同的组和个人。因此要协调出新的资源,挺困难,不是鼠标点击一下就能解决的,往往就要开会协调,几个人的一个小时就这样过去了。上面描写的五个场景在TDengine全部存在。整体来讲,我们研发效率是低下的。如果从我们对BUG修复的时长以及数目来看,与传统的大公司的研发相比,效率已经高不了多少,但与我们创业初期相比,1/3都没有。由于效率低下,导致我们的投入不够,也就导致产品的质量难以保证。
效率低下的根本原因
随着团队规模的增大,为什么协同沟通成本就急剧增加?研发效率就大幅下降呢?仔细分析,有几点原因:1. 好些工作都难重复,都藏在个人的脑子里。比如开发环境的依赖,都是各搞各的。每个人都要下载各种软件包、各种工具,读一大堆文档,按自己的理解做各种配置,最后工作,当然很开心。另外一个人,又是要走同样的路,手脚快的,也许几个小时搞定,但碰上手脚慢的,一天都搞不定,卡在什么地方,还没人能帮。2. 不重视工具、工作流管理的代码,没把他们纳入代码的版本管理。比如发版工作,本来应该是全自动化,而且也确实做到了。但一旦发版的工作流做些修改,CI/CD又卡在一个人手里,取决于这个人的水平高低,有可能很快,也有可能很慢。但总之,即使水平低,你也没办法,因为其他人没法上手马上让它工作,而且相当多程序员往往不屑于写这类程序。因此让CI/CD跑起来,只有这位“牛人”能做。3. 文档与代码脱节。比如我们TDengine测试代码,就与Testing Spec脱节。Testing Spec往往是过期的,初稿review之后再也不会有人改。新增、修改的测试例在文档里是反映不出来的。4. 对用户手册重视程度不足。虽然 TDengine 的用户手册已经远远好于中国绝大部分技术公司,但与全球顶尖的软件公司比,还有不小的差距。用户手册由于本身的性质,导致它很容易落后于代码的更新。而且研发同学普遍的共识是,写用户手册不是研发工作,无法体现自己研发水平,因此投入不够。在这种情况下,售前、交付、还有用户的问题,都只能依赖我们产品的“专家”来亲自回答,而且有时自己都拿捏不准,还要问周围同事大半天,才能给用户一个精准的回答。而且因为他能回答客户产品问题,理所当然,还会被大家认为是高手。5. 公司计算、网络资源的管理还是原始时代,完全是靠Excel表格人工在管理。
一切都需要代码化
全球软件开发行业发展到今天,早有了成熟的方法应对这些效率低下、产品质量难以保证的场景,那就是一切都要代码化。因此我们会经常听到Infrastructure as code, Environment as code, Pipeline as code, Documentation as code, Security as code, Network as code这些词。这些词是”as code movement” 在一些具体场景的体现。代码化的核心目的是让一切可自动化、可重复、可回溯,每个研发不用做低水平的重复性的工作,从而提升研发效率,进而有更多资源投入来提升产品的质量。针对TDengine,我们可以明显看到需要做或改进的地方有:
1. Environment as code:即开发环境、测试环境的自动化部署。我们不能依赖某个人脑子的记忆或经验,依赖研发同学快速阅读第三方工具用户手册、试错的能力,而是要将这些经验、能力固化成为代码。一个人趟过所有的坑后,通过代码让其他同事都能享受他工作的结果,一键就能把自己的环境设置好,根本不用去了解Maven怎么安装,MQTT数据源怎么设置等等,而且其他同学可以在他代码基础上做调整。
2. Pipeline as code:CI/CD的workflow代码化。我们早已代码化,但要把这些代码纳入到正常的版本管理,任何人都可以在现有的代码基础上修改、优化,增加新的步骤等。而且要保证我们的代码不能有任何环境的依赖,比如某台具体的测试机器,这样任何人Clone完代码后,自己一下就能把workflow搭建出来。同时,整个workflow包含的内容要越来越多。我们已经增加了Release Notes,测试覆盖率报告、性能测试报告自动生成。今后我们还要看哪些内容可以自动生成,哪些检查工具可以加上。
3. Documentation as code:文档代码化。除用户手册之外,最重要的是测试例的列表。我们需要从测试例脚本本身自动生成测试例列表,而且自动分类。这样让任何人,包括售前、交付的同学,一看就知道到底测试过哪些场景,针对某个具体客户,是否需要新增场景。用户手册我们已经代码化,但做的还不够好,因此我们现在对于一个新的功能或BUG,研发负责人有项专门的工作,就是合并PR时,检查用户手册是否有更新。
4. Benchmark as code:对比测试代码化。TDengine与其他时序数据库相比,有卓越的性能。但每个版本我们都要做对比测试,而且要不断增加与其他竞品的对比。我们已经部分实现,但还不够彻底,有一定的环境依赖。
5. Infrastructure as code:即计算资源的分配要自动化。把我们内部的服务器资源的管理完全虚拟化、脚本化,对于闲置的资源自动释放。自动化后,我们一家100人的公司,测试机房有2600多个核,根本不会存在测试资源不够的时候。要新的计算资源,几秒钟搞定。
对于研发团队,现在我能看到无法完全代码化的工作是产品设计文档,有一些工具可以帮助大家,但难以100%代码化。抛开设计文档,其他所有工作都是可以,而且必须代码化的。代码化后,个人的经验、能力就转化为团队的经验和能力,沟通交流成本大幅下降,一切都是代码说话。这也是我们为什么要对整个研发团队统计代码量的原因。代码量不是绝对,更不是唯一指标,代码量大的同学,工作不一定出色,但代码量一直很低的同学,工作是一定有问题的。在我们过去,有的同学一个月都没有递交过一次代码,这种情况再也不能发生。
一切代码化后的效果
一切代码化后,很多工作改变了,我们可以明显的看到如下的结果:1. 任何人在自己不联网的计算机上都可以打包、发布版本。如果在客户现场发现BUG并解决了它,可以马上给它安装上自己的版本,而不会有任何不兼容的事情发生。2. 任何人在自己计算机上,都可以跑测试,包括全量测试、稳定性测试、性能测试、性能对比测试、检查测试覆盖率等,而且不依赖公司的测试资源。因此完成一项功能或解决一个BUG,自己就可以全部跑一次,以避免递交PR时无法递交。3. 性能优化的同学,可以一键先在自己计算机上跑性能测试,看性能是否确实提升了没有,而不是直接递交到测试平台,等待结果之后再看。4. 新加入的同事,根本不需要熟悉环境,几个小时,就可以配置好开发环境,Clone代码,编译、运行、测试起来。手快的,就可以马上开始debug了。5. 客户、售前、交付同学关于产品的问题,研发同学一律是把用户手册的截图或链接发给对方。如果无法做到,马上去修改文档,递交PR。这样我们每个人都不用脑子里记住或记录一些产品如何避坑的小技巧了。我们留给客户的印象就是专业,产品没有瑕疵,出错全怪我自己,是由于自己没细看文档。6. 任何人,包括非研发团队的同学,可以清晰的看到每个发布的版本,进行了哪些具体测试,发布的版本是否有任何报错或报警。针对自己客户的场景,马上就知道还需要补充哪些测试用例,才能确保产品上线没有问题。7. 需要计算资源的同学,只要登录内部网站鼠标点击几下,想要的硬件资源、配置的软件环境就马上准备好了。8. 在我询问研发平台组同学的工作时,如果问负责发版的同学,他的回答是“Jeff,我这周又把发版流程优化、调整了一下,加了更多的检查,来保证产品质量”,而不是“我这周忙死了,发了几个什么版本”。如果问稳定性测试的同学,他的回答是“Jeff,这周我又新增了几个破坏性的测试场景”,而不是“我这周发现了2个BUG”。问性能测试的同学,他的回答是“Jeff,这周我新增了几个查询场景的性能测试”,而不是“我这周完成了性能对比测试”。一切代码化还可以让新人迅速进入角色,而不是受制于需要长时间沟通才能获取的信息。每个人需要依靠自己的能力,而不是掌控的信息或资源,来成为研发高手。
结语
一切代码化充分体现我们倡导的“公开、透明”的文化,也充分体现我们强调的“实事求是”的工作原则。研发就必须以代码说话,而不是把很多东西记在脑子里,或者让自己写下的文档或代码生锈长霉,这样才能形成团队的力量,集体的智慧,而且随着时间的推移,我们的积累就越来越多。效率提升之后,我们可以把省出的精力更多的倾注到创造性的工作上去,提升产品的品质,进而提升产品的市场竞争力,让我们获得商业成功。
陶建辉
涛思数据TDengine创始人