Book | 리펙터링 2판 1.3~1.4장

sik2·2022년 8월 6일
0

리뷰

목록 보기
9/12

리펙터링의 첫단계

리펙터링하기 전에 제대로 된 테스트부터 마련한다. 테스트는 반드시 자가진단하도록 만든다.

  • 리펙터링할 코드 영역을 꼼꼼하게 검사해줄 테스트 코드들부터 마련해야 한다.
  • 리펙터링에서 테스트의 역할은 굉장히 중요하다.

Statement() 함수 쪼개기

  • 중간의 switch 문을 함수 추출하기를 통해 분리한다.
  • amountFor() 함수로 분리한다.
function statement(invoice, plays) {
  let totalAmount = 0;
  let volumeCredits = 0;
  let result = `청구 내역(고객명: ${invoice.customer})\n`;
  const format = new Intl.NumberFormat("en-US", {
    style: "currency",
    currency: "USD",
    minimumFractionDigits: 2
  }).format;

  for (let perf of invoice.performances) {
    const play = plays[perf.playID]; // object {name, type}
    let thisAmount = 0;
    switch (play.type) { //<= 해당 switch 문
      case "tragedy": //비극
        thisAmount = 40000;
        if (perf.audience > 30) thisAmount += 1000 * (perf.audience - 30);
        break;
      case "comedy": //희극
        thisAmount = 30000;
        if (perf.audience > 20) thisAmount += 1000 + 500 * (perf.audience - 20);
        thisAmount += 300 * perf.audience;
        break;
      default:
        throw new Error(`알 수 없는 장르: ${play.type}`);
    }
    // 포인트를 적립한다.
    volumeCredits += Math.max(perf.audience - 30, 0);
    // 희극 관객 5명마다 추가 포인트를 제공한다.
    if ("comedy" === play.type) volumeCredits += Math.floor(perf.audience / 5);

    // 청구 내역을 출력한다.
    result += `${play.name}: ${format(thisAmount / 100)} (${
      perf.audience
    }석)\n`;
    totalAmount += thisAmount;
  }
  result += `총액: ${format(totalAmount / 100)}\n`;
  result += `적립 포인트: ${volumeCredits}점\n`;
  return result;
}

amountFor() 추출

function statement(invoice, plays) {
  let totalAmount = 0;
  let volumeCredits = 0;
  let result = `청구 내역(고객명: ${invoice.customer})\n`;
  const format = new Intl.NumberFormat("en-US", {
    style: "currency",
    currency: "USD",
    minimumFractionDigits: 2
  }).format;
  
  function amountFor(perf, play) { // 함수 추출
    let thisAmount = 0;
    switch (play.type) { //<= 해당 switch 문
      case "tragedy": //비극
        thisAmount = 40000;
        if (perf.audience > 30) thisAmount += 1000 * (perf.audience - 30);
        break;
      case "comedy": //희극
        thisAmount = 30000;
        if (perf.audience > 20) thisAmount += 1000 + 500 * (perf.audience - 20);
        thisAmount += 300 * perf.audience;
        break;
      default:
        throw new Error(`알 수 없는 장르: ${play.type}`);
    }
    return thisAmount;
  }

  for (let perf of invoice.performances) {
    const play = plays[perf.playID]; // object {name, type}
    let thisAmount = amountFor(perf, play); // 추출 함수 호출
    // 포인트를 적립한다.
    volumeCredits += Math.max(perf.audience - 30, 0);
    // 희극 관객 5명마다 추가 포인트를 제공한다.
    if ("comedy" === play.type) volumeCredits += Math.floor(perf.audience / 5);

    // 청구 내역을 출력한다.
    result += `${play.name}: ${format(thisAmount / 100)} (${
      perf.audience
    }석)\n`;
    totalAmount += thisAmount;
  }
  result += `총액: ${format(totalAmount / 100)}\n`;
  result += `적립 포인트: ${volumeCredits}점\n`;
  return result;
}

변수 이름 명확하게 수정

컴퓨터가 이해하는 코드는 바보도 작성할 수 있다. 사람이 이해하도록 작성하는 프로그래머가 진정한 실력자다.

  • amountFor 함수 안에 변수 thisAmount 이름을 result로 바꾸기
  • 변수 perf 이름을 aPerformance 로 바꾼다.(동적언어에 타입을 표시하기 위해 부정관사 a/an the를 활용했다. 개인적으로 performance로 써도 되지 않을까?)
  function amountFor(aPerformance, play) { // 함수 추출
    let result = 0;
    switch (play.type) { //<= 해당 switch 문
      case "tragedy": //비극
        result = 40000;
        if (aPerformance.audience > 30) result += 1000 * (aPerformance.audience - 30);
        break;
      case "comedy": //희극
        result = 30000;
        if (aPerformance.audience > 20) result += 1000 + 500 * (aPerformance.audience - 20);
        result += 300 * aPerformance.audience;
        break;
      default:
        throw new Error(`알 수 없는 장르: ${play.type}`);
    }
    return result;
  }
profile
기록

0개의 댓글