✏️6.8 매개변수 객체 만들기 (Introduce Parameter Object)

function amountInvoiced(startDate, endDate) {...}
function amountReceived(startDate, endDate) {...}
function amountOverdue(startDate, endDate) {...}

리팩터링 후

function amountInvoiced(aDateRange) {...}
function amountReceived(aDateRange) {...}
function amountOverdue(aDateRange) {...}

🧷 배경

데이터 항목 여러 개가 이 함수에서 저 함수로 함께 몰려다니는 경우 데이터 무리를 데이터 구조 하나로 모아준다.

📍 데이터 뭉치를 데이터 구조로 묶으면

  • 데이터 사이의 관계가 명확해진다.

  • 매개변수 수가 줄어든다.

  • 같은 데이터 구조를 사용하는 모든 함수가 원소를 참조할 때 항상 똑같은 이름을 사용하기 때문에 일관성도 높여준다.

🧷 절차

  1. 적당한 데이터 구조가 아직 마련되어 있지 않다면 새로 만든다. (저자는 동작까지 함께 묶는게 좋기 때문에 클래스로 만드는 걸 선호한다.)

  2. 테스트한다.

  3. 함수 선언 바구기로 새 데이터 구조를 매개변수로 추가한다.

  4. 테스트한다.

  5. 함수 호출 시 새로운 데이터 구조 인스턴스를 넘기도록 수정한다.

  6. 하나씩 수정할 때마다 테스트한다.

  7. 기존 매개변수를 사용하던 코드를 새 데이터 구조의 원소를 사용하도록 바꾼다.

  8. 다 바꿨다면 기존 매개변수를 제거하고 테스트한다.

🧷 예시

🧷 리팩터링 전

온도 측정값 배열에서 정상 작동 범위를 벗어난 것이 있는지 검사하는 코드

◽️ 온도 측정값을 표현하는 데이터

const station = { name: "ZB1", 
                readings: [
                  {temp: 47, time: "2016-11-10 09:10"},
                  {temp: 47, time: "2016-11-10 09:10"},
                  {temp: 47, time: "2016-11-10 09:10"},
                  {temp: 47, time: "2016-11-10 09:10"},
                  {temp: 47, time: "2016-11-10 09:10"},
                ]
              };    

◽️ 정상 범위를 벗어난 측정값을 찾는 함수

function readingsOutsideRange(station, min, max) {
  return station.readings 
    .filter(r => r.temp < min || r.temp > max);
  }

◽️ 호출문

alerts = readingsOutsideRange(station,
                              operatingPlan.temperatureFloor,  // 최저온도
                              operatingPlan.temperatureCeiling);  // 최고 온도

호출 코드를 보면 operatingPlan의 데이터 항목 두 개를 쌍으로 가져와서 readingsOutsideRange()로 전달한다.

🧷 리팩터링 과정

  1. 묶은 데이터를 표현하는 클래스를 선언한다.

class NumberRange {
  constructor(min, max) {
    this._data = {min: min, max: max}
    }
    get min() {return this._data.min;}
    get max() {return this._data.max;}
  }
  1. 새로 만든 객체를 readingsOutsideRange()의 매개변수로 추가하도록 함수 선언을 바꾼다.

function readingsOutsideRange(station, min, max, range) {
  return station.readings
    .filter(r => r.temp < min || r.temp > max);
  }
  1. 온도 범위를 객체 형태로 전달하도록 호출문을 하나씩 바꾼다.

const range = new NumberRange(operatingPlan.temperatureFloor,
                                 operatingPlan.temperatureCeiling);

alerts = readingsOutsideRange(station,
                operatingPlan.temperatureFloor,  
                operatingPlan.temperatureCeiling,
                range);  
  1. 기존 매개변수 사용하는 부분을 변경한다.

🧷 리팩터링 후

function readingsOutsideRange(station, range) {
  return station.readings
    .filter(r => r.temp < range.min || r.temp > range.max);
  }
const range = new NumberRange(operatingPlan.temperatureFloor,
                                 operatingPlan.temperatureCeiling);

alerts = readingsOutsideRange(station,range); 

Last updated