๋ฆฌํŒฉํ† ๋ง 1์žฅ์„ ์‹œ์ž‘ํ•ด๋ณธ๋‹ค.

๋“ค์–ด๊ฐ€๋ฉด์„œ

  • ์˜ˆ์‹œ๊ฐ€ ๋จผ์ €๋‚˜์˜จ๋‹ค. ๋ฆฌํŒฉํ„ฐ๋ง์ด ๋ญ”์ง€ ์•Œ๋ ค์ฃผ๋Š” ๋‹จ๊ณ„์ด๋‹ค.
  • ์ด ์ฑ…์€ ๋ฆฌํŒฉํ„ฐ๋ง์ด ๋ฌด์—‡์ธ์ง€ ์•Œ๋ ค์ฃผ๊ณ , ์ด๋ฅผ ๊ฐ์ฒด์ง€ํ–ฅ ๋ฐฉ์‹์œผ๋กœ ๊ฐœ์„ ํ•˜๋Š” ๊ฒƒ์„ ์†Œ๊ฐœํ•œ๋‹ค.
  • ๊ฐ€์žฅ ํ•ต์‹ฌ์ธ ๋ถ€๋ถ„์€ ๋’ค์˜ ์นดํƒˆ๋กœ๊ทธ์ด๋‹ค. ์ˆ˜์‹œ๋กœ ์ฐพ์•„๋ณด๋ฉด์„œ ์ ์šฉํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•ด๋ผ. (๋งˆ์น˜ ๋””์ž์ธ ํŒจํ„ด ๊ฐ™๋„ค)
  • martin-fowler-refactoring-2nd์— ์†Œ์Šค๊ฐ€ ์žˆ๋‹ค.
  • ๊ฐœ๋…์„ ์ดํ•ดํ•ด์•ผ ์ฒ˜ํ•œ ์ƒํ™ฉ์— ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์ž, ์‹œ์ž‘ํ•ด๋ณด์ž.

function statement(invoice, plays) {
    let totalAmount = 0;
    let volumeCredits = 0;
    let result = '์ฒญ๊ตฌ ๋‚ด์—ญ (๊ณ ๊ฐ๋ช…: sfinvoice.customers) \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];
        let thisAmount = 0;
        switch (play.type) {
            case "tragedy": // ๋น„๊ทน
                thisAmount = 40000;
                if (perf.audience > 30) {
                    thisAmount += 1000 * (perf.audience - 30);
                }
                break;
            case "comedy": // ํฌ๊ทน
                thisAmount = 30000;
                if (perf.audience > 20) {
                    thisAmount += 10000 + 500 * (perf.audience - 20);
                }
                thisAmount += 300 * perf.audience;
                break;
            default:
                throw new Error('์•Œ ์ˆ˜ ์—†๋Š” ์žฅ๋ฅด: sfplay.typer');
        }
 
        //ํฌ์ธํŠธ๋ฅผ ์ ๋ฆฝํ•œ๋‹ค.
        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;
}

์˜ˆ์‹œ ํ”„๋กœ๊ทธ๋žจ์„ ๋ณธ ์†Œ๊ฐ

  • ํ•œ ํ•จ์ˆ˜๊ฐ€ 50์ค„์ด ๋„˜์–ด๊ฐ€๊ณ , ์ถ”์ƒํ™”๊ฐ€ ์•ˆ๋œ ์ฝ”๋“œ๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•˜์ž.
  • ์ฝ”๋“œ๊ฐ€ ๊ต‰์žฅํžˆ ์ง€์ €๋ถ„ํ•˜๋‹ค.
  • ๊ทธ๋Ÿฐ๋ฐ ์ง€์ €๋ถ„ํ•˜๋‹ค๊ณ  ๊ณ ์นœ๋‹ค๋Š” ๊ฒƒ์€ ๋‹น์œ„์„ฑ์ด ์ถฉ๋ถ„ํ• ๊นŒ?
  • ์‚ฌ์‹ค ์ปดํŒŒ์ผ๋Ÿฌ ์ž…์žฅ์—์„œ๋Š” ๋ณ„ ์ค‘์š”ํ•œ๊ฒŒ ์•„๋‹ˆ๋‹ค.
  • ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๋Š” ์‚ฌ๋žŒ๊ณผ ํ•จ๊ป˜ ์ผํ•œ๋‹ค.
  • ์‚ฌ๋žŒ์€ ์ฝ”๋“œ์˜ ๋ฏธ์  ์ƒํƒœ์— ๋ฏผ๊ฐํ•˜๋‹ค.

ํ”„๋กœ๊ทธ๋žจ์ด ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ธฐ์— ํŽธํ•œ ๊ตฌ์กฐ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด, ๋จผ์ € ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ์‰ฌ์šด ์ƒํƒœ๋กœ ๋ฆฌํŒฉํ„ฐ๋งํ•˜๊ณ  ๋‚˜์„œ ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•œ๋‹ค.

