[C#] “if”문을 반전시켜 중첩을 줄입니다.

예를 들어 코드에서 ReSharper 를 실행했을 때 :

    if (some condition)
    {
        Some code...
    }

ReSharper는 위의 경고 (네 스팅을 줄이기 위해 “if”문을 반전시킵니다)를 알려주고 다음 수정 사항을 제안했습니다.

   if (!some condition) return;
   Some code...

왜 더 좋은지 이해하고 싶습니다. 나는 항상 “goto”와 같은 문제가있는 방법의 중간에 “return”을 사용한다고 생각했다.



답변

메소드 중간의 리턴이 반드시 나쁘지는 않습니다. 코드의 의도가 더 명확 해지면 즉시 반환하는 것이 좋습니다. 예를 들면 다음과 같습니다.

double getPayAmount() {
    double result;
    if (_isDead) result = deadAmount();
    else {
        if (_isSeparated) result = separatedAmount();
        else {
            if (_isRetired) result = retiredAmount();
            else result = normalPayAmount();
        };
    }
     return result;
};

이 경우 _isDead사실이면 즉시 메소드에서 벗어날 수 있습니다. 대신 이런 식으로 구성하는 것이 좋습니다.

double getPayAmount() {
    if (_isDead)      return deadAmount();
    if (_isSeparated) return separatedAmount();
    if (_isRetired)   return retiredAmount();

    return normalPayAmount();
};   

리팩토링 카탈로그 에서이 코드를 선택했습니다 . 이 특정 리팩토링을 다음과 같이 부릅니다. 중첩 조건부를 가드 절로 바꿉니다.


답변

미적 일뿐만 아니라 분석법 내부의 최대 중첩 수준을 줄 입니다. 이것은 일반적으로 더하기 쉬운 방법으로 이해하기 쉽기 때문에 플러스로 간주됩니다 (실제로 많은 정적 분석 도구 는 코드 품질의 지표 중 하나로이를 측정합니다).

다른 한편으로, 그것은 또한 당신의 분석법이 여러 출구 점을 가지도록합니다.

개인적으로 저는 ReSharper와 첫 번째 그룹에 동의합니다 (예외가있는 언어에서는 “다중 출구 점”에 대해 설명하기 어리석은 것으로 생각됩니다. 거의 모든 것이 던져 질 수 있으므로 모든 방법에 수많은 잠재적 출구 점이 있습니다).

성능과 관련 하여 모든 언어에서 두 버전 모두 동일 해야 합니다 (IL 수준이 아닌 경우 지터가 코드를 통과 한 후). 이론적으로 이것은 컴파일러에 따라 다르지만 실제로 널리 사용되는 오늘날의 컴파일러는 이보다 훨씬 고급 코드 최적화 사례를 처리 할 수 ​​있습니다.


답변

이것은 약간의 종교적인 주장이지만, ReSharper에 동의하면 중첩이 적어야한다는 데 동의합니다. 나는 이것이 함수에서 여러 리턴 경로를 갖는 것의 단점보다 중요하다고 생각합니다.

중첩이 적은 주요 이유는 코드 가독성과 유지 관리 성 을 향상시키기위한 입니다. 앞으로 많은 다른 개발자들이 코드를 읽을 필요가 있으며 들여 쓰기가 적은 코드는 일반적으로 읽기가 훨씬 쉽습니다.

전제 조건 은 함수 시작시 일찍 리턴하는 것이 좋은 예입니다. 전제 조건 점검의 존재로 나머지 기능의 가독성에 영향을 미치는 이유는 무엇입니까?

메소드에서 여러 번 리턴하는 것에 대한 부정적인 점은 디버거가 지금 매우 강력하며 특정 함수가 언제 어디서 언제 반환되는지를 쉽게 찾을 수 있습니다.

함수에 여러 개의 리턴이 있어도 유지 보수 프로그래머의 작업에는 영향을 미치지 않습니다.

코드 가독성이 좋지 않습니다.


답변

다른 사람들이 언급했듯이 성능 저하는 없어야하지만 다른 고려 사항이 있습니다. 이러한 유효한 우려 외에도 일부 상황에서는 문제가 발생할 수 있습니다. 당신이 double대신 처리하고 있다고 가정 해보십시오 .

public void myfunction(double exampleParam){
    if(exampleParam > 0){
        //Body will *not* be executed if Double.IsNan(exampleParam)
    }
}

외관상 동등한 반전 과는 대조적입니다 .

public void myfunction(double exampleParam){
    if(exampleParam <= 0)
        return;
    //Body *will* be executed if Double.IsNan(exampleParam)
}

따라서 어떤 상황에서는 올바르게 뒤집힌 것으로 보이는 것이 아닐 if수도 있습니다.


답변

언어가 예외를 지원하기 전날부터 함수가 끝날 때만 복귀한다는 아이디어가 나왔습니다. 그것은 프로그램이 메소드의 끝에 클린업 코드를 넣을 수 있고, 그것이 호출되고 다른 프로그래머가 클린업 코드를 건너 뛰게하는 메소드의 리턴을 숨기지 않을 것을 확신 할 수있게했습니다. . 정리 코드를 건너 뛰면 메모리 또는 리소스 누수가 발생할 수 있습니다.

그러나 예외를 지원하는 언어에서는 그러한 보장을 제공하지 않습니다. 예외를 지원하는 언어에서 명령문 또는 표현식을 실행하면 제어 플로우가 발생하여 메소드가 종료 될 수 있습니다. 즉, finally 또는 키워드를 사용하여 정리를 수행해야합니다.

어쨌든, 나는 많은 사람들이 왜 메소드가 좋은지 이해하지 못하고 ‘메소드의 끝에서만 리턴’가이드 라인을 인용한다고 생각합니다. 가독성을 높이기 위해 중첩을 줄이는 것이 더 나은 목표 일 것입니다.


답변

나는 가드 조항 인 경우 거꾸로 된 사람들의 이름이 있다고 덧붙이고 싶습니다. 가능할 때마다 사용합니다.

처음에 두 개의 코드 화면이 있고 다른 곳이 없다면 코드를 읽는 것이 싫습니다. 그냥 뒤집어 놓고 돌아옵니다. 그렇게하면 아무도 스크롤 시간을 낭비하지 않을 것입니다.

http://c2.com/cgi/wiki?GuardClause


답변

그것은 미학에 영향을 줄뿐만 아니라 코드 중첩을 방지합니다.

실제로 데이터가 유효한지 확인하기위한 전제 조건으로 작동 할 수 있습니다.