我在ThoughtWorks中的敏捷实践

本文以我在ThoughtWorks中的E项目经历为依据,覆盖了ThoughtWorks日常独立交付项目中主要的敏捷实践。

项目回顾

项目背景

E(End User Monitor System)是一个在线的物资跟踪监控系统。由ThoughtWorks团队为客户提供的一套完善的软件交付服务。

该系统为资助物资的跟踪与监控提供了完整的网络解决方案。整个流程涵盖了客户对物资来源的管控、库存管理、物资下发与跟踪、客户与IP(Implementing Partner,合作伙伴)的协作沟通、IP对运输结果的反馈(生成报告,警告通知,短信互动,邮件通知),以及IP对物资的二次分发后的记录跟踪与监控。

该项目属于海外独立交付项目,整个开发过程由ThoughtWorks团队负责管理。好了,项目信息只能透漏这么多了,不然客户要找我打官司了。


成员背景

ThoughtWorks提供完整的交付团队(PM, BA, TL, QA, DEV, UX),团队为颇具代表性的敏捷团队,规模10人左右。客户团队主要接口人3位。

ThoughtWorks团队成员,犹如一架生猛的战斗机:PM英文一流,敏捷开发管理相当到位,因为看了上万本脑残小说,时不时就用到了生活中来。TL拥有7年以上的开发经验,7年之痒,什么,不用说都懂的。TL还富有学习激情和被黑精神,黑历史墙列满了他的关辉血泪史。QA被誉为IT界的福尔摩斯,DEV都休想逃过她敏锐的鼻子(怎么是鼻子呢?太陶醉了吧,这是境界!),最后,就是'苦逼'的DEV,也就是以程序员自居的我们。

我们每个人特点各不相同,但有一点神似:专业,责任心,追求卓越

我们团队还有一个workout的文化特色,向⬇️看:

PS:我们的workout自开始之日到项目交付之期,不曾落下过一天,且收到良好的反馈。即便团队成员分开了,每个人都能将运动精神传播下去,乃至源远流长......


技术背景

我们是一个全功能团队,人人身怀敏捷开发领域的知识和技能,且有一定的经验积累,所以可以说我们天生敏捷,在开发过程中大家都能高效地分工合作。

再说技术栈,项目使用的主要技术栈是Python, Django, AngularJs, PostgresSQL, Docker。而我们DEV在进入这个项目之前,擅长的技术栈是Java, Springboot, C#, Android, jQuery


敏捷实践

项目之所以成功交付,核心在于人,而良好的敏捷流程与实践也是不容忽视的。

早在2001年,17位追求卓越的志愿者聚集在美国犹他州雪鸟独家圣地,讨论一个新的软件开发趋势,它被称作轻量型软件开发过程,后来他们将它定义为敏捷,并且发布了敏捷开发宣言:一种把一人为本、团队合作、快速响应变化和可工作的软件作为宗旨的开发方法。敏捷宣言可以总结为四句话:

1. 个体与交互   优于  流程与工具  
2. 客户协作    优于  合同谈判  
3. 响应变化    优于  遵循计划  
4. 可工作的软件 优于  面面俱到的文档  

敏捷开发的核心就是在一个高度协作的环境下,不断的通过反馈来进行自我调整和完善。重点强调的是协作反馈,协作体现在团队与客户之间的协作,团队成员之间的协作。反馈则是在开发中的任何环节,包括代码质量、自动化测试、部署、项目进度、需求变更、客户验收等,而且反馈越快越好。有句土耳其谚语这么讲的:"不管你走了多远,错了就要重新返回",所以我们越快得到反馈,就能越早确认自己有没有走错路。如果没有错,我们会更加充满信心。反之,及时做出调整,让成本最小化。

我们是一群快乐的逗比,快乐的人做出来的事情也是让人快乐的。逗比们聚集在一起,探讨出一套适合于逗比团队的敏捷开发流程,每个人都愿意遵守并维护这个工作流程,并且在流程中不断追求最佳的实践,来保证我们的项目的交付进度和软件的质量。

项目中实践主要围绕迭代进行,用一张图概括:

