리펙터링하기 전에 제대로 된 테스트부터 마련한다. 테스트는 반드시 자가진단하도록 만든다.
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;
}
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;
}
컴퓨터가 이해하는 코드는 바보도 작성할 수 있다. 사람이 이해하도록 작성하는 프로그래머가 진정한 실력자다.
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;
}