如何减少这些if else语句的圈复杂度

时间:2016-11-30 08:08:42

标签: c# algorithm command-line-arguments cyclomatic-complexity

我正在尝试验证命令行参数,并在出现错误时打印错误消息。

我的问题是,如果命令行参数的数量增加(目前,我只有3),那么我的代码将变成意大利面条代码。如何降低给定代码的圈复杂度?

var isCmdLineWrong = false;
var Arg1 = "Undefined";
var Arg2 = "Undefined";
var Arg3 = "Undefined";

var commandArguments = Environment.GetCommandLineArgs();
if (commandArguments.Contains("-r") && arguments[commandArguments.IndexOf("-r") + 1].StartsWith("-") == false)
    Arg1 = commandArguments[commandArguments.IndexOf("-r") + 1];
else
{
    isCmdLineWrong = true;
}
if (commandArguments.Contains("-n") && commandArguments[commandArguments.IndexOf("-n") + 1].StartsWith("-") == false)
    Arg2 = commandArguments[commandArguments.IndexOf("-n") + 1];
else
{
    isCmdLineWrong = true;
}
if (commandArguments.Contains("-p") && commandArguments[commandArguments.IndexOf("-p") + 1].StartsWith("-") == false)
    Arg3 = commandArguments[commandArguments.IndexOf("-p") + 1];
else
{
    isCmdLineWrong = true;
}
if (isCmdLineWrong) Console.WriteLine("Parameters structure is inconsistent");

3 个答案:

答案 0 :(得分:4)

我建议提取 CommandLine

public static class CommandLine {
  private static String FindValue(string value) {
    var commandArguments = Environment.GetCommandLineArgs();

    int index = commandArguments.IndexOf(value);

    if (index < 0)
      return null; 
    else if (index >= commandArguments.Length - 1)
      return null; // cmd like "myRoutine.exe -p" 
    else 
      return commandArguments[index + 1];  
  } 

  static CommandLine() {
    Arg1 = FindValue("-r");
    Arg2 = FindValue("-n");
    Arg3 = FindValue("-p");
  } 

  public static String Arg1 { get; private set; }

  public static String Arg2 { get; private set; }

  public static String Arg3 { get; private set; }

  public static bool IsValid {
    get {
      return Arg1 != null && Arg2 != null && Arg3 != null;
    }
  }
}

写完这堂课后你可以把

if (!CommandLine.IsValid) {
  Console.WriteLine("Parameters structure is inconsistent");

  return;
} 

if (CommandLine.Arg1 == "quit") {
  ...
}  

答案 1 :(得分:1)

在你的代码中,最重要的一点是你做了几次完全相同的事情,尽管有不同的输入"-r"Arg1,{{ 1}}和"-n"Arg2"-p"。也就是说,您有以下代码片段出现三次(减去我的重新格式化):

Arg3

Don't Repeat Yourself (DRY) principle试图警告我们不要编写复制粘贴式重复代码,原始代码很明显违反了它。

我建议您提取公共代码并将其放在单独的方法中。例如:

if (commandArguments.Contains(…) &&
    arguments[commandArguments.IndexOf(…) + 1].StartsWith("-") == false)
{
    … = commandArguments[commandArguments.IndexOf(…) + 1];
}
else
{
    isCmdLineWrong = true;
}

现在,您可以使用以下内容替换重复的static bool TryGetArg(string commandArguments, string name, out string value) { // Debug.Assert(name.StartsWith("-")); if (commandArguments.Contains("-") && arguments[commandArguments.IndexOf(name) + 1].StartsWith("-") == false) { value = commandArguments[commandArguments.IndexOf(name) + 1]; return true; } else { value = null; return false; } } if

else

答案 2 :(得分:1)

这个问题是如何重用代码的简单示例。

  • 查找似乎已复制/粘贴的代码,
  • 把它放在一个函数中,
  • 副本之间的任何差异,将它们作为参数传递,
  • 用函数调用替换副本。

结果是

    // Returns this option's value from args, or null on error
    public string OptionValue(string[] args, string option)
    {
        try
        {
            if (args.Contains(option))
            {
                string value = args[args.IndexOf(option) + 1];  // reuse expressions as well

                if (!value.StartsWith("-"))
                    return value;
            }

            return null;    // null meaning "undefined"
        }
        catch
        {
            return null;  
        }
     }

     // And now your code
     string[] args = Environment.GetCommandLineArgs();

     string Arg1 = OptionValue(args, "-r"); 
     string Arg2 = OptionValue(args, "-n"); 
     string Arg3 = OptionValue(args, "-p"); 

     bool isCmdLineWrong = (Arg1 == null ||
                            Arg2 == null ||
                            Arg3 == null);

当然,如果您没有复制/粘贴代码,可以避免所有这些重写。