如何评价软件写的好还是坏?

软件自身是一种固化的思维,因此从本质上来看,软件是不可度量的。

但这并不意味着软件不需要度量,而只是说软件中的度量大多都有一定限度。

应用各种度量数据的时候一旦跨过这种限度,结果就会适得其反。

 

在这篇文章里,我们将考查一下现有的,对软件进行度量的方法(注意:这篇里主要考察别人的方法,不是我自己的)。

可能不全面,不足的地方欢迎大家进行补充。

对软件“直观可见的质量属性”的度量比较简单,比如:Bug率,性能等,这里就不提了。

这里主要关注的是软件的内在的,不直观可见的质量属性。

 

  • 圈复杂度

 

圈复杂度主要用于度量函数或方法,从《代码大全》中可以找到圈复杂度的描述。

关于圈复杂度:Tom McCabe曾经建议使用下面的方法来度量复杂度。在这一方法中为了计算复杂度首先要计算子程序中的决策点(decision points),规则如下:

 

    1. 从函数第一行一致往下通过程序
    2.  一旦遇到以下关键字或者同类的词就加1:if,while,repeat,for,and,or
    3.  给case语句中的每一种情况加1                           --Steve McConell 《代码大全》

 

很多静态分析工具都直接提供对圈复杂度的度量,而圈复杂度本身歧义性很小,是非常难得的指标,高于15的代码基本很难看懂。

但圈复杂度更适合用于度量编码的结果,对高层设计则不太适用。

 

  • 响应集

 

  响应集是指类的各个方法直接调用的函数数目。响应集无疑的应该尽可能的小,根据得墨忒耳法则:某个对象的任何方法都应该只调用属于以下情形的方法。

         

class Demeter
{
private:
A* a;
int func();
public:
//...
void example(B& b);
void Demeter::example(B& b)
{
C c;
int f = func(); //<---- 类自己的方法
b.invert(); //<----传入参数的方法,当然参数本身也可能是函数
a = new A();
a->setActive();// <---创建的对象所拥有的方法
c.print(); // <---创建的,并归自己所有的对象的方法
}
};



         ---摘自《程序员修炼之道》

 

  • 关系内聚性(H)

 

在度量包时可以用包内部类的数目除以包内类的总数,其比值用来表示包得内聚性。如果用R表示包内部得类关系数目,用N表示包内类总数。那么:

H = (R+1)/N

  • 不稳定性(I)

不稳定性由输入耦合度(Ca)与输出耦合度(Ce)计算而来。

包得输入耦合度是指处于包外部,但依赖于包内类的数目。

包得输出耦合度是指包内部的依赖于包外部类的类数目。

这样I = Ce / (Ca+ Ce)

 

  • 抽象性(A)

 

包的抽象性用抽象类的数目和包中所有类的数目进行计算。

假如说包中类的总数是Nc, 抽象类的数目是Na ,那么抽象度A = Na/Nc

 

关系内聚性(H),不稳定性(H),抽象性(H)的进一步说明,请参见《敏捷软件开发:原则,模式与实践》一书。

 

这些度量指标无疑是有意义的,都可以用来评价软件写的好还是坏,但却不解决这样一个问题:
如果一个方案在关系内聚性(H),不稳定性(H),抽象性(H)上都有好的表现,复杂度有没有提高?如果说复杂度因此而提高了,那么这种额外支出的复杂度值不值得?

如果我们认为复杂度是软件的根本问题,那么在满足需求的前提下,使软件简单化就是最关键的使命(比灵活性等重要)。既如此,究竟应该如何度量软件的复杂度呢?

这是一个需要进一步展开的话题,我完善后会进一步和大家分享。

--------------------------------------------------------------

 

理想流 + 软件 = 《完美软件开发:方法与逻辑》
理想流 + 人生 = ??
理想流 + 管理 = ??
理想流 = 以概念和逻辑推演本质,追求真理。

posted on 2012-01-15 23:48  理想流  阅读(3248)  评论(2编辑  收藏  举报