为什么我会重构这个代码,因为Cyclomatic Complexity是58

Amz*_*ath 5 c# cyclomatic-complexity

我读过CC 10或更低版本的代码是高度可维护的.但是我写的方法有CC 58.感谢VS 2010代码分析工具.我认为,就我的理解而言,我所写的方法非常简单,易读且易于维护.因此,我不希望重构代码.但由于CC高于可接受的水平,我想知道为什么会重构这种方法.我正在学习如何改进我的代码如果我有错误,请纠正我.这是代码.

private string MapBathRooms(string value)
    {
        double retValue = 0;
        if (value == "1" || value == "One")
            retValue = 1;
        if (value == "OneAndHalf" || value == "1.5" || value == "1 1/2")
            retValue = 1.5;
        if (value == "2" || value == "Two")
            retValue = 2;
        if (value == "TwoAndHalf" || value == "2.5" || value == "2 1/2")
            retValue = 2.5;
        if (value == "3" || value == "Three")
            retValue = 3;
        if (value == "ThreeAndHalf" || value == "3.5" || value == "3 1/2")
            retValue = 3.5;
        if (value == "4" || value == "Four")
            retValue = 4;
        if (value == "FourAndHalf" || value == "4.5" || value == "4 1/2")
            retValue = 4.5;
        if (value == "5" || value == "Five" || value == "FourOrMore")
            retValue = 5;
        if (value == "FiveAndHalf" || value == "5.5" || value == "5 1/2")
            retValue = 5.5;
        if (value == "6" || value == "Six")
            retValue = 6;
        if (value == "SixAndHalf" || value == "6.5" || value == "6 1/2")
            retValue = 6.5;
        if (value == "7" || value == "Seven")
            retValue = 7;
        if (value == "SevenAndHalf" || value == "7.5" || value == "7 1/2")
            retValue = 7.5;
        if (value == "8" || value == "8+" || value == "Eight" || value == "SevenOrMore")
            retValue = 8;
        if (value == "EightAndHalf" || value == "8.5" || value == "8 1/2")
            retValue = 8.5;
        if (value == "9" || value == "Nine")
            retValue = 9;
        if (value == "NineAndHalf" || value == "9.5" || value == "9 1/2")
            retValue = 9.5;
        if(value == "10" || value == "Ten")
            retValue = 10;
        if (value == "TenAndHalf" || value == "10.5" || value == "10 1/2"
            || value == "10+" || value == "MoreThanTen" || value == "11")
            retValue = 10.5;

        if (retValue == 0)
            return value;

        return retValue.ToString();
    }
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 15

为什么不只是一个Dictionary<string, double>?这将使代码简单 - 您已将数据与查找代码分开.

private static readonly Dictionary<string, double> BathRoomMap =
    new Dictionary<string, double>
{
    { "1", 1 },
    { "One", 1 },
    { "OneAndHalf", 1.5 },
    { "1.5", 1.5 },
    { "1 1/2", 1.5 }
    // etc
};

private static string MapBathRooms(string value)
{
    double result;
    if (!BathRoomMap.TryGetValue(value, out result))
    {
        return value; // Lookup failed
    }
    return result.ToString();
}
Run Code Online (Sandbox Code Playgroud)

实际上,通过避免ToString调用,你可以使它变得更简单 - 只需将它设为Dictionary<string, string>:

private static readonly Dictionary<string, string> BathRoomMap =
    new Dictionary<string, string>
{
    // Note: I've removed situations where we'd return the
    // same value anyway... no need to map "1" to "1" etc
    { "One", "1" },
    { "OneAndHalf", "1.5" },
    { "1 1/2", "1.5" }
    // etc
};

private static string MapBathRooms(string value)
{
    string result;
    if (!BathRoomMap.TryGetValue(value, out result))
    {
        return value; // Lookup failed
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)

正如ChrisF所说,您也可以从文件或其他资源中读取此信息.

这样做的好处:

  • 这是很多容易避免的失误和延长,IMO.从输入到输出有一个简单的1:1映射,而不是可能出错的逻辑
  • 它将数据与逻辑分开
  • 它允许您在需要时从其他位置加载数据.
  • 由于集合初始值设定项使用Dictionary<,>.Add,如果您有重复键,则在初始化类型时会出现异常,因此您将立即发现错误.

这样说吧 - 您是否会考虑从基于字典的版本到"大量真实代码"版本的重构?我当然不会.

如果你真的,真的想在方法中拥有它,你总是可以使用switch语句:

private static string MapBathRooms(string value)
{
    switch (value)
    {
        case "One":
            return "1";
        case "OneAndHalf":
        case "1 1/2":
            return "1.5";
        ...
        default:
            return value;
    }
}
Run Code Online (Sandbox Code Playgroud)

我自己仍然使用字典表单...但是这确实具有将重复检测提升到编译时的非常小的优点.

  • @Amzath - 如果从配置文件/数据库填充字典,则可以扩展应用程序而无需重新构建它. (2认同)