从图中可以看出,一个Iteration通常始于IPM,止于Showcase,其中每天都会发生的有StandupPairTDDCode Review则发生在每天的Coding中,通常情况下,Story kick-off之后,就进入了开发环节,Coding便开始了。CI属于基础设施,通常在一个名为Iteration0的迭代完成,也就是正是开发开始之前就应该完成CI的搭建。Retro则较长一段时间才进行的活动,根据实际情况,有1个月一次,也有2个月一次的。另外Regular catch up with client也是因项目而异,E项目是Daily,也有Weekly的,有些项目甚至没有这项活动。

敏捷的宗旨是减少浪费,所有的敏捷实践也都是围绕着高效协作快速反馈这两个核心理念展开,那么此刻便可开始我们的敏捷之旅。


IPM

IPM(Iteration Plan Meeting),迭代计划会议主要是跟客户保持沟通与信息更新的一个会议。

敏捷宣言里面有一条:客户协作优于合同谈判。在Scrum团队中有一个角色叫做产品负责人,Ta的核心职责是确保业务需求的清晰和透明,保证开发团队对业务有足够的了解,并将这些待完成的业务需求(Story)按照优先级排列出来,按照任务卡的方式来驱动团队的开发。并在客户需求有变更后能够第一时间告知团队以做出调整。

在我们团队中,这个角色就是一开始提到的BA。她是IPM主要参与人,另外还有Tech Lead会一起参与讨论(团队中每一个人成员都是可以参与进来的)。IPM按照团队指定的迭代的周期,通常是两周,每隔两周跟客户接口人一起约一个时间,主要讨论以下几个方面的内容:

1. 下一个迭代的Story。
2. 对下一个迭代的期望。
3. 团队的人员可用性。
4. 风险的评估总结。

通过这种会议,能够让客户对我们团队状况有一个清晰的了解,而且客户对我们下一个迭代要做的功能有了整体的把控,一起设定好期望,这样也会大大降低风险。

IPM的主要产出是下一个迭代中完成的Story,这些Story即为下一个Story要完成的目标,我们通过敏捷看板工具来管理它们,例如下图mingle上位于Backlog栏中的Story:


Regular catch up with client

跟客户建立信任关系是基础条件,而让客户保持愉悦,也是项目成功交付的助推剂。

客户是位于非洲东部乌干达的子民,5个小时的时差没有造成太大的沟通障碍,他们也没有参与到我们Standup中来。所以我们团队在与客户沟通上除了两周一次IPM和Showcase,还增加里一个每天的Catch up环节,在客户上班后的固定时间一起开个小会,会议时间跟Standup差不多,主要涉及内容有:

1. 我们团队昨天的更新.
2. 客户昨天的更新
3. 确认Story。如果有变更,能及时作出调整。
4. 提醒客户使用我们开发出来的功能,以便我们尽早得到反馈。
5. 一些节日的问候,嘘寒问暖,表达我们团队的关怀。

Regular catch up with client 能产生较大的价值:

1. 首先,让客户有非常强烈的参与感,以及让他们对项目整个进展的把控(他们会觉得自己才是项目的主导者),增强他们的信心以及对我们的信任。
2. 其次,让客自己决定功能实现以及及时验收功能,降低了需求变更和打回的风险。
3. 最后,则是润滑剂了,能够在客户良好的信任的基础上,保持合作关系的轻松愉快,这会为项目的成功交付使上劲。

那么Regular catch up with client 有什么产出呢?因项目而异,比如E项目,我们每天都会跟客户进行这项活动,所以一些修改注释都会直接备注到Story中。而有些客户,因为地点时差原因,只能每周进行一次的话,catch up之后就需要一个总结性的邮件来总结并跟踪记录catch up的结果,该邮件的发送目标是相关客户和Team的所有成员。

并不是每一个项目都会有这个实践,有些独立交付的项目,他们每日站会的时候客户也会参与进来,就不需要额外单独的时间去做这件事情了,而有些项目,因为特殊性,客户可能不希望这么频繁的Catch up,这时候需要团队灵活变通,与客户一起商讨出一个合适的时间周期,做出一些权衡,让客户自身觉得舒服。总之,Keep住的一点是:保持跟客户的信息沟通,尽可能早的得到客户的反馈,保持良好的客户关系


Standup

Standup是一项成本小收益大的活动,做好它是敏捷的第一步。

Standup,就是每日站会。我听过一个有趣的事情:在敏捷开发方法兴起的时候,很多传统开发模式的团队跃跃欲试,他们选择从Standup切入。然后每天早上上班后,大家聚在一起开个会(站着、坐着都有),然后该怎么做还是怎么做。他们会对别人说,我们在搞敏捷开发...

