✏️1.7 중간 점검: 두 파일(과 두 단계)로 분리됨

현재 코드는 두 개의 파일로 구성된다.

🧷 statement.js

import createStatementData from './createStatementData.js';

function statemnt(invoice, plays) {
  return renderPlainText(createStatementData(invoice, plays));
}

function renderPlainText(data, plays) {
  let result = `청구 내역(고객명): ${invocie.customer})\n`;
  
  for (let perf of invoice.performaces) {
    result += ` ${playFor(perf).name}: ${usd(perf.amount)} ($perf.audience}석)\n`;  
  
  result += `총액: ${usd(totalAmount())}\n`;	
  result += `적립 포인트: ${totalVolumeCredits()}점\n`;
  return result;
}

function htmlStatemnt(invoice, plays) {
  return renderHtml(createStatementData, plays));
}

function renderHtml(data) {
  let result = `<h1>청구 내역(고객명): ${data.customer})</h1>\n`;
  result += "<table>\n";
  
  ...
    
  return result;
}

function usd(aNumber) {
  return new Intl.NumberFormat("en-US", 
             { style: "currency", currency: "USD", 
      		   minimumFractionDigits: 2 }).format(aNumber/100);
}

🧷 createStatementData.js

export default function createStatementData(invoice, plays) {
  const result = {};
  result.customer = invoice.customer; 
  result.performances = invoice.performances.map(enrichPerformance);
  result.totalAmount = totalAmount(result);	
  result.totalVolumeCredits = totalVolumeCredits(result);
  return result;
  
  function enrichPerformance(aPerformance) {
    const result = Object.assign({}, aPerformance); 
    result.play = playFor(result); 
    result.amount = amountFor(result);
    result.volumeCredits = volumeCreidtsFor(result);
    return result;
  }
  
  function playFor(aPerformance) {
    return plays[aPerformance.playID]
  }
  
  function amountFor(aPerformance) {
    let result = 0;
    switch (aPerformance.play.type) { 
    case "tragedy":
      result = 40000;
      if (perf.audience > 30) {
        result += 1000 * (aPerformance.audience - 30);
      }
      break;
    case "comedy":
      result = 30000;
      if (perf.audience > 20) {
        result += 1000 + 500 * (aPerformance.audience - 20);
      }
      result += 300 * aPerformance.audience
      break;
    default:
      throw new Error(`알 수 없는 장르: ${aPerformance.play.type}`);
    }
    return result;
  }
  
  function volumeCreditsFor(aPerformance) {
    let result = 0;
    volumeCredits += Math.max(aPerformance.audience - 30, 0);
    if ("comedy" === playFor(aPerformance).type) 
      volumeCredits += Math.Floor(aPerformance.audience / 5 );
    return result;
  }
  
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); 

44줄짜리 코드가 html을 제외해도 70줄이나 된다. 하지만 추가된 코드 덕분에 전체 로직을 구성하는 요소 각각이 뚜렷이 부각되고, 계산되는 부분과 출력 형식을 다루는 부분이 분리됐다. 모듈화하면서 각 부분이 하는 일과 그 부분들이 맞물려 돌아가는 과정을 파악하기 쉬워졌다.

프로그래밍에서만큼은 간결함보다는 명료함이 진화할 수 있는 소프트웨어의 정수이다. 모듈화한 덕분에 계산 코드를 중복하지 않고도 HTML 버전을 만들 수 있었다.

Last updated