๋ฆฌํŒฉํ„ฐ๋ง์˜ ์ฒซ ๋‹จ๊ณ„

  • ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋“ค ๋ถ€ํ„ฐ ๋งˆ๋ จํ•œ๋‹ค.
  • ์ด๋Š” ๊ต‰์žฅํžˆ ์ค‘์š”ํ•˜๋‹ค.
  • ์‚ฌ๋žŒ์€ ๋ˆ„๊ตฌ๋‚˜ ์‹ค์ˆ˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • statement ํ•จ์ˆ˜๋ฅผ ๋ณด๋ฉด, ๊ฒฐ๊ตญ ๊ณต์—ฐ๋กœ ์ฒญ๊ตฌ์„œ๋ฅผ ๋งŒ๋“œ๋Š” ์ž‘์—…์ด๋‹ค.
  • ์ด๋Ÿฐ ๊ฒฝ์šฐ ๊ฒฐ๊ณผ๊ฐ’์„ ๋ฏธ๋ฆฌ ๋ช‡๊ฐœ ์ž‘์„ฑํ•ด๋‘๊ณ  (json) ํ…Œ์ŠคํŠธ ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ๋‹จ์ถ•ํ‚ค ํ•˜๋‚˜๋กœ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๊ฒŒ ์„ค์ •ํ•˜์ž.

๋ฆฌํŒฉํ„ฐ๋งํ•˜๊ธฐ ์ „์—, ์ œ๋Œ€๋กœ ๋œ ํ…Œ์ŠคํŠธ๋ถ€ํ„ฐ ๋งˆ๋ จํ•œ๋‹ค. ํ…Œ์ŠคํŠธ๋Š” ๋ฐ˜๋“œ์‹œ ์ž๊ฐ€์ง„๋‹จํ•˜๋„๋ก ๋งŒ๋“ ๋‹ค.

statement ํ•จ์ˆ˜ ์ชผ๊ฐœ๊ธฐ

  • ์ผ๋‹จ statementํ•จ์ˆ˜๋ฅผ ๋ฆฌํŒฉํ„ฐ๋ง ํ•ด๋ณด์ž.
  • ์ด๋ ‡๊ฒŒ ๊ธด ํ•จ์ˆ˜์˜ ๊ฒฝ์šฐ์—๋Š” ์ „์ฒด์˜ ๋™์ž‘์„ ๊ฐ๊ฐ์˜ ๋ถ€๋ถ„์œผ๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋Š” ์ง€์ ์„ ์ฐพ๋Š”๋‹ค.
  • ์ค‘๊ฐ„ ๋ถ€๋ถ„์˜ switch๋ฌธ์„ ๋ณด์ž.
switch (play.type) {
    case "tragedy": // ๋น„๊ทน
        thisAmount = 40000;
        if (perf.audience > 30) {
            thisAmount += 1000 * (perf.audience - 30);
        }
        break;
    case "comedy": // ํฌ๊ทน
        thisAmount = 30000;
        if (perf.audience > 20) {
            thisAmount += 10000 + 500 * (perf.audience - 20);
        }
        thisAmount += 300 * perf.audience;
        break;
    default:
        throw new Error('์•Œ ์ˆ˜ ์—†๋Š” ์žฅ๋ฅด: sfplay.typer');
}
  • ํ•œ ๋ฒˆ์˜ ๊ณต์—ฐ์— ๋Œ€ํ•œ ์š”๊ธˆ์„ ๊ณ„์‚ฐํ•˜๊ณ  ์žˆ๋‹ค.
  • ์ด๋Š” ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•ด์„œ ์–ป์€ ์ •๋ณด๋‹ค. ํœ˜๋ฐœ์„ฑ์ด ๋†’๋‹ค.
  • ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์—, ํ•ด๋‹น ์ฝ”๋“œ์— ์ถ”๊ฐ€์ ์ธ ์˜๋ฏธ๋ฅผ ๋ถ€์—ฌํ•˜์—ฌ ํ•จ์ˆ˜๋กœ ๋นผ๋‘์ž.
