[Language-Agnostic] 거대한 조건을 어떻게 처리합니까?


Answers

나는 아무도 이것을 아직 얻지 못한 것에 놀랐다. 이러한 유형의 문제에 대한 리팩토링이 특별히 있습니다.

http://www.refactoring.com/catalog/decomposeConditional.html

Question

그것은 제가 사용해온 모든 언어에서 저를 괴롭혔습니다. if 문을 가지고 있지만 조건부 부분이 여러 줄로 나뉘어져 있고, if 문을 중첩하여 사용하거나 그냥 추한 것을 받아 들여야합니다. 내 인생과.

저와 다른 사람들이 같은 문제를 겪었다는 것을 당신이 발견 한 다른 방법이 있습니까?

예, 한 줄에 모두 :

if (var1 = true && var2 = true && var2 = true && var3 = true && var4 = true && var5 = true && var6 = true)
{

멀티 라인 예 :

if (var1 = true && var2 = true && var2 = true
 && var3 = true && var4 = true && var5 = true
 && var6 = true)
{

예 - 중첩 :

if (var1 = true && var2 = true && var2 = true && var3 = true)
{
     if (var4 = true && var5 = true && var6 = true)
     {



Perl에서이 작업을 수행했다면이 방법을 사용하여 검사를 수행 할 수 있습니다.

{
  last unless $var1;
  last unless $var2;
  last unless $var3;
  last unless $var4;
  last unless $var5;
  last unless $var6;

  ... # Place Code Here
}

서브 루틴을 통해 이것을 사용하려는 경우 return 의 모든 인스턴스를 return 대체하십시오.




나는 이것을 종종 부울 변수로 나눌 것이다.

bool orderValid = orderDate < DateTime.Now && orderStatus != Status.Canceled;
bool custValid = customerBalance == 0 && customerName != "Mike";
if (orderValid && custValid)
{
...



다른 사람들이 언급했듯이, 귀하의 조건을 분석하여 가독성을 높이기 위해 다른 방법으로 아웃소싱 할 수있는 방법이 있는지 확인합니다.




레벨별로 나누기를 좋아합니다. 예를 들면 다음과 같이 형식을 지정합니다.

if (var1 = true
 && var2 = true
 && var2 = true
 && var3 = true
 && var4 = true
 && var5 = true
 && var6 = true){

이 기능은 중첩이 더 많을 때 편리합니다 (모든 상황에서 "실제 조건"은 "= true"보다 더 재미있을 것입니다).

if ((var1 = true && var2 = true)
 && ((var2 = true && var3 = true)
  && (var4 = true && var5 = true))
 && (var6 = true)){



Kent Beck의 구현 패턴 을 확인하십시오. 이 상황에서 도움이 될 수있는 특정 패턴이 있습니다 ... "경비원"이라고합니다. 엄청난 조건을 갖는 것보다 가드로 분해 할 수 있으므로 어떤 방법의 불리한 조건인지 분명히 알 수 있습니다.

예를 들어, 무언가를하는 메소드가 있지만 뭔가가 아닌 다음과 같은 특정 조건이있는 경우 :

public void doSomething() {
    if (condition1 && condition2 && condition3 && condition4) {
        // do something
    }
}

다음과 같이 변경할 수 있습니다.

public void doSomething() {
    if (!condition1) {
        return;
    }

    if (!condition2) {
        return;
    }

    if (!condition3) {
        return;
    }

    if (!condition4) {
        return;
    }

    // do something
}

조금 더 장황하지만 더 읽기 쉽습니다. 특히 괴상한 중첩을 시작할 때 특히 경비원이 도움을 줄 수 있습니다 (추출 방법과 결합).

나는 그 책을 추천한다.




    if (   (condition_A)
        && (condition_B)
        && (condition_C)
        && (condition_D)
        && (condition_E)
        && (condition_F)
       )
    {
       ...
    }

반대로

    if (condition_A) {
       if (condition_B) {
          if (condition_C) {
             if (condition_D) {
                if (condition_E) {
                   if (condition_F) {
                      ...
                   }
                }
             }
          }
       }
    }

    if (   (   (condition_A)
            && (condition_B)
           )
        || (   (condition_C)
            && (condition_D)
           )
        || (   (condition_E)
            && (condition_F)
           )
       )
    {
       do_this_same_thing();
    }

반대로

    if (condition_A && condition_B) {
       do_this_same_thing();
    }
    if (condition_C && (condition_D) {
       do_this_same_thing();
    }
    if (condition_E && condition_F) {
       do_this_same_thing();
    }

연산자 우선 순위 규칙에 의존하지 않고 괄호 수가 적은 경우 여러 조건부식이 명시 적 괄호를 사용하여 식 분석을 지시하지 않으면 코드를 검사하는 대부분의 정적 분석 도구가 불만을 제기합니다.

동일한 들여 쓰기 수준의 동일한 들여 쓰기 수준에서 동일한 수직 들여 쓰기 (왼쪽 / 오른쪽 괄호 ()), 괄호가있는 조건부 표현식 및 연산자는 매우 유용한 연습으로, 모든 것을 방해하지 않고 코드의 가독성과 명확성을 크게 향상시킵니다. 한 줄에 끼어 있거나 수직 정렬, 공백 또는 괄호를 사용할 수 없습니다.

연산자 우선 순위 규칙은 까다 롭습니다. 예를 들어, &&는 ||보다 우선 순위가 높지만 | &&보다 우선 함

그래서 ...

    if (expr_A & expr_B || expr_C | expr_D & expr_E || expr_E && expr_F & expr_G || expr_H {
    }

단순한 인간이 부적절하게 읽고 평가할 수있는 매우 쉬운 여러 조건식입니다.

    if (   (  (expr_A)
            & (expr_B)
           )
        || (  (expr_C)
            | (  (expr_D)
               & (expr_E)
              )
           )
        || (   (expr_E)
            && (  (expr_F)
                & (expr_G)
               )
           )
        || (expr_H)
       )
    {
    }

가로 공간 (줄 바꿈), 세로 맞춤 또는 명시 적 괄호 유도 식 평가에 아무런 문제가 없습니다.이 모든 것이 읽기 쉽고 명확합니다.




글쎄, 먼저, 왜 안 :

if (var1 && var2 && var2 && var3 && var4 && var5 && var6) {
...

또한 추상 코드 예제를 리팩토링하는 것은 매우 어렵습니다. 구체적인 예를 보여 주면 문제에 더 잘 맞는 패턴을 쉽게 식별 할 수 있습니다.

더 나은 것은 아니지만 과거에 해왔 던 작업은 다음과 같습니다 (다음 방법은 부울 테스트의 단락을 방지합니다. 첫 번째 테스트가 false 인 경우에도 모든 테스트가 실행됩니다.) 코드를 반환하기 전에 - 내 실수를 발견하기위한 ptomato에 감사드립니다!)

부울 ok = cond1;
ok & = cond2;
ok & = cond3;
ok & = cond4;
ok & = cond5;
ok & = cond6;

어느 것이 같은 것인가 : (동일하지 않음, 상기 참고!)

확인 = (cond1 && cond2 && cond3 && cond4 && cond5 && cond6);




맥도웰,

식의 양쪽이 평가하는 단일 '&'연산자를 사용할 때 정확합니다. 그러나 '&&'연산자를 사용할 때 (적어도 C #에서는) 거짓을 반환하는 첫 번째 표현식이 평가 된 마지막 표현식입니다. 이것은 FOR 구문 앞에 evaulation을 넣는 것을 다른 어떤 방법과 마찬가지로 좋게 만든다.




코드 완성 에서 Steve Mcconell의 조언 : 다차원 테이블을 사용하십시오. 각 변수는 테이블에 대한 인덱스 역할을하며 if 문은 테이블 조회로 바뀝니다. 예를 들어, (size == 3 && weight> 70)이 테이블 항목 결정 [size] [weight_group]




Links