没错,Standup就是团队在一起快速的开一个会,大家挨个的更新一下自己的状态,这些更新主要有:

1. 昨天完成的工作。
2. 今天计划做什么。
3. 面临什么阻碍。
4. 自己手头Story的进展。
5. 是否存在技术风险。

有人会问,大家天天都在一起工作,每天跟炒土豆一样,没什么新鲜感了。这有点深处酒巷中不觉酒香的味道了。站会能够给团队带来的福利诸多:

1. 让大家进入一天的工作状态。
2. 清楚自己的Story的进展,提醒自己把握好时间,或者激励其他成员的开发进度。
3. 让团队成员知道项目其他地方的进展。
4. 如果谁遇到不好解决的问题,可以将问题抛出来,大家一起积极讨论解决方案,也能寻求其他人员的技术支持。
5. 避免在重复造轮子而耗费时间,让大家知道目前团队中可供复用的解决方案。
6. 帮助Team Leader了解哪些领域需要更多的帮助,从而更好地分配资源。

既然是快速的会议,Standup的时间就不宜过长,建议5~15分钟。最好是站着开会,因为研究表明,当人们坐着开会的时候
,会议的时间会被无形中拉长。Standup的时间安排在工作时间开始后的半个小时最佳(比如9:00上班,9:30开始),这样大家就不用一到公司就急急忙忙的参加Standup,大家有个缓冲的时间,比如说安置电脑,泡咖啡,沏茶,想想今天的计划等。而我每天早上会给自己沏壶茶。

没有什么特殊原因的情况下,确保团队成员都要参加,如果一些人因为特殊原因经常不按时到,适当调整Standup的时间,但也不宜太晚。

对于规模很小的团队(3~5人),我也强烈建议执行Standup,因为它的成本真的很低。

下面是我们团队的Standup:

PS: Standup的时候,选一实物作为Token,发言时拿着Token。上图中我们选择了瑜伽球作为Token,逗比们说:健身无处不在~


Story kick-off

在一个Story开始前,确保BA, QA, DEV对Story的理解达成一致,并严格按照AC来验收。当然,前提是Story本身是不容置疑的。

所以在Story kick off的时候,通常是三个角色一起参与:BA、QA以及要开发该Story的DEV。Story卡是BA预先写好的,通过专业的敏捷开发管理工具进行管理。DEV在kick off的时候,BA会给DEV讲解这个Story要完成的功能,以及它的AC。DEV如果对其中的描述有任何疑惑,需要及时提出来,当场弄明白才可以正确的去完成这些功能。在后续的开发过程中,如果碰到任何疑惑,随时找BA或者QA了解清楚,不应该自己猜测着开发,更不可跟着心走,因为在我们DEV界中,有一句邪门的定律:

猜出来的需求往往是不靠谱的,最终需要打回重做!

Story kick off的核心目的是确保DEV开发出的功能都是符合客户期望的。而Story本身描述错误并不在我说的范围内,我们在开发过程中,也未发生过这种情况,只是有时候客户的需求变更后,Story卡也会及时变更过来。对于Story kick off,我总结出了一些实践:

1. DEV自己先完整地过一遍Story的描述。
2. DEV给BA和QA去讲这个Story的功能以及AC。
3. 要能够清晰的讲出来,并且三者达成一致,如果有疑惑,当场要得到答案并弄明白。
4. DEV开始开发Story,并自行将Story参照AC拆分成很多个子任务列表,然后一个一个干掉他们。

最后一个实践严格上讲不是kick off环节里面的,它发生在kick off后,DEV自行决定怎么去完成功能。我比较推荐DEV在kick off后将Story划分成子任务列表,按照依赖关系和优先级排序,逐个干掉他们。一些敏捷管理工具(Trello, mingle, Pivotal Tracker, teambition)都支持这种任务拆分,你还可以很容易的记录与跟踪。我个人很喜欢这么做,这个过程不断锻炼了我拆分任务的技能,最值得一提的是当我将任务列表最后一个勾上的时候,我重重的呼出一口气:哈,我又完成了一个Story。轻松加愉快😉。

