在c#中清理超级粗箭头反模式

时间:2017-07-13 14:53:15

标签: c# if-statement nested-loops

我对编码很陌生,我希望尽早摆脱不良习惯并开始编写干净,高效的代码。我正在开发一个引用API的控制台应用程序,我有一系列深度嵌套的“if if”(最多可达10级!)。

commonLogic forQuote = new commonLogic();

if (countryRes == CountryDes)
{
    //staying in country
    try2:
    //display reasons for travel
    Console.WriteLine("What Best Describes Your Reason For Traveling?");
    Console.WriteLine(" ");
    Console.WriteLine("1. United States Resident traveling Inside the U.S.");
    Console.WriteLine("2. Visiting United States For Business or Pleasure.");
    Console.WriteLine("3. Immigrating to The Unites States.");
    Console.WriteLine("4. Student, Faculty Member or Scholar With a J-1, F-1, H-3, M-1, or Q-1 Visa.");
    Console.WriteLine(" ");
    var x = Console.ReadLine();
    Console.Clear();

    if (x == "1")
    {
        //US resident
        //first print
        forQuote.gatherUserData();
    }
    else if (x == "2")
    {
        try3:
        //visiting the US
        Console.WriteLine("What Type of Coverage Do You Need?");
        Console.WriteLine(" "); 
        Console.WriteLine("1. Medical voerage");
        Console.WriteLine("2. Trip Cancellation");
        var r = Console.ReadLine();
        Console.WriteLine(" ");
        Console.Clear();

        if (r == "1")
        {
            //medical coverage
            Console.WriteLine("What Type of Medical Coverage Do You Want?");
            Console.WriteLine(" ");
            Console.WriteLine("1. Scheduled benifits");
            Console.WriteLine("2. Comprehensive Benifits");
            var s = Console.ReadLine();
            Console.WriteLine(" ");
            Console.Clear();

            if (s == "1")
            {
                //second print
                forQuote.gatherUserData();
            }
            else if (s == "2")
            {
                //comprehensive benifits
                //third print
                forQuote.gatherUserData();
            }
            else
            {
                //first else
                Console.WriteLine("Invalid Input. Please Try Again");
            }
        }
        else if (r == "2")
        {
            //trip canccelation
            //fourth print
            forQuote.gatherUserData();
        }
        else
        {
            //secondelse
            Console.WriteLine("Invalid Input. Please Try Again");
            goto try3;
        }
    }
    else if (x == "3")
    {
        //immigration
        //fithprint
        forQuote.gatherUserData();
    }
    else if (x == "4")
    {
        //students...
        //sixthprint
        forQuote.gatherUserData();
    }
    else
    {
        //thirdelse
        Console.WriteLine("Invalid Input. Please try Again");
        goto try2;
    }

}

这只是if s的这个粗巢的一小部分样本。我已经做了大量关于清理这项工作的研究,并且很难理解/使用我找到的答案。 我在重构时遇到的最大问题是,if之后的每一个都直接依赖于它之前的if

我还制作了一个逻辑表,说明了每个if所需的输入。如果它有用,我会把它放在这里: Excel table showing if paths

我真的很感激一些帮助,并解释为什么你的答案提高了可读性和效率也很好。

2 个答案:

答案 0 :(得分:1)

让我们先解决一些直接问题。

goto语句(错误):

这句话令人困惑,因为它不符合执行流程。它基本上说“在你必须找到的代码中转到这个任意点”。现在乘以3或4,你就会看到一堆迷宫传送点。你会非常快地迷路。

以下是如何解决此问题的示例:

<Button
        android:text="Sign In"
        android:layout_width="match_parent"
        android:layout_weight="20"
        android:layout_height="0dp"
        android:id="@+id/btnSignIn"
        android:background="@drawable/button_background"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        android:textSize="15sp"
        android:layout_marginTop="2dp" />

这个例子并不完美,从技术上讲,你不需要“继续”,但我想解释它的用法。

命名约定:

每个类名,变量名,方法名等都需要一个描述性标识符。 “循环”告诉我什么。通过命名尽可能具有描述性。如果在这样做之后仍然存在一些歧义,在定义中使用注释来清除它

嵌套循环:

好的,这是你的程序的整体设计。不幸的是,提出一系列依赖性问题的控制台应用程序将会变得混乱。

为什么?

因为用户界面框架(如WPF)可以更好地处理这种类型的逻辑。例如,您可以在按钮处理程序和控件属性中处理许多逻辑。

但是,您仍然可以改进代码。但是,它需要一个非常面向对象的设计。我会选择状态模式来开始。

州模式资源:http://www.dotnettricks.com/learn/designpatterns/state-design-pattern-c-sharp

然而,如果您对类,方法,对象,属性,处理程序等没有太多经验,那么高级并不容易理解。而且,它不是甚至减少你的工作量。事实上,它是为了可读性和可测试性而增加的,如果这是概念验证或实践,你可能都不需要它们。

因此,我的建议是一步一步地学习你的知识。开发最强大的解决方案是好的,但如果你刚刚开始就不行。每次挑选一件,直到你有足够的经验将它们放在一起。

答案 1 :(得分:0)

看看这段代码:

bool loop = true;

while(loop)
{
    Console.WriteLine("Question");
    Console.WriteLine("1. Ans1");
    Console.WriteLine("2. Ans2");
    Console.WriteLine("3. Exit");
    string resp = Console.ReadLine();

    switch(resp)
    {
        case "1":
        Console.WriteLine("Ans1 chosen");
        break;
        case "2":
        SomeQuestion();
        break;
        case "3":
        loop = false;
        break;
        default:
        Console.WriteLine("Invalid Input. Please try Again");
        break;        
    }
}

void SomeQuestion()
{
    bool loop = true;

    while(loop)
    {
        Console.WriteLine("Question secon level");
        Console.WriteLine("1. Ans3");
        Console.WriteLine("2. Ans4");
        Console.WriteLine("3. Exit");
        string resp = Console.ReadLine();

        switch(resp)
        {
            case "1":
            Console.WriteLine("Ans1 chosen");
            break;
            case "2":
            break;
            case "3":
            loop = false;
            break;
            default:
            Console.WriteLine("Invalid Input. Please try Again");
            break;        
        }
    }    
}

这很简单,只有一个问题,但显示了想法。

  • 改为使用条件转到循环。
  • 相反,如果一个开关使代码更具可读性。