知易行难的故事估算
谈到用户故事估算,你会想到什么?一群人拿着敏捷扑克亮出自己估算的故事点大小。估算差异大的两位,说出自己的理由。然后团队在澄清认识的基础上,继续亮出自己的选择,经过两到三轮的估算,即可达成共识。理想很丰满,现实很骨感。你以为的估算快如风,行云流水,现实却是开发人员一脸懵逼,估算啥故事点?啥叫故事点?为啥要估算?大侠放过我,我要去开发…
为啥要估算故事点?
做任何事情前,都要先想想它背后的目的是什么。我们为什么要做用户故事的估算?其实是为了选择一定数量的高优先级用户故事放入本轮冲刺中,更快的交付对业务最有价值的功能。按优先级排序的故事,让我们不会迷失优先顺序。但是能做多少,并不是人有多大胆,地有多大产。而是要看故事的大小和团队的产能(速率)。
怎么Get团队的产能?
如果一个团队上个冲刺完成50个故事点,那么接下来的冲刺也应该差不多是50个。当然效能提升,我们会有更高的小目标。那么问题来了,第一个冲刺我们并不知道自己的产能是多少,该怎么办呢?
其实可以采用一些简单估算的方法。假设团队有7个开发人员(敏捷的开发团队,包含团队内的测试人员),一个冲刺是两周,10天,除去敏捷仪式以及一些计划外的投入,假设投入到开发(包含代码检查和测试)的工作是8天。那么团队整体可投入约为56人天。我们选取一个已完成的基准用户故事,这个故事的工作量投入是4人天,将它设为一个故事点。那么我们一个冲刺大体可完成的故事点数为14。接下来就可以这个用户故事为基准,类比其他用户故事的点数。
什么是类比估算?
就好比我们假设鹌鹑蛋是一个故事点,那么鸡蛋可能是5个故事点;鸭蛋可能是8个故事点。当然这个类比是一维的,你会说这个很简单,但是现实世界,远没那么简单。
如果我问你降龙十八掌和黯然销魂掌相比哪个更厉害,如果前者的杀伤力是8,那么后者是多少?这是一个复杂的类比。你不能简单的说黯然销魂掌是十七招,降龙十八掌是十八招,所以后者更厉害。你肯定要分析,这两个武功背后蕴含的招数,以及这些武功与其他武林绝学交手时的威力。黯然销魂掌这套掌法内力雄厚,出招怪异,曾被五绝之一的“东邪”黄药师称:此掌刚猛之威力普天之下只有郭靖的降龙十八掌可匹敌。看上去是说两者相当,但从萧峰传到虚竹,再传到洪七公,再到悟性差些的郭靖,降龙十八掌的威力已经减退了些,但仍可匹敌黯然销魂掌。说明原创降龙十八掌,明显更胜一筹。
用功能点方法估算用户故事
说了这么多武功,是想告诉大家。对于用户故事的类比估算,也需要对用户故事有足够的了解。那么功能点无疑是一个好的度量单位。而cosmic方法也是天然面向业务的。
功能处理等同于一个可以独立交付业务价值的用户故事,功能用户等同于用户角色,兴趣对象等同于面向对象程序设计中的类对象。用户感兴趣的对象(也可以等同于我们系统中的业务表)。输入、输出是与前端的交互,读、写可理解为与数据库或外部系统的交互。每个数据移动是一个功能点。通过将用户故事拆解为数据移动,我们就可以大体估算一个用户故事的功能点。而功能点等同于故事点,是一个相对单位。通过估算功能点,我们可以从业务视角进行用户故事的规模估算,不用过早地陷入技术实现的细节,进而实现用户故事的快速估算。
由于功能点与工作量的强相关性,也可以实现任务拆分时快速估算工作量,可谓同时兼顾了故事估算与任务拆分的双重疗效。
概念晦涩来个隐喻
假如你想去一家餐厅吃饭,通常我们会约兴趣相投的朋友一起(兴趣对象),来到餐厅我们会点菜(输入),服务员根据我们的菜单来上菜(输出)。假设你和朋友点了一个套餐,里面包含很多个菜,我们也算一个输入,因为厨房都是统一安排处理的;厨房将套餐端上餐桌,输出同样也算一个。
假如你有两个朋友,一个朋友吃麻辣烫不要辣,一个朋友吃酸菜鱼不要酸菜,那么这两个就要算额外的输入,因为这个相比别的菜属于个性化的需求,需要厨房额外处理。如果我们都是堂食,那么输出只算一次,如果我们除了堂食,还要求打包一份给宅家里的朋友,那么打包这个额外的动作,也要单独算一个输出。
吃饱喝足,我们查看微信钱包看余额是否足够支付这餐的费用(读),然后买单支付,钱包的余额扣除费用(写),当然这个读写的兴趣对象是账户信息(兴趣对象)。
真正的用户故事如何度量?
如何实现快速估算软件项目的用户故事功能点呢?首先,我们知道一个用户故事,已经被拆分成了一个独立的功能处理。当然有时一个对业务有价值的功能,可能非常复杂。一个用户故事也可以拆分为多个功能处理。比如查询某个班级所有学生的信息,假设用户故事是先查询学校下的班级信息,再选择某个班级,查询学生信息。这个用户故事就可以拆分为两个功能处理,一个是查询班级列表信息,一个是查询某个班级的学生信息。但是对于想查询某个班级的学生信息这个诉求来说,显然单独实现查询班级列表,无法满足交付要求的。
用户故事拆分为功能处理后,我们就分别数功能处理的数据移动,然后将每个功能处理的数据移动累加起来即可。以上面的例子,查询班级列表这个功能处理,首先我们会有一个触发输入,比如我们通过菜单页面进入;或者我们从菜单进入后,还会提供按不同的查询条件筛选,无论我们有多少个查询条件,只要我们关注的兴趣对象是一个,那么输入就都算一个功能点。
获取查询条件后,我们需要去后台读取班级信息,这里有个读的数据移动。读完的结果需要在前端以列表形式展示,这里有个输出的数据移动。如果你还要输出没有查询结果或者查询报错的信息,则可识别一个输出的数据移动。如果你需要记录日志,也可以记录一个写的数据移动。这样算来,查询班级列表可以识别5个功能点。同样查询班级下的人员信息也可以识别5个功能点。整个用户故事就是10个功能点。
你可能会说,只数数据移动,不考虑功能或算法的复杂性,会不会太不准确。这里要提示大家的是,数据移动只是简单的估计,估算时可以结合需求澄清,再调整功能点。本身斐波纳切数列也不是连续的,就是为了提示大家估算时,不要纠缠细节,比如你数了5个功能点,但是你觉得背后的计算逻辑复杂,你就可以估8个功能点。不用担心会估多,因为可能你数6个功能点,但是你觉得实现逻辑简单,你也可以给出5个功能点的建议。所以,整体看,正负差距会抵消的。
数据移动很好理解,兴趣对象看似抽象,其实也可以这样打个比方。比如你在网上购物,你需要将商品加入购物车结算。这里面你其实是有两个关心的兴趣对象的,一个是商品信息是否有货,一个是订单信息我这笔订单要买的商品。所以你要数数据移动前,需要先搞清楚自己要关心的对象。就像你想行动前,需要先考虑你的目标人选一样。
结束语
码了这么多字,目的只有一个,希望我们再开计划会时,可以更从容高效,一起加油~