一些项目会引入好的开发实践,比如说BDD。它能按照人类自然语言去描述一个功能的实现。我们的Story描述通常会参照这种方式: as...when...then...when...then。这个时候,DEV、QA、BA可以在Story kick off的时候利用一些测试工具(Cucumber)一起来编写Story验收测试用例(主要由QA来编写),DEV负责编写代码来通过这些测试。理想情况下,验收测试用例如果正确完整,当所有测试都通过后,意味着Story功能已经完成。而且这种TDD的方式,代码出现bug的几率也会大幅度降低。

下面是一对Pair做Story kick off:


Pair

结对编程的开发速度通常小于简单地将一个人的开发速度乘以2,但它依然能创造价值:知识的共享,代码质量的提高,缺陷率的降低。

XP里面提到了结对编程,它是一项经过事实证明利大于弊的实践(暂且不要喷,我也知道国内很少有公司实行结对编程的,但这也不影响它成为一项很好的实践)。

简单来讲,Pair就是两个人同时工作在同一个Story上,一起讨论Story的解决方案,并编写代码实现功能,一个人敲键盘,一个人屏幕代码,穿插着进行。所以我会经常在TW办公室看到两人(男女搭配居多)同时盯着一台显示器(有时候是两台同步的显示器,比如说我跟TL Pair的时候),他们在快速敲击键盘的时候会有一些交流,并时不时停下来讨论说笑片刻,亦或是在欣赏一下自己漂亮的代码。

下图是我跟TL Pair的剪影:

Pair将本来可以并行工作的两个人聚焦在一件事情上,表面上是在降低生产力,实际上它确实是有一定的成本的。而这种付出并不会打水漂,最明显的好处是能够最大化知识的共享(尤其是更换pair的场景下),包括业务知识的共享、技术方案共享、解决问题思路的共享,这一点尤其体现在团队有新人融入的时候,通过Pair能够快速带领新人成长起来,提高整个团队的战斗力。
另一方面就是提高代码质量,Pair实际上是两个人一直在不停的做Code Review,两个人的思维碰撞能够避免很多代码小聪明和不好的编码习惯。同时两人还可以互相监督,比如谁犯懒不想写测试了,就进行举报,举报有奖😄。

Pair中也有一些很好的实践:

1. 搭档的选择上,两个人的技能和经验最好是相当的,这样就不至于一个人成为被教育的对象,而另一个人成为键霸了。
2. 有新人加入时,需要一个经验较丰富的老人Pair,最好是有良好Coach技能的老人,老人尽量只提供思路启发,并让新人多思考和动手实现。
3. 经验相当的Pair时,可以一起讨论解决方案,并达成一致,然后一个人写测试,另一个人编写代码通过测试,两人同时保持focus。
4. 定期更换Pair,粒度可以控制在以一个Story完成为节点。大一点的Story可以keep住一个人不动,另一个人进行更换。
5. 遇到技术阻碍时,并行寻找解决方案,并最终一起决定采取什么方案。
6. 当两个人对实现细节的优劣拿捏不定时,邀请团队经验丰富的老人做出建议参考。
7. 在一些很简单的小问题上,如小的defect,可以不采用Pair。

有些时候,因为项目进度的紧张,Pair并不会这么理想的被落实,团队可以进行灵活的调整。如果Pair的时间减少了,可以通过加长Code Review的时间来做一些弥补。


TDD

TDD,测试驱动开发,这项人人都称赞、却很少有人真的去做的活动,不应该只是一个被供奉起来的神。接地气,再接地气一点。

TDD在我看来是一个存在争议的主题,因为在一个连测试的没有的代码库中(多数客户也不关心测试代码,他们通常只想要看得到的功能),它的立身之本就不复存在了。我经历过只有纯手工黑盒测试的项目,没有单元测试、没有集成测试、没有E2E测试(测试金字塔, Martin Folower),所以TDD无从谈起。我也经历过客户要求测试覆盖率的项目,有专门的测试覆盖率工具(coveralls)来检测代码库,有的甚至集成在CI上作为一个硬性指标。

我们E项目接手过来的时候,测试覆盖率还是挺高,据统计达到了90以上。所以TDD必须在一个有测试的项目中去讲。它跟我们先写实现然后给实现添加测试的过程反着来,就是我们根据对业务理解,先写一些测试(E2E,Integration, Unit),此时得到运行结果为红色,然后编写业务代码让其变绿。这么做的好处主要体现在两点:

