예외 이후에 else를 사용하십시오.


9

이 코드 비트를 고려하십시오.

if (x == 1)
{
  throw "no good; aborting" ;
}

[... more code ...]

이제이 코드를 고려하십시오.

if (x == 1)
{
  throw "no good; aborting" ;
}
else
{
  [... more code ...]
}

두 경우는 정확히 같은 방식으로 작동합니다. 첫 번째 경우는의 나머지 코드를 "포함"할 필요가 없다는 장점이 있습니다 else. 두 번째는 명시 적으로 갖는 연습 다음과 같은 장점이있다 else모든를 들어 if.

누구든지 서로에게 유리한 주장을 할 수 있습니까?


5
당신이 명시 적으로 찬성하는 관행 else은 가짜로 보입니다. 종종 else뒤로 구부리지 않는 한 블록 에 넣을 것이 없습니다 .

일관성? 코드 변경시 견고성을 허용 하시겠습니까? 가독성?
Thomas Eding

1
어, 나는 모든 사람들에게 if필요한 아이디어의 팬이 아니다 else. 우리 코드베이스에서 일한 마지막 프로그래머는 엄격히 따랐습니다 ( 때로는 ... 일종의 정신 분열증입니다 ). 결과적으로 우리는 else { /* do nothing */ }코드를
어지럽히

4
"모든 경우에 대한 다른 것"은 (어리석은) 일관성이라는 이름으로 클라우드 설계자가 발행 한 기괴한 선포처럼 보입니다. 나는 그 관습을 따르는 데 이점이 없으며 어디에서도 들어 본 적이 없습니다.
Erik Dietrich

다른 중복입니다. .NET 스택으로 작업하는 경우 ReSharper를 설치하는 것보다 모든 중복 else 문을 제거하라는 메시지가 표시됩니다.
CodeART

답변:


16

a 또는 a를 포함하는 분기 와 같이 제어 흐름을 무조건 중단시키는 분기 else이후를 추가해서는 안됩니다 . 이렇게하면 지점에서 도입 한 불필요한 중첩 수준을 제거하여 프로그램의 가독성이 향상됩니다 .ifthrowreturnelse

한 번에 throw몇 번의 던지기가 포함되면 단일으로 다소 좋아 보이는 것이 실제로 추악하게됩니다.

void myMethod(int arg1, int arg2, int arg3) {
    // This is demonstrably ugly - do not code like that!
    if (!isValid(arg1)) {
        throw new ArgumentException("arg1 is invalid");
    } else {
        if (!isValid(arg2)) {
            throw new ArgumentException("arg2 is invalid");
        } else {
            if (!isValid(arg3)) {
                throw new ArgumentException("arg3 is invalid");
            } else {
                // The useful code starts here
            }
        }
    }
}

이 스 니펫은 동일한 기능을 수행하지만 훨씬 나아 보입니다.

void myMethod(int arg1, int arg2, int arg3) {
    if (!isValid(arg1)) {
        throw new ArgumentException("arg1 is invalid");
    }
    if (!isValid(arg2)) {
        throw new ArgumentException("arg2 is invalid");
    }
    if (!isValid(arg3)) {
        throw new ArgumentException("arg3 is invalid");
    }
    // The useful code starts here
}

+1 맞습니다. 두 번째 OP 사례는주의 깊게 읽고 WTF를 남겨 ​​둡니다. 하지만 ... 항상 방법을 짧게 만들려고 노력하십시오. 200 줄 중간의 리턴도 나쁘다.
Tulains Córdova

1
공정하게 말하면 반복 사용하는 경우 할 수 있습니다 else if.
Guvante

2
@Guvante : 각 if조건은 단일 조건을 테스트하고 조건이 true 인 경우이를 처리하며 조건이 false 인 경우 발생할 수있는 대체 항목이 없으면 else ifs가 필요하지 않습니다. 우리는 dasblinkenlight의 첫 번째 스 니펫 ( " pachinko machines ")과 같은 코드를 내 사무실에서 사용 합니다.
Blrfl

