创业公司工程实践--注重迭代速度

来源:互联网 发布:淘宝用淘客推广权重低 编辑:程序博客网 时间:2024/04/30 10:28

创业公司工程实践--注重迭代速度

翻译自Edmond Lau的《高效工程师》

如果你之前没听说过,持续部署还是蛮吓人的。我怎么能这么频繁的发布又能控制质量?为啥要这么高频?为啥不招一些测试人员来保证质量?我一开始加入时候也有同样的顾虑。对于新员工,第一周就要把代码写入到线上环境,这还是蛮刺激的。过了一段日子,我发现持续部署对团队产品增长还是蛮重要的。比如用户注册量,活跃度都大幅增长。持续部署,包括其他提高迭代速度的 方法都对增长发挥作用。

我们搭建了丰富的基础架构和工具帮助自动版本和软件包管理。内部有个测试框架可以并行化测试上千单元测试和集成测试。如果测试通过,对整个软件打包发布,确认所有的行为,最后推到线上。还有一些完整的报表和警报系统来监控产品健康,有工具可以方便回滚如果发现错误代码和事故。所有这些都能降低手工部署的成本和保障服务的稳定。

为什么持续部署这么重要?它可以让工程师改变部署一个很小的,增量的变化而不是一个很庞大的多组件模块。还是相对于传统发布能降低成本,容易管理,并加速迭代。如果某人发现一个bug,持续部署能改进去修正,再去验证和上线。在传统软件中,这个过程可能要持续几天甚至几周。工程师改了一下,等待几天,融合更多的补丁在去看是否能正常。这里面就很多上下文切换。设想你需要把一个线上数据库迁移到另一个。标准做法是。1 创建新的表 2 部署代码并写入到新表和旧表。3. 拷贝已有数据从旧表到新表 4. 部署代码去读取新表 5 删除写入旧表的代码。听起来这个过程很显然,但做完这个过程大概需要4,5个提交。估计1周。如果持续部署,工程师可以在几个小时内提交4,5次。并且这种变化比较小,就很容易调试代码。以前的话你需要从上百个不同的地方去查找哪里错了,现在的话,你可以在很小的空间去查找。

虽然是增量的变化,但不是说大的功能就不能分批上。可以通过一个开关来控制,在正常情形下都关闭。比如可以让内部用户先体验,再是小流量上线,最后是全流量。这其实也意味你的代码时合并到主代码库的。团队可以避免紧密的交互而导致的合并灾难。关注在小的增量变化可以提供新的开发模式。比如大家讨论产品,我们争议一些需求是否合理。我们不需要等待下个发布周期,就可以简单打一些日志,部署,在几小时之内就可以积累一些数据了。或者看到一些性能问题,我们就直接打一些日志去看一下时间都花在哪。高效工程师总是对迭代速度非常重视。我们可以列一些方法曾某去提高速度。首先,我们说一下快速的迭代的好处,我们可以搭建更多,学习更快。在看一下创建省时工具的重要。很多工程师时间都花在调试和验证的循环过程,我们在掌握编程环境的良好习惯。最后,我们对于非技术的瓶颈如何克服。

更快行动和学习

在Facebook里面有句话move fast and break things. 这让它在8年内达到10亿以上用户。Facebook提供6周的新兵训练营。对新兵,他们也许从没用过php,在他们刚进去就可以去部署到线上,当然也会break,今年2月就出现严重的线上事故导致整个网站当机2小时。Facebook强调迭代速度和影响力,而不是不停讨论和减少失误。Facebook的增速也验证快速迭代速度。你迭代的越快,你学习的更多,知道哪些对的还是不对的。你可以搭建更多东西并且尝试新的idea。不是每个变化都能产生积极的价值和增长。当facebook的广告产品,beacon,自动广播用户的行为在外部的网站上。当然很多人非常不满,这样你就可以更好的了解这次变化是不是在正确的路上,帮助你在以后更有效发展。Facebook CEO Mark在公司IPO时候说到行动快速的重要性,“行动快速让我们学习更多更快的东西,但是当公司变大,他们就会因为害怕错误而变慢,这样就会失去机会。如果你没有破坏一些东西,就说明你行动不够快”。应该说保持高频迭代式让Facebook成长到今天的秘诀。

投资省时工具

