정상 흐름이 아닌 경우를 함수 앞부분에서 검사하고 바로 빠져나오는 조건문. 중첩된 if-else를 평평하게 펴서 핵심 흐름을 드러낸다.
// before
function payAmount() {
let result
if (isDead) result = deadAmount()
else {
if (isSeparated) result = separatedAmount()
else result = isRetired ? retiredAmount() : normalPayAmount()
}
return result
}
// after
function payAmount() {
if (isDead) return deadAmount()
if (isSeparated) return separatedAmount()
if (isRetired) return retiredAmount()
return normalPayAmount()
}- if-else는 "두 갈래가 똑같이 중요하다"고 말하고, 보호 구문은 "이건 핵심이 아니니 처리하고 나간다"고 말한다. 의도를 전달하는 방식이 다르다
- 조건을 뒤집어 적용하는 경우도 많다(
capital > 0이면 진행 →capital <= 0이면 반환) - 함수의 return이 하나여야 한다는 규칙에 매이지 않는다. 할 일을 마쳤으면 return으로 분명히 알린다
- 반복문 안의 제어 플래그(Control Flag) 변수도 같은 이유로
break·return으로 바꾼다. 가변 변수가 하나 줄어든다(제어 플래그를 탈출문으로 바꾸기, Replace Control Flag with Break) - 보호 구문으로 바꾸고 나면 "기본값 반환" 같은 설명 주석이 필요 없어지는 경우가 많다
켄트 벡의 첫 번째 정리 기법(1장 "보호 구문")이기도 하다(정리(Tidying)). TypeScript에서는 보호 구문이 그대로 타입 좁히기(Type Narrowing) 역할을 한다.
출처: 『리팩터링 2판』 마틴 파울러 (원서 Refactoring, 2nd Edition) · refactoring.com: Replace Nested Conditional with Guard Clauses · Refactoring.Guru: Replace Nested Conditional with Guard Clauses · 『켄트 벡의 Tidy First?』 켄트 벡 (원서 Tidy First?)