1. 从宏观把握Scope,开发人员不会在开发的过程中扩大或偏离Scope。举个例子,开始一个功能点时,一上来添加一个E2E测试,整个Scope在此时就被框定,然后再细分到内部实现,最终以通过这个测试来完成这个功能。
2. 提高代码的设计。当我们先写测试的时候,就会考虑到被测试的对象要尽可能被方便的测试,此时我们会尽可能的改良我的的API设计,以便利于测试,这样一来,我们写出的代码更具有可测试性,这样的代码往往具备较高的质量。
3. 确保功能不会被遗漏。我们一开始更多关注的是业务,而不是代码的实现细节,此时写出来的测试会更全面的涵盖不同的Case。

当然,采用TDD有一定的要求的,TDD考察的更多的是一个人的设计能力,所以需要有一定经验的开发人员,而新人往往是很难做到这一点,但这不应该是新人不去尝试的借口。

实际项目中,很少有这么理想的团队和客户,所以可以根据团队自身的条件,灵活采取TDD去编码。就我个人的经验,TDD编码的时候刚一开始的时候并不是那么顺手(因为TDD更偏重设计),心里会觉得比较耗费时间,最终实在Story的完成时间上是差不多的,而TDD会额外带来一些好处(缺陷率低,代码质量高)。就我个人而言,我更愿意采取TDD。但不管怎样,一个团队始终不应该放弃对有效的测试覆盖率的追求。


Code Review

不可否认的一个事实:人人都爱整洁的代码。而一个人单独编码难免会耍一些小聪明,或引入一些自身习惯难以察觉的不良代码。Code Review能让你提高警惕,并改善代码的质量。

我第一次体验Code Review是在珠海金山客户现场。因为项目是基于契约的前后端分离开发模式,ThoughtWorks这边后端就我一个人,带着一帮金山的兄弟写后端代码(基于Springboot),每天组织大家一起做Code review,挨个过当天的Code。Review过程中总会发现一些需要改进的地方,以及一些好的实践也能在团队中形成共享。比较好的现象是,客户方的Leader都高度信任和认可我们,大力支持这种实践,而给力的金山兄弟也能每次将问题记录下来并作出改正,所以日复一日,整个代码库的质量有显著的提高。

在E项目中,我们有每天的Code Review(因为一些其他原因,并没有天天进行)。因为我们有3对Pair,时间定为1小时,实践证明,Code Review能带来的好处有:

1. 让每一个人提高警惕:自己写的代码并不是只有自己看的,所以要督促自己做好。比如规避不想写测试,代码耍酷等。
2. 共同找出代码的坏味道(命名规范,代码整洁,API内聚性,面向对象设计),及时做出改正,提高代码库的质量,有助于后期扩展和维护。
3. 让团队成员知道他人在做什么以及怎么做,分享好的编码习惯和技术实现,有助于团队整体进步。

Code Review适合安排在下班前,一方面,大家经过一天的高强度的思考与编码,适当停下来,看看其他人写的代码,同时将自己代码讲解出来,还能意外的获得一些灵感,或许能解决自己面临的阻碍(你面临的问题,其他人可能已经解决了)。另一方面,如果这个时候发现代码的坏味道,需要改进的地方,下班后可以花少量时间作出更改。

为什么我说用下班后少量的时间呢?因为这些通常属于自己成长过程中欠下来的技术债,花点时间取得进步,应该不会有人会觉得这是剥削吧,而且自己需要对自己的成长负责!

Code Review也是需要时间成本的,根据团队的规模12小时(510个开发人员)。对于规模很小的团队,可以适当减少Code Review的时间和频率,如果团队经常Switch Pair,也可以适当减少Code Review的时间。不管怎样,我都强烈建议进行Code Review,形式可以不拘一格:整个开发团队或者俩俩搭档。

关于Code Review,我总结了一些好的实践:

1. 团队一起拟定一个开始时间和时长,并落实到位,保证团队成员的参与度和Focus。
2. 短时间的描述自己的Story业务,主要Focus在代码上。
3. 持续跟踪记录,并获取反馈。这需要有一个人记录问题(可以按天轮流),结束后交给Owner执行更改,并且下一次Code Review的时候先过上一次的更改。
4. 必要的时候拉长时间,条件允许下建议在一个有大显示器的会议室中进行。

下面是某个时刻,我们Team四个人正在专注地讨论为一个函数取个更好的名字(猜猜谁是表情帝??):


Showcase

不管客户有多忙,也要定期让客户确认自己的期望是否得到满足。在签订合同前,要跟客户达成一致:Showcase的地位不可动摇。

