깊은 들여 쓰기를 방지하는 방법? [닫은]


17

코드에서 들여 쓰기를 방지하기 위해 어떤 단계와 조치를 취할 수 있습니까?


2
많은 사람들이 여기서 리팩토링에 대해 이야기 할 것입니다. 어쩌면 이것은 너무 많은 질문 일지 모르지만 너무 들여 쓰지 않은 코드를 게시하면 사람들이 리팩토링하는 방법을 보여줄 수 있습니다. 물론, 그것은 아마도 질문 언어를 구체적으로 만들어 줄 것입니다.
Paddyslacker

3
작은 탭 너비를 사용하십시오.
mipadi

6
화살촉 안티 패턴. Google
IT

2
파이썬 사용 중지 : D
back2dos

제어 및 루프 로직을 살펴볼 차례입니다. 아마도 코드가 필요 이상으로 복잡하고 문제를 다시 개념화하면 코드가 훨씬 짧아 질 수 있습니다. 좋은 코드를 배우고 기술을 배우십시오.
Macneil

답변:


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조건 에서도 작동합니다 . 극단적으로, 실행 가능한 의사 코드로 끝납니다.
Alan Plum

우리가 할 수있는 다른 최선의 방법은 아마도 불필요한 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

"guard 조항"에 대한 자세한 내용은 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일부 조건이 충족되지 않아 실행 흐름을 중지시키는 코드 시작 부분에서 @JasonTuran이 지적한 것처럼 보호 절 이라고도 합니다. 그리고 그것은 분명한 이름을 가진 것에 가깝습니다.
Konrad Morawski

몇 년 전 관리자는이 스타일이 "선형 프로그래밍"으로 명명되었다고 말했지만 이것이 그의 환상이라고 생각합니다.)
Thomas Lauria

4

일반적으로 깊이 들여 쓰기 된 코드는 일반적으로 문제가있는 코드라는 것을 알았습니다. 이 문제가 발생하면 뒤로 물러서서 함수가 너무 많은 일을하고 있는지 평가하십시오.

동시에, 당신의 질문에 대답하기 위해, 들여 쓰기가 깊은 곳에서 필요하다면, 당신이 그것을 거기에 두도록 제안 할 것입니다. 그러한 코드에서 들여 쓰기는 매우 긴 코드 일 가능성이 있기 때문에 간단한 이유입니다.


2

중첩 된 구성 요소 (특히 반복되는 구성 요소)를 별도의 함수로 분리하거나 (언어가 클로저를 지원하는 경우 더 쉽습니다) 일련의 중첩 된 루프를 재귀로 대체합니다.

또한 4 개 대신 2 개의 공백을 들여 쓰기하십시오.


5
탭 너비를 변경하는 단계로 이동하면 큰 어려움에 처하게됩니다 ...
Daenyth

2

6
들여 쓰기를 변경하는 것은 해결책이 아니라 문제를 숨기는 방법 일뿐입니다.
Murph

1

깊은 들여 쓰기를 제거해야 할 범주 적 문제로 보지 않습니다 (리팩토링이 모든 것에 대한 진정한 답이라고 생각하지도 않습니다).

일반적으로 중첩 된 if 대신 논리 문을 작성하고 싶습니다.

if (foo && bar && baz) 

오히려

if foo 
 if bar
   if baz

문제는이 규칙에 해당하지 않는 for 및 while 루프도 존재한다는 것입니다.
Tamara Wijsman

@ TomWij : 스타일에 대한 범주 적 명령을 유도하려고하지 않습니다.
Paul Nathan

1
??? ``````
Tamara Wijsman

1

나는 그것을 믿지 않았지만 Code Complete에 따르면 이것이 사용하기에 적절한 장소입니다 break(팀이 승선 한 경우). 나는이 C ++ 프로그래머하지만, 더 허용 치지 break에서 사용 switch은 델파이 프로그래머보다 문 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"에서 "탈출 경로 및 조건"이 단순화된다는 것입니다.


"유지 보수 비용을 절반으로 나눈 것"에 대해 자세히 설명 할 수 있습니까? 또한 실행을 중단하면 실제로 어떻게 알 수 있습니까?
Chris

편집을했습니다. 나는 당신의 질문에 대답하기를 바랍니다 ...
Pierre Watelet

2
간단하게 가고 싶다면 goto error_handling 줄이 있습니다.
Paul Nathan

그것은 좋지 않다. 미안하지만 그것만은 아닙니다. 다시 나는 이상하다
Murph

3
try catch를 모방하는 대신 직접 사용하지 않습니까?
Newtopian
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.