当我问什么东西能产生最高的回报,一般“工具”是最常见回答。比如Facebook前工程总监Bobby,说“我发现大多成功的人总是写很多工具,如果你想预测未来成功,就看这个人能不能针对某个问题开发工具”。 同样,Twitter 前VP Raffi说“如果你对某件事手工挫折了两次,最好为第三次写个工具” 每天的时间有限,工具可以放大你的影响力。如果有两个人,一个投入到他项目并花了2个月去搭建实施一组功能。另一个知道她的工作流不是那么好,她花了前两周去完善工作流,比如设置增量,编写自动测试脚本,方便部署用户。这种改进提升她的开发效率。而前者虽然一开始快,但后面2个月,她就能追上了,并且后6周的工作是可以跟前者8周的工作媲美。并且她还是为以后接下来工作提升了33%的效率。这个例子当然是简化了,事实上,也许她需要不断发现找到瓶颈再去选择工具,但总体上你投资的省时工具都是有回报的。

对于更快的工具往往也更经常用,比如有了飞机之后大家对长途火车使用的频率就会减少。并且可以使用以前不可能的开发模式。以前传统发布,需要部署一个新版本到测试环境,再去质量测试,解决blocking问题,再去上线。这种方法其实也省不了多少时间,但当我们用持续部署,发布时间可以讲到几分钟,团队更频繁发布,也许一天十次以上。团队可以调查线上的问题,最后一周可以节约大量时间。我记得以前在百度时候,编译C++代码,需要20分钟以上在一个分布式环境下。当代码需要长时间去编译,工程师就不愿意去频繁编译,他们就喜欢打包一个大型的变化在去编译,这样可以在每个周期去修复多个编译错误。后来,百度大幅提升编译效率,大概1,2分钟,这样工程效率就大幅提高,工程师可以避免更多时间花在等待,更快发现错误,让工作流更容易上手。如果编译时间缩短到秒,比如保存文件马上触发一个后台任务去编译,让工程师发现编译错误当他们编辑时候,这是新的交互模式。可以想象,更快的编译时间让工程师可以编译上百次一天。不同编程语言也有泪水的效果,比如Java,测试下函数,编译,再运行整个程序。Scala是运行在JVM之上,可以利用Java的库来快速验证,还有一个shell环境(REPL)可以交互式看结果。这不仅仅是所REPL快,还是因为对于更小的表达式或函数能快速测试。

有很多其他的例子表明工具能节省时间。如热代码重载,当服务器或应用自动更新新版本不用重启,鼓励增量变化的工作流。持续集成,每一次提交都会去重新载入代码库并允许整个测试集去运行,这样就不用浪费时间在搜索任何破坏代码的地方。工具的省时特性也帮助团队去成长。一个工具它节约你每天1小时,那么当你有10人团队就是10倍。这是为啥Google, Facebook, Dropbox, Linkedin有整个团队去提升内部开发效率,减少编译时间,放大到1000人的工程团队,一天编译多次,就转化成每周节约1年/工程师的工作量。为了最大化这种节约时间效果,你需要在整个团队去适应。当我在Google QA团队时候,大多想做新用户界面原型用C++写的。C++对高性能来说是个非常优秀语言,但它编译慢,在原型开发和测试新用户界面时候不合适。后来利用20%时间,我用Python写了个框架让工程师可以做原型开发。他们也很聪明不需要太多说明就意识到用新框架就提高了生产力,哪怕需要做代码上转化。有时新工具就是比现在的好,但转化成本高让其他工程师不愿意学习。这样的话就要花额外努力去降低转化成本并找到更舒服的方式去集成工具到现有工作流中。或许你能让其他工程师仅仅通过很小的配置就转化到新的方法上。说服别人也是挺难的,还是可以通过数据来证明你的时间投资是正确的回报。如果你团队每周3小时花在服务器的崩溃上,你花了12小时去自动化重启服务器。很明显你这个投资1个月就收回了成本。

在工作中,我们经常遇到一个有一个截至时间:把下一件事情做好,发布新的功能,清除列表中的bug,回复下一个客户问题。我们想做工具让生活更简单些,而工具的长久价值却很难维持。还是要从小做起。找到一个领域让工具可以节省时间,去显现价值。你会探索一些更伟大的目标让工具去帮助你更有效去实现未来的工作。不要因为压力总是去搭建新功能,对于重要的但不紧急的搭建工具的投资还是有必要的。

优化调试和验证流程

