회사에서 코드 리뷰를 하다가 알게된 if-else 대신 빨리 return하는 코딩 스타일인데 접해보지 않은 분들도 계실것같아 올려봅니다. stack overflow에도 Programming style: should you return early if a guard condition is not satisfied?란 제목으로 글이 올라와 있기도 하고 effective go에도 간단히 언급되어 있는 스타일입니다.
stackoverflow에 있는 질문을 옮겨보자면 다음 두가지 코딩 스타일 중 어느것이 나은가라는 것입니다.
1. 반환값을 만들고 if문 또는 if else를 사용하는 경우
returnVal = null; if (bar()) { returnVal = baz(); } return returnVal;
2. 조건이 안맞으면 바로 리턴하는 경우
if (!bar()) { return null; } return baz();
저는 이 두가지 방법중 2번 방법을 선호합니다. 그 이유는 bar() 조건이 안맞는 경우 빨리 리턴해버림으로써 그 아래 코드를 읽을때 bar 조건이 안맞는 경우를 머리 속에서 제외하고 생각할 수 있기 때문에 코드 읽기가 쉬워지기 때문입니다. 위의 코드 정도야 간단해 보이지만 다음과 같이 복잡한 if-else 경우를 생각해보죠.
if (condition1) { foo1(); } else if (condition2) { foo2(); } else { // condition1 == false && condition2 == false foo3(); }
이 예에서는 간단히 foo1(), foo2(), foo3() 정도만 호출했지만 실제로는 블럭 사이에 코드가 길어질 수 있고 그 경우 코드를 위에서 아래로 읽어오다가 마지막 else 문을 만나면 앞서 확인한 조건들이 무엇인지 잊어버리기 쉽습니다. 그런 이유로 위에처럼 주석에 어떤 조건들이 제외되었는지 적어주는 스타일이 사용되기도 하죠.
그런데 이 경우는 return 을 빨리 해버리면 더 쉽게 읽고 쓸 수 있습니다.
if (condition1) { foo1(); return; } if (condition2) { foo2(); return; } foo3();
위에서 아래로 오면서 condition1 이 만족되면 바로 return 해버립니다. 그렇기 때문에 그 아래 if 문을 읽을땐 condition1을 머리속에서 지워버릴 수 있고, 마찬가지로 condition2에서 return 을 빨리 해버리면 condition2를 머리속에서 지워버릴 수 있어서 foo3()을 읽을때 앞서 제외된 조건이 무엇이었는지 기억하는데 부담이 덜합니다.
좀 더 극단적인 경우를 비교해보겠습니다. 다음은 if-else를 중첩하여 사용한 경우입니다.
if (condition1) { foo1(); if (condition2) { foo2(); } else { foo3(); } } else { foo4(); }
같은 코드를 적극적으로 return 하는 형태로 바꾸면 다음과 같습니다.
if (!condition1) { foo4(); return; } foo1(); if (condition2) { foo2(); return; } foo3();
한 함수의 길이가 20-30 라인으로 제한되면 좋다는 것이야 누구나 알지만, 바쁜 일정속에 리팩토링에 몸을 던지는 용감한 희생자가 없는한 코드는 길어지기 마련이라 복잡한 if-else는 종종 볼 수 있습니다. 더구나 마지막 예에서 보인바와같이 if-else가 한없이 깊어지기만 할 때도 있죠. 하지만 위와같이 빠른 return을 사용하면 그 복잡한 중첩들을 없앨 수 있게됩니다.