标签:
为了更好的阅读体验,欢迎访问 作者博客原文
EUMs(End User Monitor System)是一个在线的物资跟踪监控系统。由ThoughtWorks团队为Unicef(United Nations International Children’s Emergency Fund,联合国儿童基金会,客户)提供的一套完善的软件交付服务。
该系统为资助物资的跟踪与监控提供了完整的网络解决方案。整个流程涵盖了Unicef对物资来源的管控、库存管理、物资下发与跟踪、Unicef与IP(Implementing Partner,合作伙伴)的协作沟通、IP对运输结果的反馈(生成报告,警告通知,短信互动,邮件通知),以及IP对物资的二次分发后的记录跟踪与监控。
该项目属于海外独立交付项目,整个开发过程由ThougthWorks团队负责管理。好了,项目信息只能透漏这么多了,不然客户要找我我打官司了。
ThoughtWorks提供完整的交付团队(PM
, BA
, TL
, QA
, DEV
),团队为颇具代表性的敏捷团队,规模10人左右。Unicef团队主要接口人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
。每个人在上这个项目之前都是Python
盲。所以我们是在没有任何Python
编程语言背景下介入,另外因为从其他团队接手过来要立即继续开发(实际上是为前一个团队填坑,或者是救火)。我们的技术
和业务
扫盲期很短,这极大地体现了团队成员的学习能力,而我的周末和晚上几乎用来啃书和Coding了。
项目之所以成功交付,核心在于人,而良好的敏捷流程与实践也是不容忽视的。
早在2001年,17位追求卓越的志愿者聚集在美国犹他州雪鸟独家圣地,讨论一个新的软件开发趋势,它被称作轻量型软件开发过程
,后来他们将它定义为敏捷
,并且发布了敏捷开发宣言:一种把一人为本、团队合作、快速响应变化和可工作的软件作为宗旨的开发方法
。敏捷宣言可以总结为四句话:
1. 个体与交互 优于 流程与工具
2. 客户协作 优于 合同谈判
3. 响应变化 优于 遵循计划
4. 可工作的软件 优于 面面俱到的文档
敏捷开发的核心就是在一个高度协作的环境下,不断的通过反馈来进行自我调整和完善
。重点强调的是协作
和反馈
,协作体现在团队与客户之间的协作,团队成员之间的协作。反馈则是在开发中的任何环节,包括代码质量、自动化测试、部署、项目进度、需求变更、客户验收等,而且反馈越快越好。有句土耳其谚语这么讲的:"不管你走了多远,错了就要重新返回"
,所以我们越快得到反馈,就能越早确认自己有没有走错路。如果没有错,我们会更加充满信心。反之,及时做出调整,让成本最小化。
我们是一群快乐的逗比,快乐的人做出来的事情也是让人快乐的。逗比们聚集在一起,探讨出一套适合于逗比团队的敏捷开发流程,每个人都愿意遵守并维护这个工作流程,并且在流程中不断追求最佳的实践,来保证我们的项目的交付进度和软件的质量。
项目中实践主要有
逗比团队的实践也都是围绕着协作
与反馈
展开。
IPM(Iteration Plan Meeting),迭代计划会议主要是跟客户保持沟通与信息更新的一个会议。
敏捷宣言里面有一条:客户协作优于合同谈判
。在Scrum团队中有一个角色叫做产品负责人,Ta的核心职责是确保业务需求的清晰和透明,保证开发团队对业务有足够的了解,并将这些待完成的业务需求(Story)按照优先级排列出来,按照任务卡的方式来驱动团队的开发。并在客户需求有变更后能够第一时间告知团队以做出调整。
在我们团队中,这个角色就是一开始提到的BA。她是IPM主要参与人,另外还有Tech Lead会一起参与讨论(团队中每一个人成员都是可以参与进来的)。IPM按照团队指定的迭代的周期,通常是两周,每隔两周跟客户接口人一起约一个时间,主要讨论以下几个方面的内容:
1. 下一个迭代的Story。
2. 对下一个迭代的期望。
3. 团队的人员可用性。
4. 风险的评估总结。
通过这种会议,能够让客户对我们团队状况有一个清晰的了解,而且客户对我们下一个迭代要做的功能有了整体的把控,一起设定好期望,这样也会大大降低风险。
跟客户建立信任关系是基础条件,而让客户保持愉悦,也是项目成功交付的助推剂。
客户是位于非洲东部乌干达的子民,5个小时的时差没有造成太大的沟通障碍,他们也没有参与到我们Standup中来。所以我们团队在与客户沟通上处理两周一次IPM和Showcase,增加里一个每天的Catch up环节,在客户上班后的固定时间一起开个小会,会议时间跟Standup差不多,主要涉及内容有:
1. 我们团队昨天的更新.
2. 客户昨天的更新
3. 确认Story。如果有变更,能及时作出调整。
4. 提醒客户使用我们开发出来的功能,以便我们尽早得到反馈。
5. 一些节日的问候,嘘寒问暖,表达我们团队的关怀。
所有这些都是让客户有非常强烈的参与感,以及让他们对项目整个进展的把控(他们会觉得自己才是项目的主导者),增强他们的信心以及对我们的信任。另外让客自己己决定功能实现以及及时验收功能,这样也降低了需求变更和打回的风险。最后一条,则是润滑剂了,能够在客户良好的信任的基础上,保持合作关系的轻松愉快,这会为项目的成功交付使上劲。
并不是每一个项目都会有这个实践,有些独立交付的项目,他们每日站会的时候客户也会参与进来,就不需要额外单独的时间去做这件事情了,而有些项目,因为特殊性,客户可能不希望这么频繁的Catch up,这时候需要团队灵活变通,与客户一起商讨出一个合适的时间周期,做出一些权衡,让客户自身觉得舒服。总之,Keep住的一点是:
保持跟客户的信息沟通,尽可能早的得到客户的反馈,保持良好的客户关系
在一个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:
不管客户有多忙,也要定期让客户确认自己的期望是否得到满足。在签订合同前,要跟客户达成一致:Showcase的地位不可动摇。
Showcase就是给客户演示我们上一个迭代已经完成的功能,它的宗旨是及时得到客户的反馈,确认团队的产出是否满足客户的期望,降低需求变更返工的风险。Showcase从项目开始时周期性地进行,并直到项目交付。这个时间间隔是基于团队设定的迭代周期,我们团队是两周一次。团队跟客户安排一个远程会议(如果是在客户现场,一些参与讨论效果更好),主要涵盖了以下内容:
1. 跟客户确认上一个迭代的Story列表。
2. 项目目前的交付状态。是否正常进度,会不会延期。
3. 演示上一个迭代完成功能。在线系统演示,需要一个staging环境。
4. 客户对功能确认,对达到期望的story签字,反之。我们记录下问题,并修改,再次确认签字。
试想一下传统瀑布开发模式下,一个功能的演示通常是在所谓的里程碑节点的时候,此时项目或许开展了半年或一年甚至更久,客户这个时候见到自己的系统,简直会惊叫起来,原来这压根不是他们想要的东西(因为客户一开始都不知道自己要什么),即便开发团队严格按照预先的设计文档,这是一个灾难,而这种灾难也时常发生,导致大量的工作白费,且很难挽救。
敏捷开发可以规避这种灾难性事件的发生。而Showcase在敏捷开发中是一个不容忽视的环节,它契合了敏捷宣言中的拥抱变化优于遵循计划
。Showcase能够让团队在每个迭代完成后及时从客户拿得到反馈,对变化做出快速的响应,避免了劳动成果的浪费以及方向的偏离,也能最大化让客户的期望得到满足。
或许有些客户不愿意两周搞一次,他们觉得太频繁,尤其是国内之前跟瀑布流方式合作的客户。这个时候,团队可以就这个迭代周期进行变通调整,通常建议的是1~4周,不宜太长,过短也没什么效果,两周是我们推荐的迭代周期,至于如何权衡这个时间,有两点可以参考:
1. 在探索中找到适合团队的迭代周期,如果发现每个迭代时间不够用,要么是story划分太大,要么是迭代周期太短,这时需要根据几次的平均结果做出调整,适当扩大迭代周期,或者更合理的拆分Story。
2. 如果Showcase的时候功能背离了客户的期望,通常是因为迭代周期太长。因为用户的需求以及团队对需求的理解都在随着时间的推移而变化,导致发布时的产出并不是客户需要的。这个时候,可以考虑适当缩短迭代周期,让反馈来的更快更舒缓一些,而不是更慢更猛烈。
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,逗比们说:健身无处不在~
结对编程的开发速度通常小于简单地将一个人的开发速度乘以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在我看来是一个存在争议的主题,因为在一个连测试的没有的代码库中(多数客户也不关心测试代码,他们通常只想要看得到的功能),它的立身之本就不复存在了。我经历过只有纯手工黑盒测试的项目,没有单元测试、没有集成测试、没有E2E测试(测试金字塔, Martin Folower),所以TDD无从谈起。我也经历过客户要求测试覆盖率的项目,有专门的测试覆盖率工具()来检测代码库,有的甚至集成在CI上作为一个硬性指标。
我们EUMs项目接手过来的时候,测试覆盖率还是挺高,据不完整统计,数据达到了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是在珠海金山客户现场。因为项目是基于契约的前后端分离开发模式,ThoughtWorks这边后端就我一个人,带着一帮金山的兄弟写后端代码(基于Springboot),每天组织大家一起做Code review,挨个过当天的Code。Review过程中总会发现一些需要改进的地方,以及一些好的实践也能在团队中形成共享。比较好的现象是,客户方的Leader都高度信任和认可我们,大力支持这种实践,而给力的金山兄弟也能每次将问题记录下来并作出改正,所以日复一日,整个代码库的质量有显著的提高。
在EUMs项目中,我们有每天的Code Review(因为一些其他原因,并没有天天进行)。因为我们有3对Pair,时间定为1小时,实践证明,Code Review能带来的好处有:
1. 让每一个人提高警惕:自己写的代码并不是只有自己看的,所以要督促自己做好。比如规避不想写测试,代码耍酷等。
2. 共同找出代码的坏味道(命名规范,代码整洁,API内聚性,面向对象设计),及时做出改正,提高代码库的质量,有助于后期扩展和维护。
3. 让团队成员知道他人在做什么以及怎么做,分享好的编码习惯和技术实现,有助于团队整体进步。
Code Review适合安排在下班前,一方面,大家经过一天的高强度的思考与编码,适当停下来,看看其他人写的代码,同时将自己代码讲解出来,还能意外的获得一些灵感,或许能解决自己面临的阻碍(你面临的问题,其他人可能已经解决了)。另一方面,如果这个时候发现代码的坏味道,需要改进的地方,下班后可以花少量时间作出更改。
为什么我说用下班后少量的时间呢?因为这些通常属于自己成长过程中欠下来的技术债,花点时间取得进步,应该不会有人会觉得这是剥削吧,而且自己需要对自己的成长负责!
Code Review也是需要时间成本的,根据团队的规模1~2小时(5~10个开发人员)。对于规模很小的团队,可以适当减少Code Review的时间和频率,如果团队经常Switch Pair,也可以适当减少Code Review的时间。不管怎样,我都强烈建议进行Code Review,形式可以不拘一格:整个开发团队或者俩俩搭档。
关于Code Review,我总结了一些好的实践:
1. 团队一起拟定一个开始时间和时长,并落实到位,保证团队成员的参与度和Focus。
2. 短时间的描述自己的Story业务,主要Focus在代码上。
3. 持续跟踪记录,并获取反馈。这需要有一个人记录问题(可以按天轮流),结束后交给Owner执行更改,并且下一次Code Review的时候先过上一次的更改。
4. 必要的时候拉长时间,条件允许下建议在一个有大显示器的会议室中进行。
下面是某个时刻,我们Team四个人正在专注的讨论为一个函数取个更好的名字(猜猜谁是表情帝??):
没有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是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的细节因团队而有些差异,但它的理念是一致的:
总结过去,做的好的方面继续保持及加强,做的欠佳的方面一起讨论改进措施,并尽全力落实
。Retro让团队在实践中摸索出适合团队的最佳实践,引导团队和个人不断自我完善,追求卓越。
我们Team的一次Retro
这是我参加的一个关于敏捷实践很完善的项目,个人亲身经历了这些,深深体会到这些敏捷实践带来的益处以及个人的成长是非常大的。敏捷很好,但不只在于这些流程形式,在形式背后,我们应该深入思考这些实践是否真的让团队变得高效?让交付变得更加顺利?每个团队都是不同的,不必拘泥于这些流程形式,而是要追求这些流程产生的真正价值与意义。
主导项目成功交付的核心因素还是人,
以人为本
在软件交付项目团队中也是非常适用的。
ThoughtWorks中,唯一相同的是每个人都有独自的个性和特长,那么这些有个性的小伙伴们是如何良好地在一个团队中工作的呢,除了大家比较强的自我管理能力之外(对TW的价值文化的认同,自我管理和自我驱动力较强),也需要有意识的搞一些团队建设工作,特别是Team Leader(PM, TL)要兼顾团队建设方面的职责,思考如何让团队更快地成长起来,以及营造更融洽的团队氛围。关于团队建设,我翻译过两篇关于TL的文章:[高效技术领导的5个锦囊妙计]({{ site.url }}{{“/5-tips-for-being-an-effective-tech-lead/”}}),[初次做技术领导的三个陷阱]({{ site.url }}{{“/3-common-mistakes-of-first-time-tech-lead/”}}),欢迎阅读。
学习的乐趣在于分享。一个了不起的团队需要营造出一种浓厚学习的氛围,每个人都在驱动自己去学习提升,努力将所学的知识分享出来,自己成长了,团队也在进步。
我们Team在第一次Retro中总结出来要执行Team Session,简单来讲就是某个人分享一个主题,将自己Get到的技能通过演讲的形式在团队中分享出来,让团队每一个人都能获益。分享的主题可以是技术和非技术的(技术占得比例大),主题与项目正在使用的或者即将尝试的技术栈相关,也可以是在开发过程中的一些实践总结。
我们最开始商量出来的方案是:每天中午15分钟自由讨论时间,每周周五中午1:30~2:30有一个主题Session,由不同的人去Take。项目交付之后,再回过头去看,是有一些可以提高的地方的,比如说每天中午15分钟这个很少聚在一起讨论(刚吃完饭,休息,看看新闻等),这个自由讨论其实可以放在Code Review中穿插进行。而每周的主题Session,一开始的时候有几次分享,中间很多时候是空着的(不同的原因),整个项目下来,我也只做了一次Session(时间2个多小时)。所以在后面我们做了一些总结,讨论出方案:
1. 每周指派一个Session的Owner,Owner需要对这周的Session负责,自己本周至少有一场主题Session,也可以有多场(非常欢迎的事情),也可以邀请团队其他成员甚至团队外的人来讲Session。
2. 如果Owner因为有其他的原因没有任何Session,需要团队其他成员同意。(实在有事,大家还是可以理解的,但是本着我们黑人到底的精神,至少会想出一些惩罚措施,比如说请吃冰棍。比如说请吃新辣道,额,广告一下,新辣道是一家火锅店)
3. 鼓励在团队外做Session,比如公司级别以及社区级别的,将团队传播出去,让我们团队更具有影响力。这就需要更多的练习实践,而Team Session是一个好的练习机会。
经过改良后,效果很好,大家的参与度较高,目前一直沿用中。
PS:在ThoughtWorks这种扁平化组织中,几乎没有什么东西是可以强制的,这个是我们Team共同讨论出来的方案,不具备强制性。大家达成一致:8个人,平均每人两周一次Session,不但可以较轻松愉快的完成,利己利人。
Team Leader组织定期一对一的交流,能够更好地把握团队成员的心理状态和成长预期,从而更好地把控团队的成长方向及达成交付目标。
One2One,通常是PM定期(一个月)跟团队成员的一个单独面对面交流的机会。时间一般控制在半个小时,主要了解每个人对目前团队的看法,提一些自己觉得做得好的以及不好的点,聊一聊自己在这段时间工作的状态,以及每个人目前在团队中的成长是否符合自己预期。
我在One2One Meeting的时候,除了上述内容,我会加一个索要反馈的环节。了解一下PM视角中的我以及团队的状况,了解一些PM视角中其他成员的优势,以及给自己的一些成长建议。
身体是革命的本钱。老生常谈了,不说也懂的。
我在加入ThoughtWorks之前就从一些途径了解到TWers在日常工作中有平板支撑环节,也就是本文刚开始的时候就提到的运动文化。2015.03加入ThoughtWorks以后,发现并不是每一个Team都会集体做运动,而我是一个非常喜欢运动的人,也从运动中获益不少。所以,我不管走到哪个团队,我都会组织大家一起做平板支撑,让我感到意外的是,每个人的参与度很高,这也一直在鼓励我在Team中将运动进行到底。
运动会耽误工作时间吗?这是一个值得讨论的话题。简单算一笔账,30s * 10r + 10s * 10r + 10s = 410s,一共不到7分钟。七分钟,并不会耽误工作的时间,那么它带来的好处呢,从大家的反馈中说明一个事实:腰椎和颈椎得到了放松
、工作效率提高了
、团队气氛变好了
…
关于运动,有一些简单的实践:
1. 运动主要是活跃团队气氛,让大家忙里偷闲一会儿,同时让身体得到锻炼放松。切不可顽固不变通,大家开心的参与到其中,中间聊一些幽默风趣的话题(这个跟团队成员有关,比如说我们Team几乎每个人都很幽默,尤其是“脑残”的PM和TL)。
2. 每天在一个固定的时间开始运动,鼓励每个人都参与,但不强制。
3. 运动的强度,取决于多数人的反馈,不可强度太大,也不必太轻松。
4. 欢迎其他团队的成员加入,鼓励他们去组织自己团队做运动。
5. 团队众筹购买瑜伽垫,垫着会让胳膊肘子更舒服一些。
6. 对于平板支撑,胳膊肘子成90都,支撑的过程不要让肘子有蠕动(皮肤细嫩的女生会被磨破皮),收腹,保持臀部腰部成一条直线,切记不可让腹部吊着,这样腰部受力对腰不好。
7. 平板支撑的支撑时间不是越长越好,间隔着休息,建议支撑时间20~30秒,休息时间10秒,6~10组。
下面是我们Team的Workout剪影:
抛开工作聚在一起,放松的玩耍聊天吃饭,是为了保持更好的工作状态和团队氛围。工作也是生活中的一部分,不必让生活一直处于紧张状态。
Team Building,可以理解为团队建设,在实践中最常见的实践是大家一起聚个餐,玩个密室逃脱什么。在我司,每个人工每月都可以使用一定额度的经费,进行团队聚餐娱乐,也就是做一些工作之外建设团队的事情。这么做主要是让团队能够以放松的状态聚在一起,除了工作,天南地北,幽默逗乐,样样都来,酒饱饭足之后(基本上不喝酒),重新高效的投入到工作中。很多国内的公司也有聚餐这回事,他们通常是庆祝什么活动和功勋,而我们是为了建设团队。
Team building每月一次,以轻松为主,有吃饭环节,也有挑战冒险的娱乐活动,根据团队的意愿不一样。TB的重点是团队成员聚在一起做一些有趣的事情,培养团队成员的感情和凝聚力。比如说,我们有一次去玩密室逃脱,整个Team都在绞尽脑汁破解模式的关卡,知道胜利走出密室那一刻,我们的情感也会增加几分。形式各异,只要不太占用工作时间,一般是半个工作日以内,也可以选择节假日,当然只要达成一致。
这个是因为我司文化的特殊性,鼓励这种活动,并给与经费支持。不同的公司,团队也可以采取这种方式去把大家聚在一起,可以是领导请客(一般可以报销),可以是Team AA。
下面是我们Team building的图集:
团队建设的核心是增强团队的战斗力(技能)和凝聚力(氛围)。工作上不必太死板苛刻,学会融通,多一些包容,尽量让每一个人特长都能发挥出来,让每个人感觉自己的存在是能为团队创造价值的,并且自身能力也能得到成长。也不要遗忘对其他人发出赞美与肯定,还有生活上的关怀。
当然,如果团队中有几个快乐的逗比那是得天独厚的资源,而我们Team中几乎都是逗比,也很快乐。
我把技术实践放到最后,并不是说技术在项目中不重要,相反,技术很重要。由于项目的特殊性,我么接手项目的时候,技术选型都已经定了,好在项目在技术上不算落后,还采取了一些较新的技术。但也有一些坑,比如说使用的RapidPro。
EUMs是一个Web项目,相关的技术实践主要涉及到Web Client、Web Server、第三方服务、依赖管理与构建、测试、部署等。
Web 客户端采用了Single-page模式,所有的数据都是通过请求后端RESTful API来获取数据进行渲染。运用了目前较为广泛使用Angularjs框架。同时引入了BootStrap,使用HTML5和CSS3(SASS)。这些都是比较常用的前端技术。
服务器端使用Python语言开发,应用了Django框架以及Django REST framework,搭载了PostgreSQL数据库。
另外附加了一个团队开发的内部微服务Contact,该服务不对外暴露端口,只为EUMs系统提供服务。采用了NodeJS + MongoDB。
之前一直做Java开发,使用了Python以及Django之后,动态语言在做Web项目的时候效率是非常高的,而Python优美简洁的语法也深得我的喜欢。Django是一个比较流行的全栈Web开发框架(集 持久化,事务,权限,AOP,MVC,模板引擎等 于一身),与Django同类型的有全栈的Web2py,轻量级的Flask,等等。
在服务器端,为了做一些任务调度的工作以及查询性能优化,使用了一个使用python编写的分布式任务队列工具Celery做任务调度。利用Java编写的实时搜索和分析工具Elasticsearch来优化数据查询。
系统还集成了客户提供的一个名为VISION的服务,我个人很少涉及VISION,它只是客户那边用来提供生产数据的服务。值得一提的是RapidPro这个系统,它的官方介绍如下:
RapidPro is an Open Source platform that allows anyone to build interactive messaging systems using an easy visual interface
简单地说就是一个短信信息交互系统,只想用一句话描述:API真的不好用,不建议使用
。国内很少用这玩意,这里推荐一个产品,我司之前金数据团队开发的金数据(现在该团队已经被其他公司收购)。
项目中存在很多依赖的管理,如果人为手工去管理,这几乎是一项浪费时间而又没有任何好处的事情,好在有很多好的包管理工具可用使用。
后端Python使用了pip。前端则bower和npm管理依赖,使用grunt作为前端构建工具(现在我司前端工程师更愿意使用gulp)。
好的工具能让开发事半功倍,所以花些时间去了解这些工具的用法也是有较大价值的。
前文TDD以及CI已经强调了测试的重要性。我们同样需要一些测试工具来让我们的测试更加容易的编写和维护。
服务端则使用了Django提供的TestCase,用于后端的单元测试和API测试(集成测试)。前端使用jasmine配合我司开发的selenium进行单元测试及E2E测试。
好的实践中,部署应该是由CI服务器自动化进行的。在所有测试通过之后,将要部署的包部署到指定的环境,正常启动所有的服务,并自动化所有过程。
我们已经做到了自动化部署,这里有一个加分项,就是我们还是用了容器部署方式,使用了较为流行的docker,这为我们的部署减少了很多工作,以至于我们后期Release期间大家的节奏跟前期没有太大的区别,往不同的国家部署的时候,只用部署构建好的Image,隔离了生产环境的差异性。达到了Build once, Deploy anywhere
的水平。
完成一项工作可以有多种不同的技术来实现,技术选型在项目开始阶段非常重要,并不是越流行的技术栈就越好。在选择技术栈的时候,要考虑到的一些因素:
1. 核心是能否解决我们的问题,以及解决效率高不高。
2. 该技术是否还在维护中,是否稳定可靠。
3. 团队成员对该技术的熟悉程度,学习成本是不是很高。
本文发布出来的时候已经距离EUMs成功交付有三周左右了,其中Standup中的场景是发生在近期(EUMs项目期间使用的Token最多的是一个美式足球)。所写内容是我在EUMs项目中亲身经历,这是我经历的一个让我很深刻的敏捷开发团队。我们交付了EUMs,但我们的团队仍然在继续。我们努力打造了团队自身品牌,有我们专属的Logo和名字。当你听到ThoughtWorks的时候,你应该知道在ThoughtWorks里面,有一个逗比团队,她的名字叫DiNPO。
PS
1. 本文截图涉及到多个TWers的照片(其中有大牛熊杰),都经由同事的许可,遂敢于毫无顾忌的发表。
2. 文章中提供的链接在有网络的情况下如果不能访问,确认自己是否可以翻墙,如不可以,切勿较真。
更多内容,欢迎访问作者博客
标签:
原文地址:http://blog.csdn.net/ysjian_pingcx/article/details/51302548