有个不切实际的想法:我们能写没有任何bug第一次能工作的代码。大多数工程时间都是花在调试和验证是否按设想运行。我们越早意识到现实,我们越早注重调试和验证的迭代速度。创建正确的工作流跟创建工具同样重要。我们都熟悉小型,可重复的测试。这也告诉我们每一个最简单的测试。小的可重用的测试也去除不必要的分裂,让时间和精力可以花在更多事务上,创建一种我们可以很快迭代的紧密流程。隔离测试可以删除每一个测试中没必要代码,或者验证最少用户可以实现的步骤。但当我们关注功能或者bug时候,很少能创建最小工作流。作为工程师,我们测试产品时,能找到一些捷径。我们用程序化去创建更简单的工作流。比如你想做一个网页分析应用,提供很高级的报表从首页开始需要很多次点击。也许你需要配置很多过滤和定制时间范围去拿到你测试的报表。你不必走常见流程,通过在URL参数直接跳转到 相关的报表。也许你可以搭建一个测试组件每次仅仅载入你关心的那部分。还有例子,你想做网页产品的a/b 测试去随机展示一些变化,根据他们的浏览记录。去测试这些变化,你可能对一些条件变量做硬编码区转化,再继续改变你想要的变量。根据你使用的语言,也许你要重新编译,或者你搭建内部工具简化流程,让你去设置cookie去触发某个测试条件。

这些优化手段对简化调试很明显,但往往在一些知名公司,工程师还是花了几个月在那些很慢的工作流殇,直到他们花了一点时间在优化上。当最终他们做了改变让迭代速度更快,他们会后悔为啥不早点想到。当你全身心投入到你搭建功能或者测试bug中,你最不想去增加工作。当你已经使用某使用额外步骤的工作流,你也不愿意去替换到更精短的,这就是个陷阱。这种对更小的调试工作流需要额外投资,但却可以帮助你迟早解决头疼的bug。高效工程师知道如何调试 一个大型软件。他们知道何时应该去缩短调试流程而不是每次使用同样的时间。这种灵感来自与你对问题如何反应和如何缩短步骤。高效工程师有创建紧凑测试反馈的能力。Mike,Instagram CTO说“如果你在ios中上传照片过程中处理bug,他们有种直觉在20分钟内可重组使得按个按钮就可以重现这个问题”。当下一次你每次都遇到同样的错误或者状态,你花时间去相信如何更紧凑测试。这些可以从长远节约时间

熟练掌握编程环境

不管我们工作中遇到什么类型的软件,很多我们每天用到的工具都是一样的。我们使用无数时间在文本编辑器,集成开发环境(IDE),浏览器,手机设备。我们使用版本管理和命令行。更多,有些基本技能需要对编程的认知,包括定位代码,搜索,文档,格式化。我们在编程环境上越有效率,那么工程师效率也越高。这里面有很多例子,常用任务去完成。

对某个小地方去微调也许不值得你去关注。一开始你会花更多的时间去熟悉,但考虑到你会重复千万次在你的工作中,小改进也会积小成多。你第一次对键盘的快捷键会变慢,但长期来说这是值得。没人在一夜之间掌握,熟练时一种过程,不是一次性。当你做的舒服了,时间节省就显现了。重要是你意识到什么在你生活中让你变慢,你去找到它在去优化行动。幸运的是,很多前辈也创建了提高效率的工具,所以我们要做的就是去学习那些。下面是一些我们可以掌握编程基础的一些方法:

对你最喜欢的编辑器或IDE要熟练。很多关于最好的编辑器讨论:Emacs,Vim, TextMate, Sublime. 你就需要掌握其中一个就很好了,你去Google一下这些工具的生产力的建议,问一些高效朋友和同事观察他们的习惯,找到高效文件浏览,查找,替换,自动补全的工作流。学习并多练习。

学习至少一种高效,高级编程语言。脚本语言就会更快完成一些任务。历史上C++, Java 就是比其他脚本语言Python,Ruby 2,3倍的代码量。一般来说高级语言伴随强大的,内置类型,像列表展开,函数参数,析构指派。

使用一些Unix命令行;操作处理数据使用unix命令而不是python或java程序,这节约大量时间就从分钟到秒级。学习一些基本命令:grep, sort, uniq, wc, awk ,sed, xargs, find 这些通过管道一期可以做很强大的转化。阅读帮助文档(man) 让你知道它的参数。在对一些常用的操作做笔记。

偏好键盘而不是鼠标。有经验的程序员训练自己在打开文件,打开应用,甚至浏览网页时尽量用键盘而部署鼠标或者触碰板。这因为来回移动手在鼠标上更耗费时间,我们可以去优化。很多应用在常见操作上提供键盘的快捷键,一些文本编辑或IDE耶提供组合键去对应一些特殊的动作。

自动化手工流程:自动化是需要时间,不管你使用shell脚本,浏览器插件,但这种成本比较小,你用的越多,你就变的更好。作为推荐规则,当我手工重复一件事在3次以上,我开始想如何自动化,比如有些做网页应用,都会经历过HTML,CSS的工作流,切换浏览器,重载页面去看到变化。如果你设置工具去自动重新渲染网页当你保持你的变化,这应该更有效率。

