관리 메뉴

너와 나의 스토리

[리팩터링] 11.5 매개변수를 질의 함수로 바꾸기 Replace parameter with Query 본문

개발/Refactoring

[리팩터링] 11.5 매개변수를 질의 함수로 바꾸기 Replace parameter with Query

노는게제일좋아! 2022. 1. 18. 23:44
반응형

배경

  • 매개변수 목록은 함수의 변동 요인을 모아놓은 곳으로 함수의 동작에 변화를 줄 수 있는 일차적인 수단이다.
    • 다른 코드와 마찬가지로 이 목록에서도 중복은 피하는 게 좋으며 짧을수록 이해하기 쉽다.
  • 피호출 함수가 스스로 "쉽게" 결정할 수 있는 값을 매개변수로 건네는 것은 의미 없이 코드만 복잡해질 뿐이다..
  • 매개변수를 질의 함수로 바꾸지 말아야 할 상황도 있다. 
    • 매개변수를 제거하면 피호출 함수에 원치 않는 의존성이 생길 때
  • 주의 사항: 대상 함수가 참조 투명(referential transparency)해야 한다.
    • * 참조 투명: 함수에 똑같은 값을 건네 호출하면 항상 똑같이 동작
    • 따라서 매개변수를 없애는 대신 가변 전역 변수를 이용하는 일은 하면 안 된다.

 

절차

  1. 필요하다면 대상 매개변수의 값을 계산하는 코드를 별도 함수로 추출해놓는다.
  2. 함수 본문에서 대상 매개변수로의 참조를 모두 찾아서 그 매개수의 값을 만들어주는 표현식을 참조하도록 바꾼다. 하나 수정할 때마다 테스트한다.
  3. 함수 선언 바꾸기로 대상 매개변수를 없앤다.

 

예시

  • Order 클래스
    • class Order {
          // ...
      
          get finalPrice() {
              const basePrice = this.quantity * this.itemPrice;
              let discountLevel;
              if (this.quntity > 100) discountLevel = 2;
              else discountLevel = 1;
              return this.discountedPrice(basePrice, discountLevel);
          }
      
          discountedPrice(basePrice, discountLevel) {
              switch (discountLevel) {
                  case 1: return basePrice * 0.95;
                  case 2: return basePrice * 0.9;
              }
          }
      }
    • 함수를 간소화하다 보면 임시 변수를 질의 함수로 바꾸기를 적용할 때가 많다.
  • [Step 1] 매개변수의 값을 계산하는 코드를 별도 함수로 추출한다.
    • class Order {
          // ...
          
          get finalPrice() {
              const basePrice = this.quantity * this.itemPrice;
              return this.discountedPrice(basePrice, this.discountLevel)
          }
      
          get discountLevel(){
              return (this.quntity > 100) ? 2:1;
          }
      }
    • 그 결과 discountedPrice() 함수에 discountLevel()의 반환 값을 건넬 이유가 사라졌다. 필요할 때 직접 호출하면 되기 때문.
  • [Step 2] 이 매개변수를 참조하는 코드를 모두 함수 호출로 바꿔본다.
    • class Order {
          // ...
          get discountLevel(){
              return (this.quntity > 100) ? 2:1;
          }
      
          discountedPrice(basePrice, discountLevel) {
              switch (this. discountLevel) {
                  case 1: return basePrice * 0.95;
                  case 2: return basePrice * 0.9;
              }
          }
      }
  • [Step 3] 이제 함수 선언 바꾸기로 이 매개변수로 없앨 수 있다.
    • class Order {
          // ...
          get finalPrice() {
              const basePrice = this.quantity * this.itemPrice;
              return this.discountedPrice(basePrice);
          }
      
          get discountLevel() {
              return (this.quntity > 100) ? 2 : 1;
          }
      
          discountedPrice(basePrice) {
              switch (this.discountLevel) {
                  case 1: return basePrice * 0.95;
                  case 2: return basePrice * 0.9;
              }
          }
      }

 

 

 

출처:

- [리팩터링 2판]

반응형
Comments