Showcase就是给客户演示我们上一个迭代已经完成的功能,它的宗旨是及时得到客户的反馈,确认团队的产出是否满足客户的期望,降低需求变更返工的风险。Showcase从项目开始时周期性地进行,并直到项目交付。这个时间间隔是基于团队设定的迭代周期,我们团队是两周一次。团队跟客户安排一个远程会议(如果是在客户现场,一些参与讨论效果更好),主要涵盖了以下内容:

1. 跟客户确认上一个迭代的Story列表。
2. 项目目前的交付状态。是否正常进度,会不会延期。
3. 演示上一个迭代完成功能。在线系统演示,需要一个staging环境。
4. 客户对功能确认,对达到期望的story签字,反之。我们记录下问题,并修改,再次确认签字。

试想一下传统瀑布开发模式下,一个功能的演示通常是在所谓的里程碑节点的时候,此时项目或许开展了半年或一年甚至更久,客户这个时候见到自己的系统,简直会惊叫起来,原来这压根不是他们想要的东西(因为客户一开始都不知道自己要什么),即便开发团队严格按照预先的设计文档,这是一个灾难,而这种灾难也时常发生,导致大量的工作白费,且很难挽救。

敏捷开发可以规避这种灾难性事件的发生。而Showcase在敏捷开发中是一个不容忽视的环节,它契合了敏捷宣言中的拥抱变化优于遵循计划。Showcase能够让团队在每个迭代完成后及时从客户那得到反馈,对变化做出快速的响应,避免了劳动成果的浪费以及方向的偏离,也能最大化让客户的期望得到满足。

或许有些客户不愿意两周搞一次,他们觉得太频繁,尤其是国内之前跟瀑布流方式合作的客户。这个时候,团队可以就这个迭代周期进行变通调整,通常建议的是1~4周,不宜太长,过短也没什么效果,两周是我们推荐的迭代周期,至于如何权衡这个时间,有两点可以参考:

1. 在探索中找到适合团队的迭代周期,如果发现每个迭代时间不够用,要么是story划分太大,要么是迭代周期太短,这时需要根据几次的平均结果做出调整,适当扩大迭代周期,或者更合理的拆分Story。
2. 如果Showcase的时候功能背离了客户的期望,通常是因为迭代周期太长。因为用户的需求以及团队对需求的理解都在随着时间的推移而变化,导致发布时的产出并不是客户需要的。这个时候,可以考虑适当缩短迭代周期,让反馈来的更快更舒缓一些,而不是更慢更猛烈。

为了达到更好的Presentation效果,Showcase通常提前准备一个总结性的Slide来引导整个过程的推进,结束后该Slide即为产出的一部分,另外也会有一封总结性的邮件来跟踪记录Showcase的结果。


CI

没有CI的项目开发是在耍流氓。CI在Agile中是一项最基础的设施,它通过自动化来提供有效的反馈机制以及高效的部署,大大降低代了码集成和项目交付的风险。

CI,持续集成。在我的印象中,它是一个项目开始前必须搭建起来的基础设施。在现在的软件开发项目中,几乎没有项目是只有一个人在开发的。超过一个人就形成了团队,每个人同时并行开发不同模块的功能,这就涉及到代码的集成,所以代码集成是几乎所有开发团队都要面临的问题(一个人的开发项目不在本文范畴中)。

持续集成跟团队开发人员独立开发没有冲突,相反,借助一些工具(Jenkins, GoCD(ThougthWorks开发), Travis CI),它能快速的对我们开发人员提交到代码库的代码作出反馈。开发人员每天都在代码库提交代码,版本控制工具(比如Git)在提交前必须更新代码库最新的代码(解决冲突,代码合并,应用更改),然后将代码提交到代码库中。这个过程是代码集成的第一步,最重要的是怎么验证这些集成是正确的,就需要一些好的实践了:

