<<互联网敏捷DevOps和自动化之2.精益敏捷>>
Scrum 是一个用于开发和维持复杂产品的框架 ,是一个增量的、迭代的开发过程。在这个框架中,整个开发过程由若干个短的迭代周期组成,一个短的迭代周期称为一个Sprint,每个Sprint的建议长度是2到4周(互联网产品研发可以使用1周的Sprint)。在Scrum中,使用产品Backlog来管理产品的需求,产品backlog是一个按照商业价值排序的需求列表,列表条目的体现形式通常为用户故事。Scrum团队总是先开发对客户具有较高价值的需求。在Sprint中,Scrum团队从产品Backlog中挑选最高优先级的需求进行开发。挑选的需求在Sprint计划会议上经过讨论、分析和估算得到相应的任务列表,我们称它为Sprint backlog。在每个迭代结束时,Scrum团队将递交潜在可交付的产品增量。 Scrum起源于软件开发项目,但它适用于任何复杂的或是创新性的项目。
Scrum流程如下图:
SCRUM框架包括3个角色、3个工件、5个事件、5个价值
3个角色
产品负责人(Product Owner)
Scrum Master
开发团队
3个工件
产品Backlog(Product Backlog)
SprintBacklog
产品增量(Increment)
5个事件
Sprint(Sprint本身是一个事件,包括了如下4个事件)
Sprint计划会议(Sprint Planning Meeting)
每日站会(Daily Scrum Meeting)
Sprint评审会议(Sprint Review Meeting)
Sprint回顾会议(Sprint Retrospective Meeting)
5个价值
承诺 – 愿意对目标做出承诺
专注– 把你的心思和能力都用到你承诺的工作上去
开放– Scrum 把项目中的一切开放给每个人看
尊重– 每个人都有他独特的背景和经验
勇气– 有勇气做出承诺,履行承诺,接受别人的尊重
SCRUM理论基础
Scrum以经验性过程控制理论(经验主义)做为理论基础的过程。经验主义主张知识源于经验, 以及基于已知的东西做决定。Scrum 采用迭代、增量的方法来优化可预见性并控制风险。
Scrum 的三大支柱支撑起每个经验性过程控制的实现:透明性、检验和适应。Scrum的三大支柱如下:
第一:透明性(Transparency)
透明度是指,在软件开发过程的各个环节保持高度的可见性,影响交付成果的各个方面对于参与交付的所有人、管理生产结果的人保持透明。管理生产成果的人不仅要能够看到过程的这些方面,而且必须理解他们看到的内容。也就是说,当某个人在检验一个过程,并确信某一个任务已经完成时,这个完成必须等同于他们对完成的定义。
第二:检验(Inspection)
开发过程中的各方面必须做到足够频繁地检验,确保能够及时发现过程中的重大偏差。在确定检验频率时,需要考虑到检验会引起所有过程发生变化。当规定的检验频率超出了过程检验所能容许的程度,那么就会出现问题。幸运的是,软件开发并不会出现这种情况。另一个因素就是检验工作成果人员的技能水平和积极性。
第三:适应(Adaptation)
如果检验人员检验的时候发现过程中的一个或多个方面不满足验收标准,并且最终产品是不合格的,那么便需要对过程或是材料进行调整。调整工作必须尽快实施,以减少进一步的偏差。
Scrum中通过三个活动进行检验和适应:每日例会检验Sprint目标的进展,做出调整,从而优化次日的工作价值;Sprint评审和计划会议检验发布目标的进展,做出调整,从而优化下一个Sprint的工作价值;Sprint回顾会议是用来回顾已经完成的Sprint,并且确定做出什么样的改善可以使接下来的Sprint更加高效、更加令人满意,并且工作更快乐。
现在软件领域三大俗,说的是敏捷、大数据、云,说的越多的往往也是处于成熟中,或者需求强调的,我所遇到的项目有幸几乎都触及到这些俗气的元素。
不得不说,市场竞争和各厂商客户意识的提升,现在的用户已经被宠坏了,以前我们叫挖掘需求,也就是客户是有自己需求的只是表达传递的完整性问题,通过一定的需求工程的方法把这些需求给定义出来,变成软件需求就好了。现在客户往往是不知道自己想要什么的,他们往往会提出"高大上"的需求,比如:"我要一款软件,使我的业务管理水平达到行业的标杆,至少这个软件具体应该有什么功能我也不知道,我们预算是要多少有多少,关键是要做好,要在最短时间内最好是明天交付出来,否则后续取消与你们的合作。",相信很多开发人员听到这些"需求"都会感到无所适从。
不幸我就遇到类似的一个项目,客户需求就是一句话:"在国家批下来的预算范围内,给我们做一个本行业标杆性的软件,需求嘛你们自己研究研究,我们就看效果,但必须在 1 个月内上面领导下来参观前完成",经过初步分析,参考这个行业的同类软件,至少涉及到集群数据存储与分布式检索、广度爬虫、自然语言识别,当然还有面向客户的业务应用系统。而且作为公司的战略项目,关系公司后续的市场开拓,老板发话:"必须成功,还要注意成本"。
大家现在知道了,又遇到有中国特色的项目了,"需求范围不确定,资源限死、时间限死",大家会说不是战略项目吗,资源怎么会限死呢?但是请大家想想,客户预算是一定,根据财务核算,老板要拿的利润也是刚性的,还能剩多少,大家可以发挥想象了。考虑该如何实施这个项目时,似乎传统的项目管理从计划来分配资源模式以及采用瀑布型的开发方式,根本行不通。就在我焦头烂额之际,我想起了解过的一种开发模式:
Scrum 开发模式使得我们能够专注于如何在最短的时间内实现最有价值的部分;
Scrum 开发模式使得我们能够快速的经常的监督实际产品发展的状况;
Scrum 开发模式使得团队按照商业价值的高低先完成高优先级的产品功能,并自主管理,凝结了团队智慧创造出最好的方法因而提高效率 ;
Scrum 开发模式使得每隔一两周或者一个月,我们就可以看到实实在在的可以上线的产品。此时,就可以进一步的决定是继续完善功能实现更多需求或者直接发布了 。
这正是我想要的管理方法,也是敏捷界被采用最广泛的管理方法,但一般的 Scrum 显然也无法有效的应对此种情况了,还得自己完善和扩展。
项目开发过程的设计
图 1. 开发过程
针对这类客户应该是提供业务的解决方案然后再提供软件系统,因此整体的开发过程不能直接从用户需求开始,而应该从业务研究开始,如上图 1 的开发过程来实施。
在敏捷开发中对于需求的假设是认为,需求是涌现出来的,但我们知道架构设计能够开始是基于关键需求已经确认的情况下,而且在国内的环境下如果在需求不确定的情况下就开发,客户更可能随意的修改需求,而工期又限死的情况下,项目必然是会失败的。因此在中国的客户成熟度情况下,最好还是书面确认大部分关键需求后再开始做,否则,很多情况下会成烂尾楼。
为了能加快前期需求阶段的进展,必须有业务架构师来分解业务模块,不同的 PO 来负责各自业务模块的需求分析。当关键需求确认后,开始技术架构的设计,同时在技术架构的基础上进行迭代的开发。因此,整个团队的结构如下图 2:
图 2 .大型项目的组织结构
由规划经理来有序的协调和规划多个 PO 的前期工作,开发组由多个特性开发团队组成,由系统组完成整个软件架构设计,将系统按业务和技术进行切分,使得各开发团队间能够进行协同。
每个特性开发团队都是一个敏捷团队,均采用完整的 Scrum 的管理实践,同时采用持续集成、代码静态检查、代码交互评审的、验收测试驱动来进行质量的保证。单元测试的实践,由于时间紧研发人员都担心会影响项目进度,因为本身测试代码工作量也不少。因此我们没有按真正 TDD 方式去推行,而仅会要求针对问题最集中的模块和失败的用例涉及到的代码进行单元测试覆盖,目的是保证迭代过程中代码修改的完整性,而不是用于驱动设计,最终实际统计单元测试覆盖率仅 30%不到。先写测试用例再写代码的方式,在部分小组试过几次但大家都反馈很难适应。因此没有再继续要求。
具体的实践方法有很多文章来论述,这里就不再重复。
项目遇到的麻烦-需求
由于需求与开发团队是异步进行,而不是从一开始就紧密运作的。开发团队与规划组之间,开始并没有团队意识,还是按瀑布的阶段交付的思维来对待。所以,项目组开会时,开发团队与需求团队就经常发现摩擦。
开发要求需求人员将需求描述的非常细,否则不予接受。而需求人员由于在局方现场,要将需求描述的很细的情况下就需要耗费很多文档时间,而用户时间有限,所以希望能将需求描述简单一点,关键是需求人员将需求写的很细的情况下,开发人员在开发过程中任然还是需要不断的去沟通需求,毕竟靠文档完整表述还是有困难的。而测试团队先等待开发做完,再开始测试。于是开发、需求之间经常就需求文档细致问题无法高效协同,测试介入很晚,到测试时对业务不熟悉,只能希望开发出相关的设计文档来进行测试,效果很差。由于团队之间对立情况,反而加剧了对文档传递的依赖,项目进度慢了下来。
对此,我们认为这个是因为项目实践出来偏差,没有真正领悟,敏捷开发中为什么需求必须是讨论出来,而不能是通过一个详细设计文档去传达,使得每个成员都对需求来负责,而不是仅仅被动的接受。
对此,项目要求各团队的 PO,不再写详细的需求文档,而是出需求列表。强制要求,需求的传递必须通过需求澄清方式完成。
也就是需求、开发、测试人员,同时参与需求的分析工作。步骤如下:
需求人员列出所有的 product backlog 的 story,并进行排序;
开发、测试人员,听 PO 对每个用户故事进行讲解,注意 PO 不再提供详细需求的文档了,然后开发、测试人员可以要求 PO 对每个需求讲解清楚,直到听懂理解并能开始进行设计工作为止;
开发人员将 PO 讲解的需求给记录描述出来,需要包括基本的业务流程图以及接口说明,同时要求测试人员将需求的验收条件给写出来,整合成针对每个 story 的需求澄清文档;
由 PO 确认需求澄清文档内容的准确性,如果无误可以开始进入开发过程了。
通过这样的方式,可以节省 PO 详细需求文档的时间,同时将需求的责任分担到每个角色的身上。因为,即使再详细的文档,研发和测试人员 还是需要阅读消化同时也需要多次找 PO 确认。直接通过讲解确认,我们也称为"需求的三次握手"过程,开发、测试、需求人员,实际完成了对需求的传递、需求验证规则的统一,这时测试就可以再前期介入到项目中,对业务理解与研发处于同一水准,可以在业务层面帮助研发来纠正需求理解的偏差,考虑对异常场景的处理。
通过这种方式,研发的详细设计文档基本可以省略,但对于复杂性比较高超过实现需要 8 人时以上的 story 还是需要给出简要的设计文档,需求详细文档可以裁减掉,而且测试用例通过验收准则可以很快就转换出来。通过需求的澄清过程,而不是需求文档的传递来沟通,大大提升了项目前期的进展。
缺陷的处理
通过厘清需求的过程,整个团队开发比较顺畅了,但是在迭代中我们发现对于缺陷的处理存在问题。有一次项目整体的回顾会,各特性团队,均顺利完成了各自的 sprint 的任务,但有个团队却没有完成而且是 0 完成率,但是我们发现他们遗留的问题并不多,那么是什么原因导致的呢?经过分析我们发现,他们在 sprint 中对缺陷的处理确实是缺乏处理策略。如图 3 所示,story 遗留缺陷对应图
图 3 .某 Sprint 的 story 与缺陷的对应关系
我们在定义 story 的验收条件,是要求每个 story 不能遗留一般级别以上的缺陷。但该团队对缺陷的处理是:
先处理严重级别的缺陷;
缺陷集中到迭代后期再进行修复。
所以,当他们进行缺陷修复的排序时,将所有的严重缺陷都进行了修复,但是导致最后却是一个 story 都不能交付。因为,每个 story 都还剩一个一般级别的缺陷。而且,由于不是立即处理缺陷,导致缺陷处理周期变长,修复缺陷占用较大比例时间。等严重缺陷都修复完,已经到迭代结束期。导致所有的 story 都无法交付。
在此次,我们必须要认识到一点,我们每个迭代都要进行增量的价值交付,作为研发团队应该考虑如何在一个迭代中尽可能多的交付,而不是为了修复缺陷。所以,如果研发团队,在进行缺陷修复时,考虑先把一个 story 的缺陷全部修改完,再修订其他 story 的缺陷,应该可能交付 2 个 story 的,虽然对软件整体而言,缺陷没变,但是交付的商业价值却是更多的。
因此在后期,我们确定在迭代过程中:
必须树立尽量多交付价值的观点;
缺陷必须在发现时立即修复,不建议集中进行修复,因为缺陷的定位时间会随时间逐渐加长的,立即修复才是对进度、质量最有利的方式;
实在无法修复或确实需要时间修复的 bug,需要进行分析和规划,不能仅仅以故障的级别为修复的优先项,而是增量交付为核心关注点。
在团队中增加一个专职的 bug 修复人员,就是一旦 bug 出现,由专职的 bug 修复人员进行修复,其他人员继续 story 的开发,这个人员可以在不同迭代轮换。起初是在一个团队中采用,后来发现,这种方式也取得了很好的效率,所以,在所有特性开发团队中都采用起来。
Story 的切分
见下图 4,一般的业务系统都是按如下的方式进行横向的切分,也就是我们常说的流式结构,当某一层发生变动时,其他层可以保持不变。
图 4 .常见业务系统的结构
当到敏捷开发中队 story 的切分是基于纵向的切分如图 5 所示,也就是每个 story 都可以方便的从系统中整合与拆并。
图 5 .敏捷开发的纵向切分
采用这种结构,可以方便的进行增量交付,而且当一个有问题时,可以拆开不影响其他部分,非常适合敏捷开发增量的要求。
但在实际中需求并不是由一个个孤立的"用户故事"组成的,业务概念、业务流程其实是贯穿多个用户故事的,软件设计应该多从业务概念、业务流程的角度来思考;表面上看上去一个用户故事对应一组界面,其实界面之间是很可能有重用和共享部分的;业务逻辑层中的一些类很难将其分拆开来与用户故事、界面组一一对应,存在交叉、共享和重用的可能;数据层中的某张表,通常会支撑多个用户故事而不是一个用户故事。
例如,以下列出来的可能都需要从软件架构上做一个整体的考虑:
权限控制;
性能要求;
日志记录;
工作流;
全文搜索;
多数据库支持;
搜索引擎优化;
因此,在每个 sprint 的 backlog 的安排上,不同的整合和考虑会对项目的进展速度产生很大的影响。PO 与架构师,必须经过深入的整合梳理与排序,而不是简单的对 story 进行罗列。如果说需求决定了软件的价值,那么设计包括对需求的安排决定了软件的成本。
目前敏捷开发中对于 story 的拆分也提到很多方式,一般来说如下几种:
第一种,按工作流进行拆分
第二种,从简单到复杂
第三种,按原子操作,如分解成:Create, Read, Update, Delete;
第四种,针对公共功能的系统,
大家可以参考这几种方式来灵活的处理 story 的切分问题,但注意,还要有全局观。
跨团队的处理
我们在一个大型项目中的架构如下图 6:
图 6 .某项目的软件架构图
由于有大量的底层技术结构,所以,我们在特性团队划分时,分成 3 个业务特性团队,这个团队主要是实现业务逻辑。而底层的,大数据存在和公共平台,是由另一个团队来独立完成的。这个时候,在任务的安排上和人员协同上就需要注意。
如:在界面上有一个查询功能,其中有部分数据,必须通过大数据平台来获取,又有部分可以直接通过 oarcle 数据库获取,还有部分通过 ES 集群就可以获取,这个时候就要注意。Story 可交付的定义,应该是系统能够集成交付,而不仅仅是上层业务可交付。
图 7. 团队中 story 与人员的对应
如图 7 所示,其中业务团队要完成 story2 时,其系统要平台团队的 story2 也要完成时,就会出现协同问题。因为,2 个团队分别按自己的标准在确定故事的优先级,可能 story2 完成的时间与业务团队的 story2 的时机不对,还是无法完整交付。
对于这类,应该临时将小王划归到业务团队 2,将小宋与小王的 story 进行协同,以达到交付的目标。在多个特性敏捷团队同时运作时,这种情况,可以建立虚拟团队的方式,来临时应对这类需求。
图 8. 建立多个敏捷团队关联协同团队
这样可以很好进行某个具体交付特性的协同,保证交付的完整性。
结束语
敏捷开发的实践,一直都聚焦在单一团队运作,但当往往很多系统规模,并非 10 个人团队可以在 要求时间内交付的。当团队规模大后,原来单团队的管理,并且团队间部分需求考分的交叉,原来的单一敏捷团队的管理方式会遇到一些麻烦。我给出了自己在大团队和技术复杂性团队的实践的经验,希望对大家有所帮助。