@Blrfl 파칭코 기계 아, 완벽한 비유 +1
Jimmy Hoffa

@ Blrfl : 반복 된 ifs가 너무 많은 중첩의 나쁜 예라고 언급하고있었습니다. 어쨌든 반복해서 중첩해서는 안됩니다. 일반적으로 소량의 코드에 대해 이야기하지 않는 한 포함 할 이유가 없음에 동의합니다 else.
Guvante

5

나는 당신이 반 패턴 (anti-pattern)이라고 언급하는 "명시적인 else"관행을 호출 할 것이다. 그것은 당신의 if에 대한 특별한 케이스 코드가 없다는 사실을 모호하게하기 때문이다.

가독성 / 유지 보수성은 일반적으로 필요한 코드 흐름 구성 만 가지고있을 때 개선되고 최소화됩니다. 이것은 여분의 것을 의미하며 if의 경우 전체 기능에 범위를 추가하여 따르고 유지하기가 더 어려워집니다.

예를 들어이 기능이 있다고 가정 해보십시오.

public void ConfigureOblogon(Oblogon oblogonToConfigure)
{
    if (_validColors.Contains(oblogonToConfigure.Color))
    {
        oblogonToConfigure.ColorIndex = _validColors.IndexOf(oblogonToConfigure.Color);
    }
    else
    {
        oblogonToConfigure.Color = _validColors[0];
        oblogonToConfigure.ColorIndex = 0;
    }
}

이제 구성 중에 oblogon의 유형 / 유형 색인을 지정해야한다는 요구 사항이 있습니다. 누군가 해당 코드를 배치하고 유효하지 않은 코드로 끝날 수있는 여러 범위가 있습니다.

public void ConfigureOblogon(Oblogon oblogonToConfigure)
{
    if (!_validOblogons.Contains(oblogonToConfigure.Type))
    {
        oblogonToConfigure.Type = _validOblogons[0];
        oblogonToConfigure.TypeIndex = 0;
        if (_validColors.Contains(oblogonToConfigure.Color))
        {
            oblogonToConfigure.ColorIndex = _validColors.IndexOf(oblogonToConfigure.Color);
        }
        else
        {
            oblogonToConfigure.Color = _validColors[0];
            oblogonToConfigure.ColorIndex = 0;
        }
    }
    else
    {
        oblogonToConfigure.TypeIndex = _validOblogons.IndexOf(oblogonToConfigure.Type);
    }
}

원본 코드가 최소한의 제어 흐름 구성으로 작성되고 그에 최소화 된 구성으로 작성된 경우와 비교하십시오.

public void ConfigureOblogon(Oblogon oblogonToConfigure)
{
    if (!_validColors.Contains(oblogonToConfigure.Color))
    {
        oblogonToConfigure.Color = _validColors[0];
    }

    oblogonToConfigure.ColorIndex = _validColors.IndexOf(oblogonToConfigure.Color);
}

실수로 잘못된 범위에 무언가를 넣거나 장기적인 성장과 유지 관리에 중복을 일으키는 팽만감 범위를 끝내는 것이 훨씬 더 어려울 것입니다. 또한이 기능을 통해 가능한 흐름이 무엇인지 알기 때문에 가독성이 향상되었습니다.

나는 그 예가 약간 고안되었다는 것을 알고 있지만, 나는 여러 번 보았다.

SomeFunction()
{
    if (isvalid)
    {
        /* ENTIRE FUNCTION */
    }
    /* Nothing should go here but something does on accident, and an invalid scenario is created. */
}

따라서 제어 흐름 구조에 대한 규칙을 공식화하면 사람들이 그런 코드를 작성할 때 냄새를 맡는 데 필요한 직관을 개발하는 데 도움이 될 것이라고 생각합니다. 그런 다음 그들은 쓰기 시작합니다 ..

SomeFunction()
{
    if (!isvalid)
    {
        /* Nothing should go here, and it's so small no one will likely accidentally put something here */
        return;
    }

    /* ENTIRE FUNCTION */
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.