refactoring 1: let's start

예제를 통한 리팩터링 맛보기
refactoring

함수 추출하기


임시 변수를 질의 함수로 바꾸기, 변수 인라인하기

function playFor(aPerformance) {
  return plays[aPerformance.playID];
}

function statement(invoice, plays) {
  ...
  for(let perf of invoice.performance) {
    // AS-IS: const play = playFor(perf);
    // TO-DO: 불필요한 변수를 제거하고 아래처럼 사용
    if ('comedy' === playFor(perf).type) {...}
  }
}


반복문 쪼개기

function statement(invoice, plays) {
  let totalAmount = 0;
  let volumeCredits = 0;
  let result = `청구 내역 (고객명: ${invoice.customer}`;

  for (let perf of invoice.performances) {
    result += ~;
    totalAmount += ~;
  }

  for (let perf of invoice.performances) {
    volumeCredits += volumeCreditsFor(perf);
  }

  ...
}


반복문을 파이프라인으로 바꾸기

function totalAmount(data) {
  return data.performances.reduce((total, p) => total + p.amount, 0);
}

function totalVolumeCredits(data) {
  return data.performances.reduce((total, p) => total + p.volumeCredits, 0);
}


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

function createPerformanceCaculator(aPerforamnce, aPlay) {
  switch (aPlay.type) {
    case 'tragedy': return new TragedyCaculator(aPerforamnce, aPlay);
    case 'comedy': return new ComedyCaculator(aPerforamnce, aPlay);
    default: throw new Error(`알 수 없는 장르: ${aPlay.type}`);
  }
}

// ...(중략)...

class PerformanceCaculator {
  constructor(aPerformance, aPlay) {
    this.performance = aPerformance;
    this.play = aPlay;
  }

  get amount() {
    throw new Error('서브클래스에서 처리하도록 설계되었습니다.');
  }

  get volumeCredits() {
    return Math.max(this.performance.audience - 30, 0);
  }
}

class TragedyCaculator extends PerformanceCaculator {...}
class ComedyCaculator extends PerformanceCaculator {...}


마무리