你的项目统计这些数据吗?

为了能够更好地改进软件项目,开发团队往往会统计一些数据,用以分析总结,并作为下次开发改进的依据。那么在软件开发中,你的团队会统计哪些数据呢?这些数据又如何为下次项目改进提出帮助呢?
本文通过对软件开发过程中统计的一些数据进行分析,让读者能够从本质上重新理解统计数据的方法和意义。

1. 生产率
      统计生产率是为了能够了解开发团队的生产效率在整个行业中处于何种水平。长期统计之后可以为下次工时估算提供依据。
      单位:每人月可以生产的千行代码数,KLOC/MM
      统计了生产率对改进工作有什么样的帮助呢?支持统计这个数据的人说,统计生产率是为了和社会平均生产效率进行对比,从而分析改进方案。当自己的团队远远高于社会平均生产水平或者远远低于社会平均生产水平的时候,都预示着不好的信号。过高可能意味着代码质量的下降,而过低又可能预示着效率不足。然而社会平均生产水平究竟是什么样子的也没有组织公布出来。没有参考的数据,又如何判定高低呢?而社会平均生产水平真的具有参考价值吗?某著名公司开发的一个网站,总共代码不超过2000行,用了大概30个人月,难道他们的生产效率极低吗?不是的,而是他们的产品质量极高,代码具有高度的抽象性,十分容易扩展新功能。
      另外,统计的方法也千差万别,有人主张时间应该从需求分析开始直到发布这段时间,有人则认为只应该统计编码阶段的时间,因为前者经历软件开发的各个阶段,而后者是外包型企业,只接触从详细设计到单元测试的这几个阶段。谁说的更有道理呢?于是中间派说,这个数据统计是用来和自己比的。那么统计数据之后,如果一直很稳定代表什么意思?一直在上升又是什么意思?一直在下降呢?或者没有什么规律呢?
      这个数据还有语言相关性。C++的代码生产率和Java的生产率是不可比的,有人居然发明了一个折算指数,即生产x行Java代码相当于y行C++代码,这个折算指数是怎么来的?
      更为可笑的是,根据代码生产率来评价员工的情形,结果导致庸才得高评。

      至于平均生产率用于工时估算也是不靠谱的。大多数组织每个项目都会由不同的人组成。即使有些团队可以保持稳定的团队,但是每次的项目内容也不同。就算项目内容也都差不多,那么我们来看看这个数字是怎么计算出来的。
      估算工时  = 估算的代码行数 / 平均生产率
      平均生产率是统计出来的数字,相对比较稳定,但是估算的代码行数是如何得到的?上一次我们差不多的功能用了x行,所以这次应该是x +/- 15%(误差范围可能有所不同)。
      上次的时候你还在用Javascript实现的功能,这次改用jQuery实现了;
      上次你需要开发一个基础框架库,这次可以复用那部分;
      上次你才刚接触到WPF,这次你已经很熟练了;
      上次都是经验者,这次却都是新毕业生;
  上次的东西对这次的参考价值有多大/长期统计的东西对于日新月异软件开发来说更是难说其参考价值。


2. Bug密度
      统计Bug密度是为了能够掌握开发团队的质量水准,也就是说这个数值越低代表质量越好。
      其统计单位是:千行代码Bug数(case/KLOC)
      那么请看,这两段代码,

代码1

public Color getZembraColor(int index) {
    Color[] colors = new Color[]{Color.WHITE, Color.GRAY};
    return colors[index & 1];
}

 代码2

public Color getZembraColor(int index) {
    if (index % 2 == 0) {
        return Color.WHITE;
    } else {
        return Color.GRAY;
    }
}

这两段代码同样是完成根据行号获得斑马线颜色的,第一段代码用了4行,而第二段代码用了7行,如果不幸发生了Bug,比如,应该用Color.DARK_GARY,而不是Color.GRAY。
那么,对于第一个人来说,Bug密度 = 1 / 4 ,而第二个人则为 1 / 7,结果是第二个人的代码质量比第一个人好,事实真的如此吗?这只是个例子同样的情形比比皆是。
比如,查看一个字符串是否是许可字符串(俗称:白名单)的处理

代码1:

String [] enabledCodes = new String[]{"a", "b", "c", "d", "e", "f"};

public boolean isEnabledCode(String code) {
    for (int i = 0; i < enabledCodes.length(); i++) {
        if (code.equals(enabledCodes[i])) {
            return true;
        }
    }
    return false;
}

代码2:

public boolean isEnabledCode(String code) {
    return code.matches("a|b|c|d|e|f");
}

第一段代码9行(空行不统计),第二段代码3行。如果真的统计这个数据,又是一个庸才战胜人才的案例。

有些组织甚至制定了Bug目标,比如 8个/千行。而且还振振有词的说,超过这个数字代表质量不合格,低于这个数字代表测试不充分。于是很多人为了实现这个数字在一段高质量代码中抓破了头找Bug,最后把没有使用TAB对齐作为Bug提出来。

