如何防止深凹痕?[关闭]


17

我可以采取什么步骤和措施来防止代码中的深缩进?


2
很多人会在这里谈论重构。也许这要问的太多了,但是如果您发布了一些(不太长的)缩进的代码,人们可以向您展示他们如何重构它。当然,那可能会使问题的语言具体化……
Paddyslacker 2010年

3
使用较小的标签宽度。
mipadi

6
箭头反模式。Google,它,大量提示
NimChimpsky 2010年

2
停止使用python:D
back2dos 2010年

现在该看看您的控制和循环逻辑了。您的代码可能比需要的复杂得多,对问题的重新概念化将导致代码短得多。学习好的代码并学习技巧。
Macneil

Answers:


14

如果程序中的每个函数/方法都只做一件事情,则深度缩进通常不是问题。有时,可能有必要将条件嵌套的深度加深几层,但是老实说,我在12年以上的编码中只写了几次缩进的缩进代码。


26

您可以做的最好的事情是提取方法:

int Step1(int state)
{
    if (state == 100)
    {
        return Step2(state);
    }
    else
    {
        return Step3(state);
    }
}

int Step2(int state)
{
    if (state != 100)
    {
        throw new InvalidStateException(2, state);
    }

    // ....
}

2
这也适用于复杂条件if。极端地说,您将获得可执行的伪代码。
艾伦·梅

我们可以做的其他最好的事情就是丢弃不必要的else块。
sepehr

16

也许您可以考虑使用保护条款

代替

public void DoSomething(int value){
    if (someCondition){
           if(someOtherCondition){
                if(yetAnotherCondition){
                       //Finally execute some code
                }
           }
    }
} 

public void DoSomething(int value){
    if(!(someCondition && someOtherCondition && yetAnotherCondition)){
        return;
        //Maybe throw exception if all preconditions must be true
    }
    //All preconditions are safe execute code
}

如果您有机会,我建议您阅读Steve McConnell的Code Complete。在这些主题上,他有很多很好的建议。

http://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670/ref=pd_sim_b_6

有关“保护条款”的更多信息,请参见:https : //sourcemaking.com/refactoring/replace-nested-conditional-with-guard-clauses


8

反转你的ifs。

代替:

if (foo != null)
{
    something;
    something;
    if (x)
    {        
       something;
    }
    something;
}
else
{
    boohoo;
}

我会写:

if (foo == null)
{
    boohoo;
    return;
}
something;
something;
if (x)
{        
   something;
}
something;

同样适用于if- else块。如果else较短/嵌套较少,则将其还原。

一处检查参数值

输入方法后,请立即检查所有参数的非法值,然后继续进行以确保安全。它使代码更具可读性,但同时又省去了以后堆积条件块并将这些检查散布到整个子例程中的麻烦。


1
此样式是否有特定名称?
Thomas Lauria

@ThomasLauria我不知道。它只是早退。If代码开头的s由于某些条件未得到满足而停止执行流,也称为安全保护子句,如@JasonTuran指出的那样。这似乎与拥有一个独特的名字差不多。
康拉德莫拉斯基

几年前,我的主管告诉我,这种风格被称为“线性编程”,但是我认为这是他的幻想;)
Thomas Lauria

4

通常,我已经看到深缩进的代码通常是有问题的代码。如果您遇到此问题,请退后一步,评估您的函数是否在做太多事情。

同时,要回答您的问题,如果需要深深的缩进,我建议您放在那里。出于简单的原因,在这样的代码中,缩进会有所帮助,因为它可能是很长的代码。


2

将嵌套的组件(尤其是重复的组件)分解为单独的函数(如果您的语言支持闭包,则更容易),或者将一系列嵌套循环替换为递归。

另外,缩进两个空格而不是四个空格。


5
一旦您完成了更改标签宽度的步骤,便陷入了严重的麻烦……
Daenyth 2010年

两个空间选项卡是硬的东西....
大卫·索恩利

6
更改缩排只是隐藏问题的一种方法,而不是解决方案
Murph 2010年

1

我不认为深层缩进是要解决的绝对问题(我也不认为重构是所有问题的真正答案)。

通常,我喜欢编写逻辑语句,而不是嵌套的ifs:

if (foo && bar && baz) 

而不是

if foo 
 if bar
   if baz

问题是,for和while循环中确实存在不属于该规则的循环。
Tamara Wijsman 2010年

@TomWij:我不是要引起对风格的绝对要求。
保罗·内森

1
??? `````
Tamara Wijsman

1

我自己不相信它,但是根据Code Complete的说法,这是一个合适的使用位置break(如果您的团队在其中)。我想这在C ++程序员中是可以接受的,但是breakswitch语句中使用它比在Delphi程序员中break使用,仅当您不想编写while循环时才使用。


0

实际上,缩进确实是一种可以战胜的想法。我学会做的是先将方法分成几部分,然后使用一个怪异的技巧,如果一件失败,则跳过接下来的每一部分。这是一个例子:

代替 :

 {if (networkCardIsOn() == true)
     {if (PingToServer() == true)
        {if (AccesLogin(login,pass) == true)
             {if (nextCondition == true)
                ...
         }
     }
 }

我目前写:

 {vbContinue = true;

 if (vbContinue) {
       vbContinue = networkCardIsOn();
       if (vbContinue == false) {
             code to Handle This Error();
       } 
 }

 if (vbContinue) {
       vbContinue = PingToServer();
       if (vbContinue == false) {
             code to HandleThisError2();
       } 
 }

 if (vbContinue) {
       vbContinue = AccesLogin(login,pass);
      if (vbContinue == false) {
             HandleThisErrorToo();
       } 
 }
 ...

一开始这对我来说似乎很奇怪,但是自从我使用它以来,维护成本已经减少了一半,并且最终我的大脑变得凉爽。

实际上,这种“技术”带来的好处是,由于代码的密度较小,因此代码的复杂度实际上被分割了。

阅读代码时,您无需记住任何有关过去条件的信息:如果您在代码中的X点,则前面的步骤已通过并且已经成功。

另一个好处是,简化了所有嵌套的“ if-else”中的“转义路径和条件”。


您能否详细说明一下“维护成本已减半”?此外,您如何才能真正知道停止执行该怎么办?
克里斯,2010年

我已经做了一些编辑。我希望我能回答您的问题...
Pierre Watelet 2010年

2
如果您想简单地走,则有一个goto error_handling行。
保罗·内森

不好 对不起,但事实并非如此。然后我
又很

3
为什么不直接使用try catch而不是模仿try catch?
Newtopian
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.