function statement(invoice, plays) {
    let totalAmount = 0;
    let volumeCredits = 0;
    let result = '์ฒญ๊ตฌ ๋‚ด์—ญ (๊ณ ๊ฐ๋ช…: sfinvoice.customers) \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];
        let thisAmount = 0;
        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;
 
    func amountFor(pert, play) {
        let thisAmount = 0;
        switch (play.type) {
            case "tragedy": // ๋น„๊ทน
                thisAmount = 40000;
                if (perf.audience > 30) {
                    thisAmount += 1000 * (perf.audience - 30);
                }
                break;
            case "comedy": // ํฌ๊ทน
                thisAmount = 30000;
                if (perf.audience > 20) {
                    thisAmount += 10000 + 500 * (perf.audience - 20);
                }
                thisAmount += 300 * perf.audience;
                break;
            default:
                throw new Error('์•Œ ์ˆ˜ ์—†๋Š” ์žฅ๋ฅด: sfplay.typer');
        }
        return thisAmount;
    }
}
 
 
  • ์ด๋ ‡๊ฒŒ ๋ฆฌํŒฉํ† ๋ง ํ–ˆ๋‹ค๋ฉด, ๋ฐ”๋กœ ์ปดํŒŒ์ผ ํ•œ๋‹ค.
  • ์กฐ๊ธˆ์”ฉ ์ˆ˜์ •ํ•˜์—ฌ ํ”ผ๋“œ๋ฐฑ ์ฃผ๊ธฐ๋ฅผ ์งง๊ฒŒ ๊ฐ€์ ธ๊ฐ€๋Š” ์Šต๊ด€์ด ์‹ค์ˆ˜ํ•˜๋Š” ์žฌ์•™์„ ํ”ผํ•˜๋Š” ๊ธธ์ด๋‹ค.

๋ฆฌํŒฉํ† ๋ง์€ ํ”„๋กœ๊ทธ๋žจ ์ˆ˜์ •์„ ์ž‘์€ ๋‹จ๊ณ„๋กœ ๋‚˜๋ˆ  ์ง„ํ–‰ํ•œ๋‹ค.

  • ์ด๋ ‡๊ฒŒ ์ˆ˜์ •ํ–ˆ๋‹ค๋ฉด, ๋ฐ”๋กœ ๋กœ์ปฌ ๋ฒ„์ „ ๊ด€๋ฆฌ ์‹œ์Šคํ…œ์— ์ปค๋ฐ‹ํ•œ๋‹ค.
  • ํ•˜๋‚˜์˜ ๋ฆฌํŒฉํ„ฐ๋ง์„ ๋ฌธ์ œ ์—†์ด ๋๋‚ผ ๋•Œ๋งˆ๋‹ค ์ปค๋ฐ‹ํ•œ๋‹ค. ๊ทธ๋ž˜์•ผ ์ด์ „ ์ƒํƒœ๋กœ ๋นจ๋ฆฌ ๋˜๋Œ๋ฆด ์ˆ˜ ์žˆ๋‹ค.
  • ์ผ๋‹จ ์˜ฎ๊ฒจ์„œ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ์œผ๋‹ˆ (์ด๋ถ€๋ถ„์ด ์ค‘์š”..), ๋‚ด๋ถ€ ํ•จ์ˆ˜์˜ ํ‘œํ˜„์„ ๋ณ€๊ฒฝํ•ด๋ณด์ž.
  • thisAmount โ†’ result
func amountFor(pert, play) {
    let result = 0;
    switch (play.type) {
        case "tragedy": // ๋น„๊ทน
            result = 40000;
            if (perf.audience > 30) {
                result += 1000 * (perf.audience - 30);
            }
            break;
        case "comedy": // ํฌ๊ทน
            result = 30000;
            if (perf.audience > 20) {
                result += 10000 + 500 * (perf.audience - 20);
            }
            result += 300 * perf.audience;
            break;
        default:
            throw new Error('์•Œ ์ˆ˜ ์—†๋Š” ์žฅ๋ฅด: sfplay.typer');
    }
    return result;
}
  • ๋‹ค์Œ์œผ๋กœ๋Š” aPerf๊ฐ€ ์• ๋งคํ•˜๋‹ˆ ์ด๊ฑธ aPerformance๋กœ ๋ฐ”๊พธ์ž.
func amountFor(aPerformance, play) {
    let result = 0;
    switch (play.type) {
        case "tragedy": // ๋น„๊ทน
            result = 40000;
            if (aPerformance.audience > 30) {
                result += 1000 * (aPerformance.audience - 30);
            }
            break;
        case "comedy": // ํฌ๊ทน
            result = 30000;
            if (aPerformance.audience > 20) {
                result += 10000 + 500 * (aPerformance.audience - 20);
            }
            result += 300 * aPerformance.audience;
            break;
        default:
            throw new Error('์•Œ ์ˆ˜ ์—†๋Š” ์žฅ๋ฅด: sfplay.typer');
    }
    return result;
}
  • ๋ถ€์ •๊ด€์‚ฌ๋ฅผ ๋ถ™์ด๋ฉด ์ข‹๋‹ค๊ณ  ํ•œ๋‹ค.
  • ๊ทธ๋Ÿฐ๋ฐ ์ด ๋ถ€๋ถ„์€ ์–ธ์–ด์˜ ์ฝ”๋“œ ์ปจ๋ฒค์…˜์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์งˆ ๋“ฏ ํ•˜๋‹ค.

์‚ฌ๋žŒ์ด ์ดํ•ดํ•˜๋„๋ก ์ž‘์„ฑํ•˜๋Š” ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์ง„์ •ํ•œ ์‹ค๋ ฅ์ž๋‹ค.

Reference