在交互环境中去测试想法。很多传统语言,像C++, Java, 测试一个很小的表达式都需要你去编译。像Python,Ruby,Javascript有解释器允许你去估算和测试表达。可以更有自信去测试行为并提供更快的测试速度。

更快更容易去运行单元测试当前的变化。使用测试工具仅仅运行你影响到的集合。最好时集成到你的文本编辑器或IDE,你可以通过快捷键来触发。一般来说,你运行测试速度越快,更多把测试当成日常开发,你节约时间就越多。

想想我们在编程环境中花的时间,掌握日常基本工具时非常划算的投资。这让我们去将有限时间放到更重要的问题上。

不要忽略非工程的瓶颈

优化你迭代速度的策略其实跟优化其他任何系统性能类似:分析最大的瓶颈,在去解决和消除。其实工具,调试工作流,或者编程环境你是可以去控制的,但也许那些不是拖慢你的真正瓶颈。

非工程的限制也许是阻碍你的迭代速度。客户支持在收集一些bug报告细节慢了。公司也许有一些服务保障它们客户的反应时间,这种限制了你发布新软件的频率。或者你的组织有一些特殊流程你需要去遵守。高效工程师分析出最大瓶颈也许这些不涉及到编写代码或者你的舒服区。它们尝试去扩大能力范围,在他控制之外的事情上也要做到最好。

有个常见的瓶颈就是其他人的依赖。一个产品经理也许在收集客户需求上做慢了, 一个设计师没有及时提供photoshop模版,其他工程团队没有按时发布功能,阻碍了你现在的开发。也许是懒惰和不完美,在优先级上不一致导致。前端团队因为依赖后端团队的重要功能而无法提供用户界面。但后端团队是把它放到最低优先级,比其他规模化和稳定性的重要度低。这种对优先级的不一致让你很难成功。你越早意识到你能主动发现瓶颈,你也越可能去改变目标或者重新建立功能上的优先级。

沟通对于人力上瓶颈时非常关键。在团队会议或者每日进度上去询问更新和承诺。阶段性跟产品经理去检查并保证你没缺失什么。在邮件或者会议记录上去跟进重要事务和时间点。项目往往在缺乏沟通而不是过分沟通的情况下失败。即使资源限制你更早的视线,澄清你的优先级和期望值有助于你提早计划和采用其他替代方案。你可以决定,去自己处理项目以来,虽然你需要花额外时间学习如何做,这也让你更早去实现功能。确实很难除非你已经跟其他人士沟通很多。

还有一个常见瓶颈时做决定的来自于公司高层,比如google当时新用户界面都要经过VP的批准。里面涉及到评估流程,不同需求,优先级,最后需要多次审核。对于这些在工程师控制之外的瓶颈。最好的方式还是去积极工作,不要等到你投入了很大哦工程时间在去寻求项目认可。最好,从原型就要有优先级,采集早期数据,做用户调查,然后让项目更早期获得认可。及早知道高层他们主要关注点,你也就对细节做针对性调整。如果一开始老板不同意,也要积极争取产品经理,设计者,其他领导让他们帮你说话。我不希望看到的是最后一刻的反馈,往往涉及大量修改,这白白浪费大量工程时间。不要再最后去延迟批准。

第三个瓶颈是产品上线时候的审查。比如质量保证团队,性能团队的要求。当你关注在特性上往往推迟了这些审核到最后一刻,意识到这些团队需要两周的时间去沟通。还是要及早计划,在合作上面还是要多去交流,让你在在上线检查时候就要保持运作,不要等到最后才去安排所有的审查。

在大公司,解决这些瓶颈往往超出你的作用力范围,你能做的也就是在周围努力。在小性创业公司,你能直接注意到瓶颈。我们可以创立共同信任来一起负担一些抉择。Donald Knuth 说过 过早优化是罪恶之源。比如搭建持续部署的流程,跟批准流程,也许后者更为重要。你要分析最大的瓶颈,不管你的工程工具,跨组依赖,批准流程,或者组织架构,找到它在去优化。

总结:

迭代越快,你学习到 的越多。如果你想通过缓慢行动来避免错误,这样就失去机会

投资工具。更快编译速度,更快部署周期,更敏捷开发,那些省时工具越用越上手。

优化调试。不要低估你花在验证代码是否工作的时间。投资足够时间去优化

熟练基础结构。熟悉并有效使用每日开发环境。

对迭代速度有清醒认识。不要忽略任何组织上相关的瓶颈。

0 0