ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Refactoring] 10장 : 조건부 로직 간소화
    책/Refactoring 2판 2024. 2. 14. 11:37
    반응형

    조건문 분해하기

    // before
    if (!aDate.isBefore(plan.summerStart) && !aDate.isAfter(plan.summerEnd)) {
        charge = quantity * plan.summerRate;
    }
    else {
        charge = quantity * plan.regularRate + plan.regularServiceCharge;
    }
    
    // after
    if (summer()) {
        charge = summerCharge();
    }
    else {
        charge = regularCharge();
    }
    • 복잡한 조건문은 코드를 어렵게 만드는 원흉이다.
    • 코드를 부위별로 분해한 다음 코드 덩어리들을 의도를 살린 이름의 함수 호출로 바꿈

    조건식 통합하기

    // before
    if (someExp1) return 0;
    if (someExp2) return 0;
    if (someExp3) return 0;
    
    // after
    if (someFunc()) return 0;
    
    function someFunc() {
        return (someExp1 || someExp2 || someExp3);
    }
    • 조건은 다르나 결과가 같은 여러 조건문이 있을 때 조건 검사 함수를 만들어 하나로 통합한다.

    중첩 조건문을 보호 구문으로 바꾸기

    // before
    function getPayAmount() {
        let result;
    
        if (isDead) {
            result = deadAmount();
        }
        else {
            if (isSeperated) {
                result = separatedAmount();
            }
            else {
                if (isRetired) {
                    result = retiredAmount();
                }
                else {
                    result = normalAmount();
                }
            }
        }
    
        return result;
    }
    
    // after
    function getPayAmount() {
        if (isDead) return deadAmount();
        if (isSeperated) return separatedAmount();
        if (isRetired) return retiredAmount();
        return normalAmount();
    }
    • 조건문이 주로 쓰이는 두 가지 형태
      • 참, 거짓 경로 모두 정상 동작일 때
      • 한쪽만 정상인 형태 (보호 구문)
    • 한쪽만 정상인 경우, 비정상 조건을 if에서 검사하고 참이면 바로 리턴하는 방식으로 구현하는게 가독성이 좋음

    조건부 로직을 다형성으로 바꾸기

    // before
    switch (bird.type) {
        case '유럽 제비':
            return "보통이다";
        case '아프리카 제비':
            return "지쳤다";
        case '노르웨이 파랑 앵무':
            return "그을렸다";
        default:
            return "알 수 없다";
    }
    
    // after
    class Bird {
            get plumage() {
                    return "알 수 없다";    
            }
    }
    
    class EuropeanSwallow extends Bird {
        get plumage() {
            return "보통이다";
        }
    }
    
    class AfricanSwallow extends Bird {
        get plumage() {
            return "지쳤다";
        }
    }
    
    class NorwegianBlueParrot extends Bird {
        get plumage() {
            return "그을렸다";
        }
    }
    • 다형성을 이용하여 복잡한 switch 문을 처리할 수 있다.
    • Bird bird = new EuropeanSwallow() 와 같이 사용하여 동작을 처리할 수 있다.
    • 자바의 경우 추상 클래스, 인터페이스를 이용해서 더 유연하게 가능
    • 무조건 모든 if 나 switch에 다형성을 적용하라는 것은 아니고, 복잡하거나 매우 자주 나타날 때 이렇게 할 수도 있다는 참고로써 사용

    특이 케이스 추가하기

    // before
    if (customer === "미확인 고객") customerName = "거주자";
    
    // after
    class UnknownCustomer {
        get name() {return "거주자";}
    }
    • 특정 값에 대해 똑같은 동작을 수행하는 코드가 여러 곳이라면 이를 한 곳에 모으는 게 좋다.
    • 특이 케이스는 클래스로 만들 수도 있고, 리터럴 객체 형태로 준비할 수도 있다.
    • 솔직히 잘 모르겠다..이렇게까지 해야하나? 걍 함수로 빼놓는 정도면 될 거 같긴 한데

    어서션 추가하기

    // before
    if (this.discountRate) {
        base = base - (this.discountRate * base);
    }
    
    // after
    assert(this.discountRate >= 0);
    if (this.discountRate) {
        base = base - (this.discountRate * base);
    }
    • 특정 조건이 참일 때만 제대로 동작하는 코드가 있을 수 있음
      • 제곱근 계산은 입력이 양수일때만 제대로 동작
      • 객체 필드 중 최소 하나에는 값이 들어있어야 동작하는 경우
    • 어서션을 코드에 추가하면 주석을 굳이 달지 않아도 쉽게 알 수 있다.
    • 어서션 : 항상 참이라고 가정하는 조건부 문장
      • 어서션이 들어간다고 해서 동작이 달라지지는 않는다.

    제어 플래그를 탈출문으로 바꾸기

    // before
    for (const p of people) {
        if (!found) {
            if (p === "조커") {
                sendAlert();
                found = true;
            }
        }
    }
    
    // after
    for (const p of people) {
        if (p === "조커") {
            sendAlert();
            break;
        }
    }
    • 플래그는 거의 좋을 때가 없다. 그냥 쓰지 말자.
    • 반복문의 경우 break, continue 등을 쓰는게 낫고, 함수의 경우에는 그냥 조건이 되면 바로 return 하는 것도 방법이다.

     

    https://product.kyobobook.co.kr/detail/S000001810241

    반응형
Designed by Tistory.