目标与问题
优秀的计划就是项目利益相关者认为足够可靠, 可以作为决策基础的计划.
估计和规划是重要的, 但也是困难和容易出错的. 我们不能仅仅由于他们很困难就不去做这些事. 项目早起给出的估计没有项目晚期给出的估计准确. 不确定性锥形显示了这一逐渐细化的过程.
规划的目的是招到一个最佳答案, 用于回答’要构建什么’这一产品开发的总问题. 这一答案综合了功能, 资源和进度. 一个可以减少风险, 降低不确定性, 为可靠的决策提供支持, 建立信任和传递信息的规划过程为解答这个问题提供了支持.
当一个人同时处理3个及以上的任务时, 用于增值的工作时间会迅速减少.
应对不确定性的最佳方式是迭代.
基于活动的规划分散了我们对功能的注意力, 而功能才是衡量客户价值的单元. 采用基于活动的计划所得到的进度表时, 许多问题都可能导致延期交付. 项目的参与者本来是满怀好意地把多任务处理当做一个可能解决延迟的办法, 但由于多任务处理背后隐藏的代价, 实际上会导致更长的延误. 当进度表上剩余时间不够的时候, 不可能避免地要放弃一些功能. 由于是按照开发人员认为最有效的顺序来对功能进行开发, 因此被放弃的功能对用户来说不一定是价值最低的.
忽视用户最终需要什么的不确定性, 会导致虽然按时完成了项目, 缺没有包含在制定计划以后发现那些重要功能. 而忽视关于如何开发产品的不确定性, 则会导致在项目计划中漏掉一些活动, 反过来增大了项目呗延迟, 最后放弃部分功能, 或者不适当地降低质量的可能性.
很多公司混淆了估计和承诺. 在哪里只要开发小组做出一个估计, 他们就必须对它做出承诺.
敏捷开发小组作为一个整体一起工作, 但包含了由特定人员担任的不同角色. 首先是产品所有者, 负责确定产品前景和小组将要实现功能的优先级. 然后是客户, 就是为项目提供资金或在软件完成后购买他的人. 敏捷开发项目中的其他角色海包括用户, 开发人员和项目经理.
敏捷开发小组按照短的, 时间限制的迭代周期进行工作, 在每次迭代结束的时候交付一个可用的产品. 在这些迭代中开发的功能是根据它们对产品的业务重要性选择出来的. 这保证了最重要的功能将首先开发. 用户故事是敏捷开发小组表示用户需要的一种常见方式. 敏捷开发小组认识到一个计划可能很快就会过时. 因此, 他们会更具需要调整计划.
项目应该被看做是迅速, 可靠地产生有用的新功能和新知识的流程, 而不是只是对一系列步骤的执行. 项目会产生两类新知识: 关于产品的知识和关于项目本身的知识. 每类知识在使计划更精细, 从而为机构获取更多价值上都是有益的.
敏捷开发小组使用3个层次上的规划: 发布规划, 迭代规划和每日规划. 发布规划展望一次发布的整个时间范围, 通常是3~6个月. 迭代计划只考虑当前一次迭代的持续范围, 通常是2~4周. 每日计划则由小组成员在每日例会上向其他人做出的承诺组成.
理解产品所有者的满意条件对发布规划和迭代规划都至关重要. 在发布规划中, 整个开发小组会确定一个方法满足本次发布在范围, 进度和资源方面的满意条件. 为此, 产品所有者可能需要放宽一个或几个满意条件. 进行迭代规划时也会经历类似的过程, 只是此时的满意条件是将要实现新的功能和用于演示这些功能呗正确实现的高级测试用例.
规模估计
所需要知道的仅是某个特定的用户故事或者功能是比其他用户故事和功能大一些还是小一些.
故事点是用于表达用户故事, 功能或者其他工作的总体规模的度量单位.
需要的功能 –> 对规模进行估计 –> 推算持续时间 –> 进度表
故事点是对用户故事规模的相对度量. 具有10个故事点的用户故事的规模, 复杂度或者风险应该估计为具有5个故事点的用户故事的两倍. 具有10个故事点的用户故事的规模, 复杂度或者风险同样应该为一个20点的用户故事一半. 有意义的只是分配给不同用户故事的点值的相对大小.
速度是对开发小组每次迭代的进度率的度量. 在每次迭代结束的时候, 开发小组可以看看他们完成了哪些用户故事, 通过计算完成的用户故事的故事点估计值之和来得到小组的速度.
故事点只是对要进行的工作的规模估计. 与其说一个项目的持续时间是估计出来的. 不如说是通过求取项目的总故事点数, 再除以小组的速度而推算出来的.
理想时间(ideal time)是某件事在剔除了所有外围活动之后所需要的时间. 耗用时间(elapsed time)是时钟上显示流逝掉的时间. 用理想时间而不是用耗用时间来预测某件事的持续时间总是更准确, 而且要容易得多.
理想时间和耗用时间是不同的. 一场美式橄榄球的理想时间是60分钟. 但是, 在一场60分钟的比赛结束前, 时钟上通常可能已经过了3个小时或以上. 当然, 导致这一差异的原因是比赛过程中可能出现的各种干扰.
使用理想日而不是耗用日, 更容易估计开发一个故事所需要的时间量. 按照耗用时间进行估计要求我们考虑在处理这个用户故事时所有可能出现的干扰. 而如果我们以理想日进行估计, 就只需要考虑这个用户故事所需要的时间. 这时, 理想日是对规模的估计, 虽然他的以及没有故事点那么严格.
采用理想日进行估计的时候, 最好只为每个用户故事分配单一的估计值. 应该把所有需要的时间加在一起, 说某个用户故事需要9个理想日, 而不是说它需要4个程序员日, 2个测试人员日和三个产品所有者日.
回报渐减法则(回报的增长幅度随着投入的增加而减小).
13 * 0 ≠ 0
用户故事, 史诗和主题
花更多的时间和精力来得到一个估计值, 并不一定会提高它的准确性. 应该根据估计的目的来决定在估计中投入多少工作量. 虽然众所周知将要做某项工作的人才能给出最好的估计, 但在一个敏捷开发小组中. 我们无法提前知道谁将负责这项工作. 因此, 估计应该是小组合力完成的一项活动.
估计应该基于一个预先定义的尺度. 将在最近处理的功能以及需要非常可靠估计的功能应该足够小, 从而可以使用一个1~10之间的非线性尺度, 例如1, 2, 3, 5和8来进行估计. 不太可能在最近的几次迭代中实现的大功能可以不分解, 用大的单位, 如13, 20, 40, 100来估计. 有些小组选择在估计尺度中包含0.
要得到一个估计值, 我们可以依赖专家意见, 类比和裂解. 规划扑克是一个有趣而且有效方法. 他结合了上述3种办法. 在规划扑克中, 每个估计者有一叠写有有效估计值的卡片. 每讨论一个功能, 每个估计者就选择一张代表他的估计值的卡片. 所有的卡片都同时展示出来. 小组对估计值进行讨论, 重复这个过程直到达成一致的估计.
故事点是对规模的估计, 当一个用户故事的相对大小发生了变化的时候, 才需要重新估计.
规模不发生变化的时候, 不需要重新估计. 用速度来重新修正迭代估计.
把重估当做为估计将来的用户故事而进行的学习体验.
记住故事点和理想日是对功能规模的估计, 可以帮助您知道何时应该进行重估. 只有在您对一个或多个故事的相对规模的看法发生变化时, 才应该进行重构. 不要只因为进度没有您预期那么快而进行重估. 让速度这个很好的均衡器来解决大多数估计中的不确定性.
我不建议在一次迭代结束的时候给出部分完成的用户故事的部分点数. 我的倾向是让小组在速度计算中要么得到所有的估计点数(如果他们完整地结束了一个功能, 而且该功能被产品所有者接受), 要么就什么也得不到. 但是, 小组也可能会选择对部分完成的用户故事进行重估. 通常, 这意味着对一个代表这次迭代中已完成工作的用户故事和一个或多个说明剩余工作的用户故事进行估计. 这些用户故事估计值的和并不需要等于最初的估计值.
开发小组可以选择使用故事点或理想日进行估计. 两者都是具有一定有点的可行方法.
故事点的优势是可以帮助促进小组的跨功能行为. 此外, 由于故事点是更为纯粹的对规模的估计, 因此即使小组在技术上或是领域知识上取得了进步, 也并不需要重估它们. 用故事点进行估计往往比用理想日估计要快. 最后, 与理想日不同, 可以在小组成员之间对故事点进行比较, 如果一个小组成员认为某件事需要他4个理想日, 而另外一个成员认为她只需要1个理想日, 也许他们都是对的, 但他们缺乏讨论的共同基础, 无法建立一个单一的估计,
理想日的优势在于更容易向开发小组之外的人进行解释, 以及更容易开始.
我的倾向是使用故事点. 使用故事点进行估计的优点更具有说服力. 如果小组对单纯的规模进行估计存在困难, 我会让他们用理想日开始估计, 然后再然让他们转化到故事点上. 我会更多地问’这个功能的规模与我们刚才估计的那个相比怎样?’, 而不是’它会需要多少个理想日?’. 大部分小组几乎不会注意到这种逐渐的转变, 而当他们意识到的时候, 他们已经是在用故事点, 而不是理想日进行思考了.
为价值做规划
由于会很少有足够的时间来完成所有的事, 因此需要通过优先级来确定首先处理哪些工作. 确定优先级时需要考虑4个主要因素.
综合考虑这些因素, 首先是主题的价值和成本. 这样做可以给主题安排出初始的顺序. 然后可以根据其他因素前后移动主题的顺序.
经济指标:
因为大多数公司的底线是赚到或者节省的金钱数目, 所以对主题的经济分析可以帮助确定主题的优先级. 通常, 预测未来两年中的收入和操作效率就已经足够. 不过, 如果需要的话, 您也可以看得更远一些.
对主题的收益进行建模的一个好方法是考虑它可以产生的收入, 主要来自从新客户处, 从现有客户购买更多的许可或额外的服务处, 从没有这些功能就可能转向竞争产品的客户处, 以及从它所能带来的操作效率提升上.
今天赚到或者花费的钱比将来赚到或者花费的钱更有价值. 将要一个当前的金额和一个将来的金额做比较, 需要对将来的金额贴现得到当前的金额. 当前金额就是可以被存入银行, 或者进行其他相对安全投资, 然后在将来那个时候涨到那个将来金额的金钱数目.
有4个可以用于对现金流进行评估的好方法, 它们分别是净现值, 内部收益率(投资收益率), 回收期和贴现回收期. 通过对每个主题计算这些指标, 产品所有者和开发小组可以对主题的优先级做出明智的决策.
功能的类型:
我们暂时停下, 回忆一下我们为什么在进行这些讨论. 在前面的章节中, 我们学习了确定功能优先级时有4个因素需要考虑.
第10章’确定经济优先级’说明了确定功能的总体优先级时考虑学习和降低风险因素的重要性. 这一章介绍了两种方法: Kano分析和相对权重, 来根据功能的合意性确定优先级.
在Kano分析中, 功能被分成必须的功能, 线性的功能和兴奋点. 这一工作是通过向潜在的用户问后面两个问题来完成的: 如果有这个功能他们会觉得如何以及如果没有这个功能他们又会觉得如何.
相对权重方法提供了一种使用一个价值对实现一个功能所带来的收益, 不实现它所带来的惩罚和实现它的成本进行评估的方法, 这个值就代表了这个功能的优先级.
按照用户故事所支持数据的边界来分割大型用户故事.
把大型故事分割成独立的建立, 读取, 更新和删除操作.
考虑去除横切考虑(例如安全日志, 日志记录, 错误处理等), 为用户故事建立两个版本: 一个具备对横切考虑的支持, 另一个不具备这种支持.
考虑把功能性和非功能性需求隔离到不同用户的故事, 从而分割大型用户故事.
如果大型用户故事中的晓故事具有不同的优先级, 则可以对它们进行分割.
不要把大型用户故事分割成任务, 而是寻找一个方法来交付一项功能的所有层.
避免在具有适当规模的功能中增加相关变化而把事情弄糟, 除非这些变化具有相同的优先级.
无论是一个用户故事相对迭代周期太大还是一次迭代的时间对它不够, 分割这个用户故事都是有益的. 如果您需要提供对比单个大故事更准确的估计, 分割大型用户故事也是有益的.
可以按照用户故事所支持的数据类型来分割它, 也可以根据故事中固有的操作来进行分割. 按照常用的CRUD操作来进行分割是很常见的. 把横切考虑, 例如安全处理, 日志处理和错误处理等, 隔离出去也可以使用户故事更小. 还可以在实现用户故事功能的迭代中忽略性能要求来是它变小, 性能要求可以形成独立的用户故事并在以后的迭代中得到满足. 很多用户故事描述了两个以上的要求, 如果这些要求具有不同的优先级, 就可以根据它们进行切割.
要避免把用户故事分割成实现该功能时所必须完成的开发任务. 我们都有把工作分割成它的必须任务的习惯, 所以很容易按照这种方式来分割用户故事. 还要避免在一个大型用户故事中增加对交付该故事并非必须的相关变动的诱惑, 因为这样会让它变得更大.
最后, 记住有些时候组合用户故事也是恰当的. 尤其是在修复故障时, 它们中的每一个本身可能都太小.
进度安排
发布规划是建立很高层次的, 覆盖超过一次迭代周期长度的计划过程
发布计划是覆盖了比一次迭代更长时间范围的高层次计划. 对大多数开发小组来说, 每3~6个月会进行一次发布, 但是根据开发的软件类型不同, 更频繁或者更少的发布也不少见. 最简单的情况下, 发布规划可以说是微不足道的: 用预期的速度乘以计划的迭代次数, 然后选择用户故事, 让它们的规模估计值的总和充满这次发布.
发布计划并不需要精确说明在每次迭代中需要完成哪些工作. 实际上, 很少会需要这一水平的细节. 对大多数项目而言, 指出第一次迭代中要处理的用户故事就足够了, 可以把剩下的用户故事留到以后再按优先级分配到其他的迭代中.
发布规划是一个迭代的过程, 首先要确定产品所有者对这个项目的满意条件. 这些条件通常包括了在进度, 范围和资源方面的目标. 如果无法规划一个项目来满足最初的满意条件集, 就需要要重复规划过程, 看是否能满足一个缩小了的满意条件; 不然的话, 也许可以晚一些交付某些要求的功能, 或者采用一个更大的开发小组.
一旦建立了发布计划, 不要把它挂在墙上发霉. 通常要在每次迭代开始时更新它.
\ | 发布计划 | 迭代计划 |
---|---|---|
规划时间范围 | 3~9个月 | 1~4周 |
计划对象 | 用户故事 | 任务 |
估计的单位 | 故事点或理想日 | 理想小时 |
建立迭代计划的过程会引导开发小组对产品设计和软件设计都开展讨论. 产品设计讨论的主题可能是关于诸如为了优化价值而对用户故事进行最佳的组合, 对向客户展示可用软件后获得的反馈进行解释理解, 或者需要的是功能应实现到何种程度. 软件设计的讨论则可能是关于采用适当的体系层来实现新功能, 应该采用哪种技术, 是否可以重用已有的代码. 通过这些讨论, 开发小组可以更好地理解应该将要构建什么东西.
速度驱动的迭代规划的步骤:
要求开发小组把用户故事逐个添加到迭代中, 直到他们无法承诺完成更多的故事.
关键在于让小组中的每个人都有责任做出他们力所能及的贡献, 二不管这是不是他们的专长.
与发布计划不同, 迭代计划更仔细地审视单次迭代中的特定工作. 迭代计划所看到的范围不会超过一次迭代, 而不是像典型的发布计划那样达到3~9个月. 在发布计划中相当大的用户故事在迭代计划中被分解成任务. 对每项任务, 都要按照完成该任务所需要的理想小时数进行估计.
概括起来有两种进行迭代规划的方法: 速度驱动的方法和承诺驱动的方法. 两种方法有很多相同的步骤, 而且常常会建立起一样的迭代计划.
2~4周
招到一个可以鼓励每个人都在迭代中按照稳定的步幅工作的迭代长度.
一直2周的迭代会使得开发小组过度紧张. 建议采用 6*2 + 1的大循环, 在1的时候由开发小组自由选择优先级, 他们可以在这里清理技术负债.
大多数敏捷开发小组采用2周或者4周的迭代长度. 没有适用于所有小组的绝对正确的迭代长度. 每个小组都应该考虑自己所处的独特环境, 选择对自己合适的迭代长度. 进行这一决策时需要考虑的因素包括:
不确定性和进度估计
产品阶段 | 低端乘数 | 高端乘数 |
---|---|---|
初始产品定义 | 0.6 | 1.6 |
认可的产品定义 | 0.8 | 1.25 |
需求说明 | 0.85 | 1.15 |
产品设计说明 | <0.9 |
1.1 |
详细设计说明 |
0.9 |
<1.1 |
被接受的软件 | 1 | 1 |
1~3次
完成迭代次数 | 低端乘数 | 高端乘数 |
---|---|---|
1 | 0.6 | 1.6 |
2 | 0.8 | 1.25 |
3 | 0.85 | 1.15 |
4次以上 | 0.9 | 1.1 |
进行迭代 > 使用历史值 > 做出预测
有3种估计速度的方法. 首先, 如果您有历史平均值的话, 可以使用他们. 不过在使用之前, 您应该考虑小组, 项目的本质和采用的技术等方面还有没有显著的变化. 其次, 您可以推迟对速度的估计直到您进行了几次迭代. 这通常是最好的选择. 第三, 您可以通过把一些用户故事分解成任务, 看看多少任务可以充满一次迭代, 来对速度进行预测. 这一过程与迭代规则很相似.
无论您采用那种方法, 都应该以一个范围来给出对速度的估计值, 这个范围反应了估计值中所蕴含的不确定性. 不确定性雏形为要使用的范围大小提供了建议.
承诺提供所有的这堆功能, 可能还会提供另外一堆功能中的一部分.
大多数项目都包含大量的不确定性. 项目小组简历的进度表和最后期限中往往没有完全反映这种不确定性. 有些时候, 如果这种不确定性非常大或者非常显著, 就需要在估计项目持续时间的时候采取一些额外的步骤. 这些情况可能包括: 提前很多进行项目规划, 项目必须绝对满足最后期限, 同事交付一组相当严格的功能集, 项目是外包的, 需求仍然处于非常表面的层次, 或者在日期出错时会产生严重的影响(经济或其他方面)等.
功能缓冲区和进度缓冲区是两类最常见的缓冲区. 当确定了项目中所有需求的优先级, 然后发现可能不能交付所有功能的时候, 就要建立一个功能缓冲区. 例如, 敏捷开发过程DSDM建议把一个项目中30%的工作看做是可选的, 从而为项目建立功能缓冲区. 如果时间不够用, 仍然可以通过放弃功能缓冲区中的事项来达到进度表的时间要求.
另一方面, 可以在进度表中包含一定量的时间来建立进度缓冲区, 这个时间的量反映了蕴含在项目规模中的不确定性. 可以通过同时估计每个用户故事具有50%可能的规模和具有90%可能的规模来构造进度缓冲区. 通过对每对50%和90%估计值采用平方和的平方根公式, 可以估计出合适的进度缓冲区.
项目应该用功能缓冲区来预防功能不确定性, 用进度缓冲区来预防进度不确定性. 可以把功能缓冲区和进度缓冲区结合起来. 实际上, 这常常是个好办法, 因为它可以让每个缓冲区的规模都更小.
敏捷开发项目倾向于在开发大型项目的时候避免使用很大的开发小组, 而是使用多个小组. 当有多个小组工作与一个项目时, 他们就需要互相协调工作. 本章说明了4种在帮助多个小组共同处理一个项目时很有效的方法.
首先, 小组应该为他们的估计建立一个共同的基础. 所有小组都应该同意按照相同的单位进行估计: 要么故事点, 要么理想日. 他们海应该通过对对一小组故事形成一致的估计值来对使用的单位的含义达成一致.
其次, 当多个小组需要一起工作的时候, 尽早给他们的用户故事增加细节常常很有帮助. 进行这一工作的最佳办法是确认产品所有者对用户故事的满意条件. 这些满意条件就是一旦完全实现了这个故事, 就可以显示为真的那些事.
第三, 在发布规划过程中结合一个滚动前瞻计划, 可以让多个小组受益. 滚动前瞻计划简单地向前看几次迭代(2~3), 通过共享在不久的将来每个小组分别会处理哪些工作的信息, 让小组之间可以协调工作.
第四, 在具有很多小组间依赖性的高度复杂项目中, 把馈送缓冲区结合到计划中是有益的. 估计缓冲区是在计划中的一段时间, 可以避免一个小组推迟交付导致另一个小组推迟启动.
一般可以按照说明这些方法的顺序把它们纳入到项目中. 不过, 也可以按照您所希望的任何顺序来使用它们.
跟着与交流
速度度量的是小组在每次迭代中完成的工作量. 应该采用或全无的规则来计算速度. 如果完成了一个故事, 小组就可以在计算速度的时候得到它所有的估计值. 如果在迭代中只是部分完成了一个故事, 确定速度时就完全不要考虑它.
发布耗散图显示出每次迭代开始时项目中剩余的功能点或理想日数目. 小组的耗散过程从来都不会是完全平滑的. 例如, 不准确的估计, 估计值的变化和范围的变化等都会导致它的起伏. 耗散图甚至可能在一次迭代中显示出待完成的工作量的增加. 这意味着虽然小组可能完成了一些工作, 但他们要么认识到剩下的工作被低估了, 要么就是增加了项目的范围. 解释发布耗散图的一个关键在于理解它显示的是小组恩净进度(他们的进度减去所有被增加到项目中的工作).
发布耗散条形图提供了一种某些时候会有用的对标准发布耗散图的变形. 它把小组相对规划的工作的进度和对发布范围的改变给分隔开, 通过把条形的底部降到水平轴以下来显示范围的变化. 这类图比标准耗散图更有表达力, 但必须小心使用, 因为它在一些公司中可能导致关于某个变化影响的到底是图中条形的顶部还是底部的争论.
停车场图提供了一个有用的高层次视图, 体现了小组在实现项目中所规划的不同主题时的进度.
任务板, 常常是一张白板, 软木板或者只是墙上特定的一片区域, 可以帮助开发小组组织他们的工作, 并把他们可视化. 任务板的纵览都带有标题, 小组成员根据工作进展把任务卡片在各栏间移动.
迭代耗散图类似于发布耗散图, 但只是用来跟踪当前迭代中的工作. 它的纵轴是剩余工作的小时数, 而横轴是迭代中的天数.
小组要做出更好的估计, 就应该反对跟踪花在任务上的实际小时数. 这样所付出的工作量和带来的风险通常超过了它带来的好处.
小组不应该计算或跟踪个人速度.
1. 背景
日期
迭代的起止日期
工作天数
人员
名字, 计划天数, 实际天数
2. 度量
每晚构建结果
日期, 状态(如果测试通过则报告成功的数目; 如果失败则报告失败的数目)
迭代耗散图
3. 内容和评估
用户故事, 结果, 计划的点数, 获得的点数
迭代回顾
行动事项, 责任人
我们希望就估计和计划进行的沟通是频繁的, 诚实的和双向的. 甘特图可以用作对计划进行沟通的有益的工具. 不过不应该让它进入到低于功能分解的层次, 而且图中功能应该显示为在整个迭代持续期内都在进行处理.
耗散图是对进行沟通的主要手段, 但它们常常需要同时有一个图显示开发小组再每次迭代中的速度. 把速度考虑成一个取值范围而不是单个值是有益的. 有一个好方法可以达到这一目的, 就是同时使用最近一次迭代的速度, 前8次迭代的平均速度和前8次迭代中最差的3次迭代的平均速度. 这3个值很好地描绘出刚发送的情况, 长期平均的情况和最坏条件下可能发生的情况.
迭代结束小组在某些项目中可能是有用的, 它既可以传递当前的信息, 也可以作为供将来使用的历史文档.
敏捷规划有效的原因
把开发小组的关注点从建立完美的计划, 移动到简历目前有用的计划.
不同计划是用户不同目的的事实. 帮助小组从不同的角度来看这个项目.
迫使小组在功能上来考虑产品.
敏捷规划的目的是以迭代的方式发现总体产品开发问题的自家解决方案, 这个问题就是在哪段时间内使用哪些资源来得到哪些功能.敏捷估计和规划方法可以成功找到这样的解决方案的原因包括: 计划是在不同层次上做出的, 并且重规划频繁地发生; 计划是根据功能而不是根据任务做出的; 首先估计规模, 然后根据规模的估计值推算出持续时间; 小故事保持工作的流动, 而且每次迭代结束时会消除处理中的工作; 是在小组层次而不是个人层次对进行进度度量; 承认不确定性并为之做计划.