1. 开发人员对自己编写的代码添加足够的测试覆盖率。这是基本,基本最无敌:一来验证代码的正确性,二来防止被误更改。
2. 每个人提交代码到代码库之前在自己的机器上保证单元测试都能通过,很耗时集成测试和E2E测试可以更多的交给CI去跑。
3. 借助一些CI工具(见上文),将代码集成的结果反馈展示在团队所有人都能看到的Dashboard上,一定要大家都可以看到。
4. CI定期检查代码库的更新,只要有更新,就要运行所有的测试。这里有个权衡:不耗时的单元测试每次全部运行,集成测试也要频繁的运行,耗时的E2E测试可以稍微执行少一点(比如设置夜间执行)。我们这个项目,是每次检查到更新就会运行所有的测试(单元测试+集成测试6分钟,E2E测试30分钟)
5. CI如果没有通过,所有人都应该停止向代码库中提交代码,直到CI被修复,所以如果CI挂了,能够及时通知相关开发人员,要第一时间修复。
6. 所有测试通过之后,CI负责自动化部署到不同的环境(Test,开发团队测试环境;Staging,客户ShowCase环境;UAT和Production,用户验收测试环境和生产环境,通常开发团队没有权限),并正常启动所有的服务。

下面是我们CI的Dashboard,使用了一个Chrome插件BuildReactor(如果加载不了就说明需要翻墙)将Go的多个Pipeline集中展示出来。


Retro

团队专注于交付目标,埋头干活的同时,也要懂得停下来总结过去,并更好地抬头看路。

Retro是Retrospective的简写,即回顾。团队通常以回顾会议的形式进行,大家坐在一起,对过去的这段时间里,我们Team的工作状态(团队合作,技术实践,团队氛围等)做一个总结,它有一点基本思想:对事不对人,大家思想自由Open。如何做到这一点,就要说说我们Team的做法:

1. 确认构建安全的环境。怎么讲呢,就是每个人都是觉得当前的会议是可以自由发表意见的,而不是因为某些人(比如说不友善的Leader)而不敢发表意见。开始前每个人对安全系数打分,1~10分,如果平均分数偏低(比如低于6分),需要将Leader从会议中"驱赶出去",直到大家觉得安全了才好。
2. 建立几项总结指标(Well, Less Well,Suggestion,Action),大家分别对前三项提出自己的看法。第四项是综合所有前三项的结果总结出来后面要做的事情。
3. 使用Sticker纸片(下文图中有),最好是用马克笔写(这样一张Sticker就不能泛泛无边的写),一张Sticke写上一个点的内容即可。
4. 时间控制在5分钟以内,每个人自己将Sticker按照分栏贴好,然后Facilitator(通常是PM或BA)开始带着大家过每一栏的Sticker,对Less Well栏中,将同一类的问题归纳起来,总结出相应的解决措施。
5. 将Action栏中的Sticker指派Owner,并落实。
6. Retro建议进行的周期为一个月,如果跟客户关系融洽且相对容易参与进来,可以将客户Involve进来,然后一起构建一个安全的环境(有可能因为大家的打分较低,客户不得不“出场”,所以客户参与不是必须的)。

说得天花乱坠,没有行动,犹如竹篮打水。Retro这个环节最核心的产出物是Action,团队共同一致商量出来的措施,有没有效果就在于行动了,所以Action分配了Owner之后,一定要跟踪这些Action有没有落实执行。一方面,需要Owner拥有高度的责任心和执行力,尽职将这些Action落实执行。

Retro的细节因团队而有些差异,但它的理念是一致的:总结过去,做的好的方面继续保持及加强,做的欠佳的方面一起讨论改进措施,并尽全力落实。Retro让团队在实践中摸索出适合团队的最佳实践,引导团队和个人不断自我完善,追求卓越。

我们Team的一次Retro


总结

这是我参加的一个关于敏捷实践很完善的项目,个人亲身经历了这些,深深体会到这些敏捷实践带来的益处以及个人的成长是非常大的。敏捷很好,但不只在于这些流程形式,在形式背后,我们应该深入思考这些实践是否真的让团队变得高效?让交付变得更加顺利?每个团队都是不同的,不必拘泥于这些流程形式,而是要追求这些流程产生的真正价值与意义。

PS:文章中提供的链接在有网络的情况下如果不能访问,确认自己是否可以翻墙,如不可以,切勿较真。


术语注释

  • PM:Project Manager,项目经理
  • BA:Business Analyst,业务分析师
  • TL:Technical Leader,技术领导
  • QA:Quality Assurance,测试人员
  • DEV:Developer,开发人员
  • UX:User Experience,用户体检设计师
  • AC:Acceptance Criteria,验收条件
  • UAT:User Acceptance Test,用户验收测试
  • Retro:Retrospective,回顾会议
  • TB: Team building,团队建设

文章已经过完善发布于InfoQ,阅读InfoQ文章

推荐阅读更多精彩内容