Visual Studio代码指标和交换机案例的可维护性指标

时间:2010-05-29 22:34:10

标签: visual-studio indexing maintainability code-metrics

作为一个喜欢遵循最佳实践的人,

如果我运行代码指标(右键单击解决方案资源管理器中的项目名称并选择“计算代码指标” - Visual Studio 2010):

    public static string GetFormFactor(int number)
    {
        string formFactor = string.Empty;
        switch (number)
        {
            case 1:
                formFactor = "Other";
                break;

            case 2:
                formFactor = "SIP";
                break;

            case 3:
                formFactor = "DIP";
                break;

            case 4:
                formFactor = "ZIP";
                break;

            case 5:
                formFactor = "SOJ";
                break;
        }

        return formFactor;
    }

它给我一个 61 的可维护性指数

(当然,如果你只有这个,那么这是微不足道的,但是如果你使用像哲学这样的类这样的实用程序,那么你的实用程序类将具有最差的可维护性指数..)

这是解决方案吗?

7 个答案:

答案 0 :(得分:26)

首先:61被认为是可维护的代码。对于可维护性指数,100很容易维护代码,而0很难维护。

  • 0-9 =难以维护
  • 10-19 =适度维持
  • 20-100 =维护良好

可维护性指数基于三个代码指标:即Halstead Volumen,Cyclomatic Complexity和Code of Code并基于following formula

  

MAX(0,(171 - 5.2 * ln)(Halstead   体积) - 0.23 *(Cyclomatic   复杂性) - 16.2 * ln(线条)   代码))* 100/171)

事实上,在您的示例中,可维护性指数的低值的根本原因是Cyclomatic Complexity。此度量标准是根据代码中的各种执行路径计算的。不幸的是,度量标准不一定与代码的“人类可读性”一致。

示例,因为您的代码导致索引值非常低(记住,lower越难维护)但实际上它们非常容易阅读。这在使用Cyclomatic Complexity来评估代码时很常见。

想象一下,代码有几天的开关块(Mon-Sun)加上几个月的切换块(Jan-Dec)。此代码将具有可读性和可维护性,但会导致巨大的Cyclomatic Complexity,因此Visual Studio 2010中的维护性指数非常低。

这是关于度量的众所周知的事实,如果根据数字判断代码,则应该考虑这个事实。不应查看绝对数字,而应随时监控这些数字,以便将其理解为代码更改的指标。例如。如果可维护性指数始终为100且突然降至10,则应检查导致此问题的变化。

答案 1 :(得分:5)

可维护性指数可能更高,因为您为解决方案选择的方法缺乏可扩展性。

正确的解决方案(上面提到的Mark Simpson)是可以扩展为使用新形状因子而不重建代码的解决方案 - 代码中的switch / case语句始终是OO设计已被遗忘的标志,应该总是被视为一种糟糕的代码味道。

就个人而言,我会实施......

interface IFormFactor
{
    // some methods
}

class SipFormFactor : IFormFactor...

class DipFormFactor : IFormFactor...

Etc.

...并让界面上的方法提供所需的功能 - 您可以将其视为[我猜]与GoF命令模式类似。

这样你的高级方法就可以......

MyMethod(IFormFactor factor)
{
    // some logic...

    factor.DoSomething();

    // some more logic...
}

...您可以在以后进行并引入新的外形,而不必像使用硬编码的switch子句那样更改此代码。您还会发现这种方法也很容易适用于TDD(如果您正在正确地进行TDD,您最终应该这样做),因为它很容易进行模拟。

答案 2 :(得分:3)

我知道这个答案很晚,但我感兴趣的是还没有人提出字典解决方案。我发现在处理像这样面向数据的巨大switch语句时,将switch-case折叠成字典通常更具可读性。

public static readonly IDictionary<int, string> Factors = new Dictionary<int, string> {
   { 1, "Other" },
   { 2, "SIP" },
   { 3, "DIP" },
   { 4, "ZIP" },
   { 5, "SOJ" }
};

public static string GetFormFactor2(int number)
{
   string formFactor = string.Empty;
   if (Factors.ContainsKey(number)) formFactor = Factors[number];
   return formFactor;
}

这给你一个74的维护性指数 - 比数组解决方案略低,因为类耦合到字典,但我觉得它更通用,因为它适用于你通常会打开的任意数量的类型。与数组解决方案一样,它可以很好地扩展并删除大量重复代码。

一般来说,使用数据驱动的方法可以帮助您的代码更清晰,因为它将重要的部分(在这种情况下,条件和结果)与cruft(在这种情况下,switch-case)分开

答案 3 :(得分:2)

有两件事让人想起:

使用枚举结合描述和值

public enum FormFactor
{
    Other = 1,
    SIP = 2,
    etc.
}

使用类或结构来表示每个外形

public class FormFactor 
{
    public int Index { get; private set; }
    public string Description { get; private set; }

    public FormFactor(int index, string description)
    {
        // do validation and assign properties
    }
}

答案 4 :(得分:2)

我这样做,忘记了可维护性指数:

public static string GetFormFactor(int number)
{
    switch (number)
    {
        case 1: return "Other";
        case 2: return "SIP";
        case 3: return "DIP";
        case 4: return "ZIP";
        case 5: return "SOJ";
    }

    return number.ToString();
}

恕我直言,易于阅读,易于更改。

答案 5 :(得分:0)

我不知道它有多重要,但以下是76:

private static string[] _formFactors = new[] { null, "Other","SIP","DIP", "ZIP", "SOJ"};
public static string GetFormFactor2(int number)
{
    if (number < 1 || number > _formFactors.Length)
    {
        throw new ArgumentOutOfRangeException("number");
    }

    return _formFactors[number];
}

答案 6 :(得分:0)

显然对我来说, Enum 方法是最易维护的,因为它不涉及硬编码字符串,因此没有拼写错误问题和编译时语法检查。 只有限制是命名规则。