3. Bug原因分类
    统计产生Bug的原因分类,有助于针对某个开发阶段进行改进,比如,如果是设计上的遗漏比较多,那就提升设计能力,如果是编码上的问题比较多,那就提高编码能力。
    统计单位:百分比 (%)
    计算方法:某类原因引起的Bug数量/Bug发生数量

    如此统计似乎很可以有针对性的改进,然而如何从这组数据中得到改进的方案呢?一般做法是,针对特定类型Bug进行全面分析,总结出薄弱环节,改进其设计方法和/或加强其复查力度。
    我们姑且排除技术人员为了推卸责任而将代码实现的问题写成设计问题或者需求问题。且当数据都是可靠的。那么对于设计不足你会采取什么样的方法来改进呢?下面是一些可能被选为改进方案的选项。
    -原来我们用的是流程图,下次我们改进用UML图;
    -原来我们的复查工时为1倍,下次我们用1.5倍的时间;
    -制定一个CheckList用以复查;

其结果真的会改进设计质量吗?
    -采用UML图之后大家不明白数据流程了;
    -多付出的复查时间只是被浪费了,因为做法没有改变;
    -制定的CheckList只是把已知的知识写在了纸上;
    因为产生设计遗漏的原因并不是设计能力不足,也不是复查不充分,而是因为设计本身就是一个猜想的工作*,所以遗漏是必然的。改进设计的方案应该是用测试代替设计**

    Bug产生的原因并不是这些:需求分析不充分,需求文档书写不全面,详细设计有遗漏,编码过程中有遗漏。
    Bug产生的唯一原因是,写了代码没有进行充分的测试。试想,为什么Bug没有在开发组发现,而是被测试组发现,或者最终用户发现。就是因为开发组所采用的测试用例集合不充分和/或执行不到位。把这个原因写成其他原因所产生的结果就是摔倒了不说走路方法不对,却说地不平,于是就会出现上面那些隔靴搔痒的改进措施。


4. 二次Bug率
    二次Bug是指修改Bug的时候没有修改完成,导致该Bug再次被测试出来,或者由于修改该Bug引起另外的Bug发生。统计二次Bug率把握Bug的修改质量。针对发生的问题集中区域进行改进,有助于提高质量,缩短测试周期,从而为保证交货期而做出贡献。
    统计单位:百分比(%)
    计算方法:二次Bug数量/本轮测试发生Bug数

    如果二次Bug率居高不下,你会采取什么措施?
    首先是原因分析,可能的结论是
     -修改代码的影响性分析不足
     -修改代码的方案审核不足
     -修改代码后的测试不足
    于是,对应的改进方案可能是
     -在Bug修改流程中增加影响性分析文档制作过程
     -代码方案必须经过2个人审核
     -代码提交后必须经过2个人测试之后才能够交给测试组

     这样做的通常结果是:
     -二次代码率很稳定,没有得到任何改善
     -Bug修改流程变长了,于是测试周期变得更长,于是交货期更加不可靠
     -开发人员的加班变多了,士气下降了,质量更不可靠。

    统计这个数据只能够得到和与其相反的效果。
    

5.进度百分比
   对任务进行分解,得到WBS之后,每个小任务都要进行工时估算,然后放入甘特图,当任务在进行中的时候,每天统计该任务的完成情况,一般用百分比来表示。
   统计单位:百分比(%)
   计算方法:由任务执行者自行估算

    众所周知,软件开发中有很多不可预见因素,导致技术人员容易偏向乐观,往往估算工时会比实际工时短。尽管有时项目经理会适当增加Buffer,但是开发人员却并没有因此而减少乐观的态度。于是一个开发人员在报告进度时,对于他认为快要完成了的任务报告为90%。而第二天,他发现了一个很大的遗漏,那个遗漏占到整个功能的60%,于是第二天他又不好意思说昨天发现了重大遗漏,所以,原来的90%其实是:40% * 90% = 36%。他只好说91%。这样的进度报告又有什么意义呢?至于能够估算为85%的进度又有多少可靠可言呢?然而管理人员就是这样要求,所以开发人员也只好这样报告。形成一个互相欺骗的环境。


6.测试用例执行速率
    每单位时间能够执行的测试用例数量是测试用例执行速率。了解测试用例执行速率可以估算出测试的执行时间。
    单位:用例数/单位工时,例如每天可执行测试用例数。
    每个人每天上班时间为8小时,但是工作时间并不是8小时,上个厕所,抽个烟,聊个天,开个会.....很多事情都会占用这8小时之内的时间,而且由于切换任务和打断会导致效率进一步下降。更何况上次统计测试执行时间的时候所填写的数据可靠度本身就很低。而且测试用例的执行难度并不相同,有的光准备数据就需要5分钟,有的可以和别的共享数据,有的可以在前一个执行完之后马上执行。这个数据中充满着变化的因素。如何才能够确保数据可靠?






如果你的团队在统计这些数据,你如何控制其他那些“变化”的量?
如果你的团队真的在统计这些数据,是否意味着你的团队更喜欢庸才而不是人才呢?
如果你真的不明白这些数据的含义,你又为什么要统计这些数据呢?

你现在大概气势汹汹的准备问我,“那你说应该统计哪些数据!”。不要着急,下期就说。

--------------
*软件开发本身充满着太多的不确定因素,设计只是将能够想到的内容写下来的过程。
**用测试代替设计指的是测试驱动开发。

posted @ 2012-10-19 22:22  史蒂芬.王  阅读(3227)  评论(3编辑  收藏  举报