前言
去年为了了解敏捷开发流程和DevOps, 也看了《猎豹行动》这本书. 同样按照, 故事脉络、相关概念、个人感悟这几个模块来整理笔记.
故事脉络
一家金融服务公司, 为了更快地响应业务部门的请求, 更好地交付业务价值, 启动名为“猎豹行动”的行动计划, 落实敏捷转型.
要解决的问题:
- 开发模式依然以瀑布模型为主, 交付慢且昂贵, 业务部门对此不满
- 业务部门架构复杂, 各自的利益与兴趣点不同, 难以形成统一的优先级和需求意见, 对IT部门有不同的请求
- IT部门由于预算问题, 人员编制不足
- 流程烦琐、基础设施落后、自动化程度不足
- PMO部门承担所有项目的甲方, 为了维护部门利益, 在所有项目中做中间人角色, 不愿IT部门直接解除其他业务部门(最终用户), 但又不愿承担PO的角色
猎豹行动启动方案:
- 组织全覆盖的敏捷扫盲班, 让所有IT同事对敏捷开发有基本的了解, 审视当前的交付模式并找出改进点.
- 分析当前的瀑布模型开发:
- 痛点
- 业务部门
- 逾期交付、超支、缺乏透明度,不知道具体进度、很难变更需求、看到成品时项目已接近尾声、最终发现开发出来的产品不是他们想要的、殆误战机,丢失市场机会
- IT部门
- 过度承诺、难以一次性消化所有需求、惧怕需求变更、不断重做、后期压力巨大、加班
- 业务部门
- 导致痛点的原因
- 只有预算和目标交付时间是确定的
- 不确定因素
- 范围和具体需求、可能的需求变更、人员(放假离职)、估算的准确性、对现有系统的影响、服务器环境的搭建
- 存在的问题
- 需求分析花的时间多,开发时间被压缩
- 变更成本高
- 业务要在用户验收测试阶段才能看到成品,临近目标交付日期, 才发现产品不合要求
- 痛点
- 介绍敏捷开发模式:
- 迭代开发就是敏捷开发最重要的特点. 软件开发最重要的是搞清楚用户到底想要什么. 以两组蒙娜丽莎的完成过程图为例, 如果客户任务蒙娜丽莎的头最重要, 那上面那组的第二幅图就可以交付.
- 跟每个团队进行交谈, 了解团队痛点, 探讨具体改进方案.
- 总结敏捷开发给业务部门和IT部门带来的好处, 并给出敏捷启动建议:
- 围绕已知的范围和需求定义用户故事和建立Product Backlog
- 为用户故事排优先级
- 商定Sprint的长度
- 商定Sprint计划会议和评审会议的日程
- 商定发布计划
- 准备相应的辅助工具
- 组织针对业务部门的敏捷基础培训, 配合落实敏捷转型.
- 通过“棉花糖挑战”和“传硬币”两个游戏, 分别领悟简单设计、提早测试、快速反馈、减少批量, 提高交付速度的重要性. 把项目需求条目化, 定期排序, 确保有限的资源和时间用在最有价值的事情上.
- 从工具开始落地敏捷, 提升效率.
- 利用开源软件的优势, 站在巨人的肩膀上开发. 采用了以下工具, 如项目管理工具JIRA、知识管理工具Confluence、代码托管平台GitHub、代码缓存及管理仓库工具Nexus、持续继承工具Jenkins、代码静态审查工具SonarQube、自动化部署工具Ansible
- 针对人手不够, 而阻碍工具落地的情况, 采取以下措施:
- 通过工作坊和团队一起找出痛点, 列出所有改进点并进行优先级排序
- 每个团队每天划出一个固定时段, 半小时到1小时, 这段时间内, 所有团队成员放下手头的交付工作, 自行或组队摘取改进点进行实施, 并建立激励机制鼓励大家积极参与.
以团队共创形式开展工作坊:
what
- 和团队一起找出痛点, 列出所有改进点并进行优先级排序
how
- 主题介绍.
- 主要是确立目标.
- 头脑风暴.
- 每个人先列出实现目标的障碍和对应想法, 然后分成几个小组, 每个组把组员的想法, 都进一步提炼成几个想法.
- 排列组合.
- 对每个组提炼出来的想法, 再进一步归类.
- 提炼中心词.
- 对每类想法, 提炼中心词.
- 模型图.
- 思考中心词之间的逻辑关系, 通过关系摆放形成图形, 解读图形, 制定行动方案.
- 主题介绍.
通过工作坊, 发现以下问题:
- 1)业务请求跟踪性差
- 2)缺乏回归测试
- 3)手工部署
针对以上问题, 采取相应措施:
- 1)-1 JIRA记录所有的请求和需求, 建立可视板使进度可视化.
- 1)-2 每日站会围绕JIRA可视板进行,确认每天的优先级、进度、阻碍.
- 1)-3 通过Confluence建立项目文档和知识库. 使所有知识和信息透明化, 提升沟通和学习效率
- 2) 找出合适的自动化测试方案, 通过Jenkins每天自动执行全部自动化测试并发布测试结果, 结合SonarQube观测测试代码覆盖率是否处于上升趋势
- 3) 通过Ansible编写部署脚本, 实现部署自动化.
实施过程的阻碍:
- 遗留代码耦合度高, 可测试性低, 导致自动化回归测试落地缓慢.
- 上线流程烦琐, 倾向延迟修复版本的上线而造成更大的业务影响.
- 不管付出多少努力, 零缺陷和零风险都是不可实现的, 很多问题只有在生产环境才会出现. 做到真正的持续交付、频繁上线, 每次上线所涉及的变更范围缩到最小, 当问题出现的时候, 能更快地修复问题并把业务影响降到最低.
项目试点实践经验:
采用新交付方式, 规范并简化流程:
- 拥抱变化
- 适应任何需求变化以满足业务部门的最终需求. 拆分原始需求并快速交付其中最重要的部分获取反馈并及时修改
- 拆分
- 把大的需求拆分成最小可交付需求来缩短交付时间和实现持续交付
- 简化流程
- 最终用户与IT工程师直接沟通, 减少交接与签署, 不再依赖繁文缛节的文档. 业务部门可通过JIRA Service Desk直接提交需求, 规范交付文档, 使业务部门和IT部门对验收条件达成共识.
- PS: 以前老大也经常这么说,产品提的需求只是个解决方案,还需要跟业务沟通,把握真正的需求
- 透明可视化
- 需求与细节都记录在JIRA上. 通过看板可视化进度与阻碍. 定期汇报
- 改进服务
- 上线后业务人员可为每个交付评分和反馈意见
- 拥抱变化
基于产品的持续改进:
- 建立CI/CD流水线, 加快暴露集成问题
- 实现基于主干开发, 避免上线代码非测试过的版本等问题
- 特性开关控制新功能
采用敏捷估算预测交付时间, 迭代进行过程中, 通过燃尽图持续观察团队的交付速率, 并及时调整预测.
从满足对方要求的定制化接口到通过API开放数据:
- 采用演进式的设计方法和微服务架构.
- 先搞清楚对家需要哪些数据(可根据对家系统所要求的接口文件规格文档), 然后为此设计Process API, 满足对家直接访问的需求. 在底层, 对数据按照领域进行归类, 设计相应的Domain API, 从Domain API获取元数据整合出Process API所需要的数据.
- 实施部分, 每个API都是一个独立的微服务应用, 基于Spring Boot开发. 借助Spring Cloud来搭建整个微服务框架.
- 通过Spring Cloud Contract框架实现契约测试.
从“预算驱动交付”到“价值驱动交付”
- 引入服务等级, 统一确定请求优先级来安排产能:
- 延迟成本,cost of delay,计算每个请求如果逾期的话造成的损失,将其折算成金钱,来量化所有请求的优先级
- 服务等级,class of service,对于不同的请求类型,赋予不同的服务等级,区别处理
- 加急类(Expedite), 常见于一些时效性特别强的需求, 或者对产品重大缺陷的修复. 这一类请求将被视为最高优先级, 可以无视最大在制品(WIP)的限制而直接进行作业. 然而这样的请求, 很容易对看板的正常工作造成冲击, 因此加急类的任务个数, 通常仅设置为1.
- 固定交付日期类(Fixed Delivery Date), 推荐安排一定的产能来处理一些固定交付日期的请求. 对于这一类请求, 需要交付团队在开发之前对请求的工作量进行估算, 并在开发过程中定期地确认进度. 一旦发现进度落后到有可能无法完成的地步, 则需要交付团队对请求重新进行评估. 如有必要, 这类请求可以升级为加急类.
- 标准类(Standard), 最普通的请求. 推荐大部分的产能都归类到此类请求. 交付团队无需对请求的工作量进行估算, 直接按照先进先出的顺序进行处理即可. 但对于超过两周工作量的请求, 建议先进行拆分.
- 无形类(Intangible), 主要针对一些用户价值有限的附加功能, 推荐安排此类任务上的产能应该低于标准类的产能.
- 引入服务等级, 统一确定请求优先级来安排产能:
采用关键链方法, 把约束理论运用到项目管理中, 解决依赖冲突, 突破项目管理的瓶颈
- 新项目由于资源冲突, 计划时间超出规定的交付时间. 同时考虑到原来的计划是有安全时间的, 于是调整计划, 把所有任务的时间减半, 而这些被扣除的安全时间放在最后一个任务后作为项目缓冲时间
对于IT部门, 致力于培养能做到端到端交付的T型人才
- 模糊原来诸如BA、开发工程师、测试工程师、运维工程师等的明确的职能分工, 尽可能做到负责一个用户故事或需求的端到端交付, 包括分析、开发、测试、运维等
相关概念
敏捷方法论
Scrum
- 方法选择: 有专属团队的纯开发项目,需要稳定的交付节奏的项目,适用Scrum。需要跨项目、跨团队合作的,一人分饰多角的,维护类型的项目,适用看板
- 相关概念
- Product Owner(PO),用户/客户/业务代言人,即可以做出业务决策(需求和优先级)的人
- Scrum Master,熟悉Scrum流程的人,指导和确保团队以Scrum的方式进行交付
- Sprint,对迭代的说法。一个项目或产品的交付就是由一个又一个的Sprint构成的
- User Story,用户故事。具有业务价值的交付单位,一个项目或产品由很多用户故事构成
- Product Backlog,可理解为项目的代办列表,由用户故事构成
- Sprint Backlog,一个Sprint的代办列表,确定Sprint里有哪些用户故事,框定Sprint的开发范围
- 过程
- 每个项目或产品的交付由若干个Sprint构成。Sprint的周期是固定的,以保持节奏。通常是2-4个星期,不建议超过4个星期
- 每个Sprint开始时,PO和IT团队一起开Sprint计划会议,PO对Product Backlog中的用户故事进行排序,选出最重要的用户故事
- IT团队对这些用户故事进行估算。Sprint的周期和团队成员数量的确定,也确定了团队的大概交付能力
- 确定哪些用户故事会放到这个Sprint的Backlog里,作为Sprint的开发范围
- 围绕用户故事开发,每天一次站会,汇报昨天做了什么,今天会做什么,昨天遇到什么问题, 而且控制会议时长和参会人数以提高效率
- Sprint结束的时候,开评审会议,展示交付,PO的反馈,包括需求变更都可定义成新的用户故事放到Product Backlog里重新排队
- Sprint结束的时候,开评审会议,展示交付,PO的反馈,包括需求变更都可定义成新的用户故事放到Product Backlog里重新排队
- 敏捷的所有改变都是为了快速反馈
- 短迭代开发,让PO更快、更早地看到成品,给予反馈
- 每日站会,每天都能看到进度和阻碍
- 回顾会议,每个迭代都反思改进点,形成持续改善的机制
极限编程
12个实践
- 确保开发可更早开始和迭代式的持续交付
- 计划游戏,planning game,
- 把整个项目拆分成从几天到几个星期的若干个迭代,把需求拆分成一个独立的用户故事,放在Backlog里——》每个迭代开始时,用户对用户故事进行排序——》通过估算确定哪些用户故事可在整个迭代里开发。且只对当前迭代进行计划,新需求产生的用户故事要放到后面的迭代中
- 小型发布,small release,
- 每个迭代后,所开发的用户故事都可发布或展示给用户,获取反馈,新的用户故事放到后面的迭代中
- 计划游戏,planning game,
- 确保客户和交付团队都明白在做什么
- 现场客户,onsite customer,
- 用户应该和交付团队始终在一起,持续参与到项目中,阐明用户故事的具体需求和用户故事优先级,给交付团队及时的反馈
- 系统隐喻,system metaphor,
- 记录用户故事需求时,用交付团队和客户都能理解的语言编写
- 现场客户,onsite customer,
- 编码规范,code standards,
- 有一套整个团队都认可的规范
- 结对编程,pair Programming,
- 两个人结对在同一台计算机前来完成编程,一次性完成编程与评审, 共同讨论设计、测试、编程. 解决传统事后代码review, 需要重写单元测试及review参与度和质量的问题
- 测试驱动开发,test driven development,
- 在编程前就根据用户故事的需求写好测试(自动化测试),通过测试来验证编程代码是否满足需求
- 持续集成,continuous integration,
- 每天或每次有代码提交时就集成一次(编译、运行所有自动化测试、打包), 尽早暴露问题并及时修复
- 重构,refactoring,
- 不改变功能和外部行为而优化代码的可读性、质量、性能,有了自动化测试和持续集成,可保证重构后出现测试失败,立即回滚代码
- 简单设计,simple design,
- 只为当前要做的需求进行最简单的设计, 因为越简单的东西, 越不容易出错, 越复杂的东西, 越容易出错. 而如果设计不能满足需要时, 在自动化测试和持续集成的保障下, 通过重构来解决.
- 代码集体所有权,collective code ownership,
- 在自动化测试和持续集成的保障下,任何人都可以对代码重构
- 每周只工作40个小时,40-hour week,
- 保障每天足够的时间恢复精力, 避免提前透支精力
- 确保开发可更早开始和迭代式的持续交付
5个核心价值
- 沟通,communication、简单,simplicity、反馈,feedback、勇气,courage、谦逊modesty
看板(另外一种敏捷、精益的方法)
- 原则
- 进度可视化
- 识别整个交付从左到右的各道工序哪里是瓶颈
- 根据约束理论,一切瓶颈以外的改善都是徒劳的. 约束理论Theory of Constraint,TOC,帮助企业识别出在实现目标的过程中存在着哪些制约因素,并进一步指出如何实施必要的改进措施
- 限制在制品(WIP,Work-in-progress)
- 一个请求,只有所有工序都完成并交付到客户那里,其价值才能得到体现
- 大量在制品堆积会导致优先级迷失和任务切换,任务切换又会导致效率低下,降低交付速度
- 只有下游有闲置产能才从上游拉入新的请求,避免在制品堆积
- Scrum限制在制品的方式是, 通过Sprint计划会议限制每个Sprint放入的用户故事
- 看板则是在每道交付工序中限制并行任务数量, 随时都可以把新的请求放入Backlog中并排序, 只要有闲置产能时就把优先级高的请求拉入进程
- 观察和改善流动
- 进度可视化
- 与Scrum相通的地方
- 都基于敏捷与精益的原则,追求价值,消除浪费
- 都是基于拉动的计划系统
- 都限制在制品
- 都通过透明化来获取快速反馈
- 都聚焦于更早和更频繁地交付软件
- 都需要把大需求拆分成小故事
- how
- 可利用JIRA,按需定义看板的范围、外观、限制在制品数量、泳道、卡片的外观等。每天对着JIRA看板来开每日例会,业务也可通过看板的情况来判断团队分配是否合理,及整个交付过程的瓶颈在哪
- 观察看板时,要关注的是有没有空闲的任务,而不是有没有空闲的人员
- 从右往左看, 先聚焦在制品, 尽快把在制品完成
- 看累积流图,一个面积图,强调用户故事或是需求数随时间而变化的程度,直观显示整体趋势走向。x时间,y需求数量, 不同颜色的面积区分如待处理、处理中、已完成状态的需求。
用户故事地图
- why
- 真正的敏捷开发必须是基于用户故事的开发过程
- 如按报表来拆成若干个用户故事,选最常用的报表(对业务有价值的最小单位)先开发给业务测试,更快的获得反馈, 使大部分问题能更早地暴露, 为其他用户故事打下基础,通过早交付、早测试、早验收把产品的方向确定。
- 如果只是按功能点拆分,单个功能点的完成没有什么业务价值,无法测试
- 真正的敏捷开发必须是基于用户故事的开发过程
- how
- 从左到右按时间顺序罗列用户行为(流程的每一步)——》在每个用户行为从上至下地罗列相应的细节(包括所需的开发点)。基于这张地图,还可对每个开发点的业务价值进行审视,找出最小可用产品(MVP,Minimal Viable Product)并制订发布计划. 制定发布计划时,遵循刚刚好good enough、更好better、最好best的演进原则
- 记录家里所有物品的APP,每购入新物品就记录
- 用户故事地图
- 回顾地图,梳理每个用户故事的优先级,设想如果我们要在一周内做出MVP,会做哪些用户故事
- 定义MVP的必要性:
- 开发一个功能所需要的时间与成本总是超出预期的
- 需求是需要验证的假设,通过MVP可以快速试验,通过最小成本验证需求假设是否成立
- MVP是从整个业务角度来找出一个既能实现相同业务目标、IT成本最小的方法来快速启动新业务
- 如,要开一家提供网上订餐外送服务的餐厅,半个月内做出一个静态网站,展示菜式和订餐热线,生意就可在半个月之内运作起来。审视的是整个商业模式,不光是IT功能,更重要的是这样的外送服务模式是否可行和菜品是否受欢迎
- 用户故事拆分, 使故事最小化
- 用户故事地图
- 从左到右按时间顺序罗列用户行为(流程的每一步)——》在每个用户行为从上至下地罗列相应的细节(包括所需的开发点)。基于这张地图,还可对每个开发点的业务价值进行审视,找出最小可用产品(MVP,Minimal Viable Product)并制订发布计划. 制定发布计划时,遵循刚刚好good enough、更好better、最好best的演进原则
- 3C原则
- Card(地图)
- Conversation,确定发布计划后,要和PO围绕当前发布计划中的每一张Card聊具体需求
- Confirmation,确定验收条件
- 敏捷落地比较图
DevOps
- 敏捷打通了业务、开发、测试之间的墙, 通过更紧密的沟通与交互实现更频繁的交付. 而开发与运维之间还有一堵墙, 运维也需要稳定的部署、监控支持持续交付. DevOps就实现开发与运维一体化和端到端的持续交付,融合了敏捷与精益的精神, 涉及自动化、精益思想、量度和分享.
- 精益是从丰田生产系统移植到软件开发的方法, 看板方法就是其中一种精益方法.
交付文档模版:
- 需求描述
- 作为(谁),我想要(做什么),为了(为什么)。
- 行为驱动开发: 业务人员确定对系统的期望行为,采用业务部门和IT部门双方都能看懂的统一语言Gherkin的given when then的语言格式, 编写验收实例, 再通过自动化测试框架cucumber执行实例,实现验收测试自动化,并纳入持续集成
- cucumber,一个用普通语言描述测试用例的、支持行为驱动开发BDD的自动化工具,由Ruby编写,支持Java、.NET等多种开发语言。
- 确认理解
- 复述对需求的理解
- 问为什么
- 在什么场景下需要这个需求,包括谁用、什么时候用和使用条件、要解决什么问题、使用频次、怎么发生等(挖掘真实用意,因为有些需求是解决方案)
- 验收条件
- “完成定义”, Definition of Done
- 实例化需求, 验收测试用例的具体例子. 避免误读, 让抽象的需求变得具体和可测试.
- 以终为始,一开始明确要做成什么样,指导行动并确保结果正确。包括happy path和exceptional scenario
- 详细设计与实现
- 集成测试结果
- 用户验收测试
- 上线备忘
- 上线所需要的额外步骤
敏捷估算
- 敏捷采用的估算单位是故事点, 一个和复杂度或规模有关的相对数, 而用户故事的复杂度或规模, 是一个相对时间更稳定的常量, 因为时间是不可控因素, 同样的需求不同人做的耗时差异性很大.
- 扑克牌游戏方法
- 团队每个成员都有一副扑克牌, 每副扑克牌包含一个不同的数字, 如斐波那契数列, 然后对应故事点分别为1, 2, 4, 6, 10等. 当大家都消化完一个用户时, 同时通过出牌的方式来展示每个人的估算结果. 给出最高和最低估算的两人要解释和辩论. 最后团队得出一个大家都认同的估算值.
- 该方法的原理就是利用人群中涌出的群体智慧远远超过个人智慧.
- 估算时间
- 首先测试交付速度. 观察团队在头一两个迭代中可以实际交付多少个故事点来预测团队的交付速率, 从而计算完成所有故事点需要多少个迭代. 而在Scrum, 迭代的周期是固定的, 知道有多少个迭代就能知道需要多长时间
- 在迭代进行过程中, 通过燃尽图来持续观察团队的交付速率是在提升还是下降, 随时作出调整
关键链
- 关键路径是项目活动及其逻辑关系图中最长的路径, 通常决定项目工期
- 而关键链是决定项目长度的全部关键因素的关键路径和其他一些需要关键资源的任务
- 把关键链上所有任务被扣除的安全时间放在最后要给任务后作为项目缓冲,保护项目不受关键链任务延迟的影响。所有非关键路径上的任务被扣减的安全时间也集中在一起作为接入关键链的接驳缓冲,保护关键链不受这些任务延迟的影响
- 如果按非关键链的做法, 为所有的任务都加入安全时间, 会被学生症侯群、多任务和延迟的累计浪费掉所有的安全时间, 从而导致项目延迟
- 学生症候群指通常人们会先极力争取安全时间, 得到安全时间后, 就不着急, 真正开始往往在最后一刻, 造成安全时间被浪费. 所以在任务阶段剥夺安全时间可以迫使相应的资源在任务开始的时候就全力以赴地执行任务
- 估算通常被视作承诺, 考虑到今后的估算被压榨, 人们通常不会呈报提前完工, 这部分的延迟会转嫁到下一个任务, 而最终导致项目延迟. 而关键链方法, 任何任务提前完成都增加到缓冲区
- 关键链区别于关键路径主要是,
- 关键链考虑了资源冲突. 把安全时间从每个任务中转移出来的前提是, 每个任务所需要的资源都能聚焦在当前任务上
- 约束理论五步法
- 定义系统限制(瓶颈)
- 决定如何充分利用限制
- 让非限制资源充分配合
- 打破系统限制
- 若限制已打破,回到步骤一
其他相关思维:
- 真正的持续交付需要从左端的业务需求到右端的上线全流程配合
- 计划不是为了执行, 而是提前做好各种情况的预案, 集结资源, 以应对将来可能的各种变化
- 敏捷开发提倡信任、自治及通过技术手段如自动化测试来取代繁文缛节的文档.变革需要整个公司文化和价值观上的改变与配合以及人力、工具的投入, 只有管理层的支持才能使变革遍地开花.
个人感悟
上一篇《凤凰项目-三步工作法笔记》中, 提到多读书真的很重要, 因为虽然知识不能改变命运, 但是能改变思维.
后来我想了下, 应该是”意识到必须做出改变“更重要. 那样看了书之后, 不是只有“哦, 我知道了”, 而是会想办法把书里面的内容吸收用起来.
比如说, 把迭代思维融入到日常生活中, 其实是一种解决拖延症的好办法, 把要完成的事情拆分到足够小, 小到不用犹豫就能做的, 同时把这些任务可视化, 持续监控并调整自己的行为, 直到完成.
而“限制在制品”的应用, 就是把任务拆分到足够小之后, 排好优先级, 一件一件的完成, 减少不必要的任务切换, 专注于尽快消除未完成的任务.
ps: 尝试了一段时间后, 还是有些问题, 最重要的原因, 应该是缺少反馈, 多去接受外界的反馈才是真正的走出舒适圈…