[ Programming > Refactoring ]
[๋ฆฌํฉํฐ๋ง] ๊ธฐ๋ฅ ์ด๋
[๋ฆฌํฉํฐ๋ง] ๊ธฐ๋ฅ ์ด๋
์ง๊ธ ๊น์ง๋ ํ๋ก๊ทธ๋จ ์์๋ฅผ ์์ฑ ํน์ ์ ๊ฑฐํ๊ฑฐ๋ ์ด๋ฆ์ ๋ณ๊ฒฝํ๋ ๋ฆฌํฉํฐ๋ง์ ํ๋ค. ๊ทธ๋ฆฌ๊ณ ๋ฆฌํฉํฐ๋ง ์ ์๋ ์ฌ๊ธฐ์ ๋ํด ์์๋ฅผ ๋ค๋ฅธ ์ปจํ ์คํธ (ํด๋์ค ๋๋ ๋ชจ๋)๋ก ์ฎ๊ธฐ๋ ์ผ๋ ์ค์ํ ์ถ์ด๋ผ ํ๋ค. ๊ทธ๋์ "๊ธฐ๋ฅ ์ด๋" ๊ธ์์๋ ํจ์ ์ฎ๊ธฐ๊ธฐ, ํ๋ ์ฎ๊ธฐ๊ธฐ์ ๊ฐ์ ๋ฆฌํฉํฐ๋ง ๋ฐฉ๋ฒ์ ์๊ฐํ๋ ค๊ณ ํ๋ค.
1. ๊ธฐ๋ฅ ์ด๋ ๋ฆฌํฉํฐ๋ง ๋ฐฉ๋ฒ
1.1 ํจ์ ์ฎ๊ธฐ๊ธฐ
์ํํธ์จ์ด ํต์ฌ์ ์ค๊ณ๋ ๋ชจ๋์ฑ์ด๋ค. ๋ชจ๋์ฑ์ ํ๋ก๊ทธ๋จ์ ์์ ํ ๋ ํด๋น ๊ธฐ๋ฅ์ ์์ ์ผ๋ถ๋ง ์ดํดํด๋ ๊ฐ๋ฅํ๊ฒ ํด์ฃผ๋ ๋ฅ๋ ฅ์ด๋ค.
๋ฆฌํฉํฐ๋ง ์ ์์ ๋ฐ๋ฅด๋ฉด ๋ชจ๋์ฑ์ ๋์ด๋ ๋ฐฉ๋ฒ์ "์๋ก ์ฐ๊ด๋ ์์๋ค์ ํจ๊ป ๋ฌถ๊ณ , ์์ ์ฌ์ด์ ์ฐ๊ฒฐ ๊ด๊ณ๋ฅผ ์ก๊ธฐ ์ฐพ๊ณ ์ดํดํ ์ ์๋๋ก ๋ง๋ค๊ธฐ"์ด๋ค. ๊ทธ๋ฆฌ๊ณ ํ๋ก๊ทธ๋จ์ ์ผ๋ง๋ ์ดํดํ๋๋์ ๋ฐ๋ผ์ ๋ชจ๋์ฑ์ ๋ ์ ๋์ผ ๊ฐ๋ฅ์ฑ์ด ์ฆ๊ฐํ๋ฉฐ ์์๋ค์ ์ด๋ฆฌ ์ ๋ฆฌ ์ฎ๊ฒจ์ผํ ์ ๋ ์๋ค.
ํจ์ ์ฎ๊ธฐ๋ Case
์ด๋ค ํจ์๊ฐ ์ํ ๋ชจ๋ A์ ์์๋ค๋ณด๋ค ๋ชจ๋ B์ ์์๋ค์ ๋ ๋ง์ด ์ฐธ์กฐํ๋ค๋ฉด, ์ด ํจ์๋ฅผ ๋ชจ๋ B๋ก ์ฎ๊ธฐ๋ฉด ์ด ์ํํธ์จ์ด๋ ๋ชจ๋ B์ ์ธ๋ถ์ฌํญ์ ๋ ์์กดํ๊ฒ ๋๋ค. (์บก์ํ๊ฐ ๊ฐ์ ๋๋ค.)
๋์ฐ๋ฏธ ์ญํ ๋ก ์ ์๋ ํจ์ ์ค ๋ ๋ฆฝ์ ์ผ๋ก ๊ณ ์ ํ ๊ฐ์น๊ฐ ์๋ ๊ฒ์ ์ ๊ทผํ๊ธฐ ๋ ์ฌ์ด ์ฅ์๋ก ์ฎ๊ธด๋ค. (๋๋ ๋ค์ ์ ๋ฐ์ดํธ ๋ ๋ฐ๋๋ฆฌ๋ผ ์์๋๋ ์์น์ ๋ฐ๋ผ์ ์ฎ๊ธด๋ค.)
์ฌ์ค ํจ์๋ฅผ ์ฎ๊ธธ์ง ๋ง์ง๋ฅผ ์ ํ๊ธฐ๋ ์ฝ์ง ์๋ค. ์ ์์ ๋ฐ๋ฅด๋ฉด ๊ทธ๋ด ๋ ๋์ ํจ์์ ํ์ฌ ์ปจํ
์คํธ์ ํ๋ณด ์ปจํ
์คํธ๋ฅผ ๋๋ฌ๋ณด๋ฉด ๋์์ด ๋๋ค. ๊ทธ๋ฆฌ๊ณ ํจ์ ์ด๋ ๋ฟ๋ง์ด ์๋๋ผ ์ฐ๊ด๋ ํจ์๋ค์ ํด๋์ค ๋ฌถ๊ธฐ๋ ํด๋์ค ์ถ์ถํ๊ธฐ๋ก ํด๊ฒฐํ๊ธฐ๋ ํ๋ค.
๊ทธ๋ฆฌ๊ณ ํจ์์ ์ต์ ์ ์ฅ์๋ฅผ ์ฐพ๊ธฐ ์ด๋ ค์ด ๊ฒฝ์ฐ์๋ ํ ์ปจํ
์คํธ์ ๋๊ณ ์์
ํด๋ณด๋ ๊ฒ๋ ์ข๋ค. ๊ทธ๋ฌ๋ฉด ์ผ๋ง๋ ์ ํฉํ์ง ์ ์ ๊นจ๋ฌ์ ๊ฐ๊ณ , ๊ทธ ํ๋จ์ ๋ฐ๋ผ ์ธ์ ๋ ์ฎ๊ธธ ์ ์๋ค. ๊ทธ๋ฆฌ๊ณ ์ด์ ๊ทธ ์์๋ฅผ ์ฝ๋๋ฅผ ํตํด ์๋ณด๋๋ก ํ๊ฒ ๋ค.
// ์ค์ฒฉ ํจ์๋ฅผ ์ต์์๋ก ์ฎ๊ธฐ๊ธฐ// Before: calculateDistance ํจ์๊ฐ trackSummary ํจ์ ๋ด๋ถ์ ์ค์ฒฉ์ผ๋ก ์ ์ธ๋์ด ์๋ค.// ๋ชฉํ: calculateDistance ํจ์๋ฅผ ์ต์์๋ก ์ฎ๊ฒจ ์ถ์ ๊ฑฐ๋ฆฌ๋ฅผ ๋ค๋ฅธ ์ ๋ณด์ ๋
๋ฆฝ์ ์ผ๋ก ๊ณ์ฐํ๊ณ ์ถ๋ค.function trackSummary(points) { const totalTime = calculateTime(); const totalDistance = calculateDistance(); const pace = totalTime / 60 / totalDistance; return { time: totalTime, distance: totalDistance, pace: pace } function calculateDistance() { let result = 0; for (const i = 1; i < points.length; i++) { result += distance(points[i-1], points[i]); } return result; } function distance(p1, p2) { ... } function radians(degrees) { ... } function calculateTime() { ... } }// ๋ชฉํ ๋ฌ์ฑ ํfunction trackSummary(points) { const totalTime = calculateTime(); const pace = totalTime / 60 / totalDistance(points); return { time: totalTime, distance: totalDistance(points), pace: pace };}function totalDistance(points) { ... } // totalDistance๋ด๋ถ์ distance์ radians๋ฅผ ์ค์ฒฉ ํจ์๋ก ์ ์ธํ ์๋ ์๋ค.function distance(p1, p2) { ... }function radians(degrees) { ... }function calculateTime() { ... }
์ ์ฝ๋๋ฅผ ๋ณด๋ฉด ์ค์ฒฉํจ์๋ค์ ์ต์์๋ก ๋์ด์ฌ๋ ค ์ถ์ ๊ฑฐ๋ฆฌ์ ๋ํ ๊ณ์ฐ์ trackSummay ์ปจํ ์คํธ์ ๋ ๋ฆฝ์ ์ผ๋ก ๋ถ๋ฆฌํ๋ค. ๊ทธ๋ฆฌ๊ณ totalDistance ํจ์์์ distance์ radians ํจ์๊ฐ ์ฌ์ฉ๋๋๋ฐ, ๊ฐ์์ฑ์ ์ค์ด๊ธฐ ์ํด totalDistance ๋ด๋ถ์ ์ค์ฒฉ ํจ์๋ก ์ ์ธํ๋ ๊ฒ๋ ๊ณ ๋ คํ ์ ์๋ค. ํ์ง๋ง ์ ์๋ ์ค์ฒฉ ํจ์๋ฅผ ์ฌ์ฉํ๋ค ๋ณด๋ฉด ์จ๊ฒจ์ง ๋ฐ์ดํฐ๋ผ๋ฆฌ ์ํธ ์์กดํ๊ธฐ๊ฐ ์ฌ์ฐ๋ ๋๋๋ก ์ฌ์ฉํ์ง ๋ง์๊ณ ์ฃผ์ฅํ๋ค.(๊ทธ๋ฆฌ๊ณ ์ธ์ด์ ๋ฐ๋ผ ์ค์ฒฉ ํจ์ ์ ์ธ์ ๋ํ ํ๊ณ๊ฐ ์์ด์, ์ธ์ด์ ๋ฐ๋ผ ๋ฐฉ๋ฒ์ด ๋ฌ๋ผ์ง ์ ์๋ค.)
์ด๋ฒ์๋ ์ต์์ ์ปจํ ์คํธ๋ก ํจ์๋ฅผ ๋นผ๋ ๊ฒ์ด ์๋ ๋ค๋ฅธ ํด๋์ค๋ก ์ฎ๊ธฐ๋ ์์์ด๋ค.
// ๋ค๋ฅธ ํด๋์ค๋ก ์ฎ๊ธฐ๊ธฐ ์์// Before : Account์ ๊ณ์ข ์ข
๋ฅ์ ๋ฐ๋ผ ์ด์ ์ฑ
์ ์๊ณ ๋ฆฌ์ฆ์ด ๋ฌ๋ผ์ง๋ ํจ์๊ฐ ์กด์ฌํ๋ค.// ๋ชฉํ : ์ด์ ์ฑ
์ ์ฑ
์์ ๋ณ๋๋ก ๋ถ๋ฆฌํด๋ณด์.class Account { get bankCharge() { let result = 4.5; if (this._daysOverdrawn > 0) result += this.overdraftCharge; return result; } get overdraftCharge() { if(this.type.isPremium) { const baseCharge = 10; if(this.daysOverdrawn <= 7) { return baseCharge; } else { return baseCharge + (this.daysOverdrawn - 7) * 0.85; } } else { return this.daysOverdrawn * 1.75; } }}// After : AccountType ํด๋์ค๋ก ์ด๋class Account { get bankCharge() { let result = 4.5; if (this._daysOverdrawn > 0) result += this.type.overdraftCharge(this.daysOverdrawn); return result; } // ์์ ๋ฉ์๋๋ก ๋ง๋ค๊ฑฐ๋ฉด get overdraftCharge ๋ฉ์๋๋ฅผ ๋๋ค.}class AccountType { overdraftCharge(daysOverdrawn) { // daysOverdrawn์ ๊ณ์ข๋ณ๋ก ๋ฌ๋ผ์ง๋ ๋ฉ์๋์ด๊ธฐ ๋๋ฌธ์ ๊ทธ๋๋ก ๋๋ค. // ์ฌ์ฉํ๋ ์ปจํ
์คํธ๊ฐ ๋ง์ผ๋ฉด daysOverdrawn์ด ์๋๋ผ account๋ฅผ ํต์งธ๋ก ์ฌ์ฉํ๋ค. if(this.isPremium) { const baseCharge = 10; if(daysOverdrawn <= 7) { return baseCharge; } else { return baseCharge + (daysOverdrawn - 7) * 0.85; } } else { return daysOverdrawn * 1.75; } }}
1.2 ํ๋ ์ฎ๊ธฐ๊ธฐ
ํ๋ก๊ทธ๋จ์ ์ง๋ค๋ณด๋ฉด ์ฃผ์ด์ง ๋ฌธ์ ์ ์ ํฉํ์ง ์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ํ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๊ธฐ ์ํ ์ฝ๋๋ก ๋ฒ๋ฒ ์ด ๋๋ ๊ฒฝํ์ ํด๋ณธ์ ์์ ๊ฒ์ด๋ค. ๊ทธ๋์ ์ดํดํ๊ธฐ ์ด๋ ค์ด ์ฝ๋๊ฐ ๋ง๋ค์ด์ง๊ณ ์ด๋ค ์ผ์ ํ๋์ง ํ์ ํ๋๋ฐ ๋ฐฉํด๊ฐ ๋๋ค.
๊ทธ๋์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๊ฐ ์ค์ํ๊ณ ๋ง์ ์ ํฉํ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค์ด ๋ด๊ณ ์ ํ ๋ ์ด๋ ต๋ค. ์ ํฉํ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค๊ธฐ ์ํด์๋ ๊ฒฝํ๊ณผ ๋๋ฉ์ธ ์ฃผ๋ ์ค๊ณ๊ฐ์ ๊ธฐ์ ์ด ํ์ํ๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ๋ฐ ๊ธฐ์ ์ ๊ฐ์ก๋ค๊ณ ํด๋ ์๋ จ์๋ค๋ ํ๋ก์ ํธ๋ฅผ ์งํํ ์๋ก ๋ฌธ์ ๋๋ฉ์ธ๊ณผ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ๋ํด ๋ ๋ง์ด ๋ฐฐ์ฐ๊ณ ์๋ชป๋ ๊ฒ์ผ๋ก ํ๋ช ํ๊ณ ์์ ํ๊ธฐ๋ ํ๋ค๊ณ ํ๋ค.
ํ๋ ์ฎ๊ธฐ๋ Case
ํจ์์ ์ด๋ค ๋ ์ฝ๋๋ฅผ ๋๊ธธ ๋๋ง๋ค ๋ค๋ฅธ ๋ ์ฝ๋์ ํ๋๋ ํจ๊ป ๋๊ธฐ๊ณ ์๋ ๊ฒฝ์ฐ
์ด๋ค ๋ ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ ๋ ๋ค๋ฅธ ๋ ์ฝ๋์ ํ๋๊น์ง ๋ณ๊ฒฝํด์ผํ๋ ๊ฒฝ์ฐ
ํ๋ ์ฎ๊ธฐ๊ธฐ ๋ฆฌํฉํฐ๋ง์ ๋ณดํต ๋ ํฐ ๋ณ๊ฒฝ์ ์ผํ์ผ๋ก ์ํ๋๋ค. ํ๋์ ํ๋๊ฐ ์ฎ๊ฒจ์ง๋ฉด ๊ทธ ํ๋๋ฅผ ์ฌ์ฉํ๋ ๋ง์ ์ฝ๋๊ฐ ์ฎ๊ฒจ์ง ์์น์์ ์ฌ์ฉํ๋๊ฒ ๋ ์์ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ํ์ง๋ง ์ฎ๊ธฐ๋ ค๋ ๋ฐ์ดํฐ๊ฐ ์ฐ์ด๋ ํจํด ๋๋ฌธ์ ๋น์ฅ ํ๋๋ฅผ ์ฎ๊ธธ ์ ์๋ ๊ฒฝ์ฐ๊ฐ ์๋ค. ๊ทธ๋ด ๋ ์ฌ์ฉ ํจํด์ ๋จผ์ ๋ฆฌํฉํฐ๋งํ๊ณ ํ๋๋ฅผ ์ฎ๊ฒจ์ผํ๋ค.
์๋๊ฐ ๊ทธ ์ ์ฉ ์์๋ค.
// Before : Customer ํด๋์ค์ discountRate์ด ์กด์ฌ.// ๋ชฉํ : ํ ์ธ์จ์ ๋ปํ๋ discountRate ํ๋๋ฅผ Customer -> CustomerContract๋ก ์ฎ๊ธฐ๊ธฐclass Customer { constructor(name, discountRate) { this._name = name; this._discountRate = discountRate; this._contract = new CustomerContract(dateToday()); } get discountRate() { return this._discountRate; } becomePreferred() { this._discountRate += 0.03; // + ๋ค๋ฅธ ์ผ๋ค } applyDiscount(amount) { return amount.subtract(amount.multiply(this._discountRate)); } dateToday() { return new Date(); }}class CustomerContract { // ๊ณ์ฝ ํด๋์ค constructor(startDate) { this._startDate = startDate; }}// After : discountRateํ๋๋ฅผ CustomerContract๋ก ์ด๋์ํจ๋ค.class Customer { constructor(name, discountRate) { this._name = name; this._contract = new CustomerContract(this.dateToday()); this._setDiscountRate(discountRate); // contract ํด๋์ค ํธ์ถ ๋ค ์คํ } get discountRate() { return this._contract.discountRate; } setDiscountRate(number) { return this._contract.discountRate = number; } becomePreferred() { this._contract.discountRate += 0.03; // ๋ฑ๋ฑ } applyDiscount(amount) { return amount.subtract(amount.multiply(this._contract.discountRate)); } dateToday() { return new Date(); }}class CustomerContract { constructor(startDate, discountRate) { this._startDate = startDate; this._discountRate = discountRate; } get discountRate() { return this._discountRate; } _setDiscountRate(aNumber) { // ์ ๊ทผ ์ ์ด ์บก์, ํ์
์คํฌ๋ฆฝํธ๋ฉด ๊ตณ์ด aNumber๋ก?? this._discountRate = aNumber; }}
ํ๋๋ฅผ ์ฎ๊ธฐ๋๋ฐ ๊ทธ ํน์ฑ์ ๋ฐ๋ผ์ ์ ๊ทผ ์ ์ด์๋ฅผ ์์ ํ๋ ๋ฑ ๋ ์ฝ๋ ํน์ฑ์ ๋ง๊ฒ ์บก์ํ๋ฅผ ์ ์ ํ ํด์ผํ๋ค.
๋ค์์ ๊ณต์ ๊ฐ์ฒด๋ก ์ด๋์ํค๋ ์์์ด๋ค. ์ฝ๋๋ณด๋ค๋ ๋ฆฌํฉํฐ๋ง์์ ์ ๊ฒฝ์จ์ผํ ์ ์ด ๋ฌด์์ธ์ง ์์๊ฐ๋ ๊ฒ์ด ์ข์ ๊ฒ ๊ฐ๋ค.
// Before : Account์ ์ด์๊ฐ Account์ ๋ฐ๋ผ ๋ค๋ฅด๋ค// ๋ชฉํ : AccountType์ ๋ฐ๋ผ ์ด์๊ฐ ๋ค๋ฅด๊ฒ ๋ณ๊ฒฝํ์ผ๋ฉฐ DB๊น์ง ์ผ์นํ๋์ง ํ์ธํ๊ธฐ.class Account { constructor(number, type, interestRate) { this._number = number; this._type = type; this._interestRate = interestRate; } get interestRate() {return this._interestRate;}}class AccountType { constructor(name) { this._name = name; }}// After : AccountType์ ๋ฐ๋ผ ์ด์๊ฐ ๊ฒฐ์ ๋๋ฉฐ, ๊ฒ๋ณด๊ธฐ ๋์๋ ์ผ์นํ๋์ง ํ์ธํ๋ฉฐ ๋ง๋ค์ด์ผ ํจ.class Account { constructor(number, type, interestRate) { this._number = number; this._type = type; } get interestRate() {return this._type.interestRate;}}class AccountType { constructor(name, interestRate) { this._name = name; this._interestRate = interestRate; } get interestRate() {return this._interestRate;}}
์ ์ฝ๋๋ DB์ ๋น์ฐํ ๊ฐ ๊ณ์ข๊ฐ ๊ณ์ข ์ข ๋ฅ์๋ฐ๋ผ ๊ฐ์ ์ด์์จ์ ๊ณต์ ํ๋ค๊ณ ๊ฐ์ ํ๊ณ ๋ง๋ ์ฝ๋์ด๋ค. ํ์ง๋ง ์ด์ ์๋ ๊ณ์ข ๋ณ๋ก ์ด์์จ์ด ๋ฌ๋ผ์ก๋๋ฐ ์๋กญ๊ฒ ๊ณ์ข ์ข ๋ฅ๋ณ๋ก ์ด์์จ์ด ๊ฐ๊ฒ ์ค์ ํ๋ค๋ฉด ์์ ์ ๊ณผ ํ์ ๊ฒ๋ณด๊ธฐ ๋์์ด ๊ฐ์์ง ํ์ธํด์ผํ๋ค. ๊ทธ๋์ ์๋์ ๊ฐ์ ์ค๊ฐ ์ฝ๋๋ฅผ ์ง๋๊ฒ ๋์์ด ๋ ์ ์๋ค.
class Account { constructor(number, type, interestRate) { this._number = number; this._type = type; assert(interestRate === this._type.interestRate); // ์ด์, ํ
์คํธ ์ค์ ์ค๋ฅ ํ์ธํ์ฌ ๊ฒ๋ณด๊ธฐ ๋์ ์ผ์น ์ฌ๋ถ ํ์ธ this._interestRate = interestRate; } get interestRate() {return this._interestRate;}}
1.3 ๋ฌธ์ฅ์ ํจ์๋ก ์ฎ๊ธฐ๊ธฐ
์ค๋ณต ์ ๊ฑฐ๋ ์ฝ๋๋ฅผ ๊ฑด๊ฐํ๊ฒ ๊ด๋ฆฌํ๋ ํจ๊ณผ์ ์ธ ๋ฐฉ๋ฒ์ด๋ค. ํน์ ํจ์๋ฅผ ํธ์ถํ๋ ์ฝ๋๊ฐ ๋์ฌ ๋๋ง๋ค ๊ทธ ์์ด๋ ๋ค์์ ๋๊ฐ์ ์ฝ๋๊ฐ ์ถ๊ฐ๋ก ์คํ๋๋ ๊ฒฝ์ฐ ๊ทธ ๋ฐ๋ณต๋๋ ๋ถ๋ถ์ ํผํธ์ถ ํจ์๋ก ํฉ์น๋ ๊ฒ์ด ์ข๋ค. ๊ทธ๋ฌ๋ฉด ๋์ค์ ์์ ํ ์ผ์ด ์๊ฒผ์ ๋ ํ ๊ณณ๋ง ์์ ํ๋ฉด ๋๋ค. ๋ฌผ๋ก ๋ฐ๋๋ก ์ฝ๋์ ๋์์ ์ฌ๋ฌ ๋ณํ๋ค๋ก ๋๋ ์ผ ํ๋ ์๊ฐ์ด ์ค๋ฉด ๋ฌธ์ฅ์ ํธ์ถํ ๊ณณ์ผ๋ก ์ฎ๊ธฐ๋ฉด ๋๋ค.
๋ฌธ์ฅ๋ค์ ํจ์๋ก ์ฎ๊ธฐ๋ ค๋ฉด ๊ทธ ๋ฌธ์ฅ๋ค์ด ํผํธ์ถ ํจ์์ ์ผ๋ถ๋ผ๋ ํ์ ์ด ์์ด์ผ ํ๋ค.
๋ฌธ์ฅ์ ํจ์๋ก ์ฎ๊ธฐ๋ Case
ํผํธ์ถ ํจ์์ ํ ๋ชธ์ ์๋์ง๋ง ์ฌ์ ํ ํจ๊ป ํธ์ถ๋ผ์ผ ํ๋ ๊ฒฝ์ฐ ํด๋น ๋ฌธ์ฅ๊ณผ ํผํธ์ถ ํจ์๋ฅผ ํต์งธ๋ก ๋ํ๋์ ํจ์๋ก ์ถ์ถ
์๋๋ ๊ทธ ์์๋ก ์ฌ์ง ๊ด๋ จ ๋ฐ์ดํฐ๋ฅผ HTML๋ก ๋ด๋ณด๋ด๋ ์ฝ๋๋ค.
// Before : "์ ๋ชฉ"์ ์ฌ์ง ์ ๋ณด์ ์ผ๋ถ์ด๋ฉฐ emitPhotoData์ ํญ์ ํจ๊ป ํธ์ถ๋๋ค. // ๋ชฉํ : ์ ๋ชฉ์ ์ถ๋ ฅํ๋ ์ฝ๋๋ฅผ emitPhotoData๋ก ์ฎ๊ฒจ ์ค๋ณต์ ์ ๊ฑฐํ๋ค.function renderPerson(person) { const result = []; result.push(`<p>${person.name}</p>`); result.push(renderPhoto(person.photo)); result.push(`<p>์ ๋ชฉ: ${person.photo.title}</p>`); result.push(emitPhotoData(person.photo)); return result.join("\n");}function photoDiv(aPhoto) { return [ '<div>', `<p>์ ๋ชฉ: ${p.title}</p>`, emitPhotoData(aPhoto), '</div>'].join("\n");}function emitPhotoData(aPhoto) { const result = []; result.push(`<p>์์น: ${aPhoto.location}</p>`); result.push(`<p>๋ ์ง: ${aPhoto.date.toDateString()}</p>`); return result.join("\n");}// After : emitPhotoData์์ ์ ๋ชฉ์ ํจ๊ป ์ถ๋ ฅํ๊ฒ ๋ณ๊ฒฝfunction renderPerson(person) { const result = []; result.push(`<p>${person.name}</p>`); result.push(renderPhoto(person.photo)); result.push(emitPhotoData(person.photo)); return result.join("\n");}function photoDiv(aPhoto) { return [ '<div>', emitPhotoData(aPhoto), '</div>'].join("\n");}function emitPhotoData(aPhoto) { return [ `<p>์ ๋ชฉ: ${aPhoto.title}</p>` `<p>์์น: ${aPhoto.location}</p>` `<p>๋ ์ง: ${aPhoto.date.toDateString()}</p>` ].join("\n");}
1.4 ๋ฌธ์ฅ์ ํธ์ถํ ๊ณณ์ผ๋ก ์ฎ๊ธฐ๊ธฐ
ํจ์๋ ํ๋ก๊ทธ๋๋จธ๊ฐ ์์ ์ฌ๋ฆฌ๋ ์ถ์ํ์ ๊ธฐ๋ณธ ๋น๋ฉ ๋ธ๋ก์ด๋ค. ๊ทธ๋ฐ๋ฐ ์ถ์ํ๋ผ๋ ๊ฒ์ ๊ทธ ๊ฒฝ๊ณ๋ฅผ ํญ์ ์ฌ๋ฐ๋ฅด๊ฒ ๊ธ๊ธฐ๋ ํ๋ค๋ค. ๊ทธ๋์ ์ฝ๋ ๋ฒ ์ด์ค์ ๊ธฐ๋ฅ ๋ฒ์๊ฐ ๋ฌ๋ผ์ง๋ฉด ์ถ์ํ์ ๊ฒฝ๊ณ๋ ์์ง์ธ๋ค. ์ด๊ธฐ์๋ ์์ง๋ ๋๊ณ ๋จ์ผ ์ฑ ์์ ๊ฐ์ง ํจ์๊ฐ ์ด๋์ ๋ ์ด์์ ์ฑ ์์ ์ํํ๊ฒ ๋ฐ๋ ์๋ ์๋ค.
๋ฌธ์ฅ์ ํธ์ถํ ๊ณณ์ผ๋ก ์ฎ๊ธฐ๋ Case
์ฌ๋ฌ ๊ณณ์์ ์ฌ์ฉ ํ๋ ๊ธฐ๋ฅ์ด ์ผ๋ถ ํธ์ถ์๋ค์๊ฒ๋ ๋ค๋ฅด๊ฒ ๋์ํด์ผํ๋ ๊ฒฝ์ฐ
๊ทธ๋ฐ๋ฐ ์ ๋ณ๊ฒฝ์ด ์์ ๋ณ๊ฒฝ์ด๋ผ๋ฉด ๊ทธ๋ฅ ๋ฌธ์ฅ์ ํธ์ถํ ๊ณณ์ผ๋ก ์ฎ๊ธฐ๋ฉด ๋์ด์ง๋ง, ํธ์ถ์์ ํธ์ถ ๋์์ ๊ฒฝ๊ณ๋ฅผ ์์ ํ ๋ค์ ๊ทธ์ด์ผ ํ๋ ๊ฒฝ์ฐ๋ ์๊ธธ ์ ์๋ค. ๊ทธ๋ฌ๋ฉด ํจ์๋ฅผ ๋ค์ ์ธ๋ผ์ธ์ผ๋ก ๋ง๋ค๊ณ ์ ํฉํ ๊ฒฝ๊ณ๋ฅผ ๊ทธ์ด์ผ ํ๋ค.
์๋ ๊ทธ ์์๋ก ์์น ์ ๋ณด๋ฅผ ๋ค๋ฅด๊ฒ ๋ ๋๋ง ํ๋๋ก ๋ง๋ค์ด์ผํ๋ ๊ฒฝ์ฐ์ด๋ค.
// Before : photo์ location์ด ํญ์ ๊ฐ๊ฒ ๋ ๋๋ง ๋๋ค.// ๋ชฉํ : listRecentPhotos()๊ฐ ์์น ์ ๋ณด(location)์ ๋ค๋ฅด๊ฒ ๋ ๋๋งํด์ผ ํ๋ค.function renderPerson(outStream, person) { outStream.write(`<p>${person.name}</p>\n`); renderPhoto(outStream, person.photo); emitPhotoData(outStream, person.photo);}function listRecentPhotos(outStream, photos) { photos .filter((p) => p.date > recentDateCutoff()) .forEach((p) => { outStream.write('<div>\n'); emitPhotoData(outStream, p); outStream.write('</div>\n'); });}function emitPhotoData(outStream, photo) { outStream.write(`<p>์ ๋ชฉ: ${photo.title}</p>\n`); outStream.write(`<p>๋ ์ง: ${photo.date.toDateString()}</p>\n`); outStream.write(`<p>์์น: ${photo.location}</p>\n`);}// After : function renderPerson(outStream, person) { outStream.write(`<p>${person.name}</p>\n`); renderPhoto(outStream, person.photo); emitPhotoData(outStream, person.photo); outStream.write(`<p>์์น: ${person.photo.location}</p>\n`) // ์์น๊ฐ ๋ณ๋๋ก ๋น ์ง}function listRecentPhotos(outStream, photos) { photos .filter((p) => p.date > recentDateCutoff()) .forEach((p) => { outStream.write('<div>\n'); emitPhotoData(outStream, p); outStream.write(`<p>์์น: ${p.location}</p>\n`); // ์์น๊ฐ ๋ณ๋๋ก ๋น ์ง outStream.write('</div>\n'); });}function emitPhotoData(outStream, photo) { outStream.write(`<p>์ ๋ชฉ: ${photo.title}</p>\n`); outStream.write(`<p>๋ ์ง: ${photo.date.toDateString()}</p>\n`);}
์ ์์๋ ํผํธ์ถ์๊ฐ ๊ฐ๋จํ๊ณ ํธ์ถ์๊ฐ 2๊ฐ ๋ฟ์ธ ์ํฉ์ด๋ค. ํ์ง๋ง ๋ง์ฝ ํธ์ถ์๊ฐ ๋๊ฒ ๋ง๊ณ ํผํธ์ถ์๊ฐ ๋ณต์กํ๋ฉด ๋จ๊ณ ๋ณ๋ก "์๋ก์ด ํผํธ์ถ์์ ๋จ๊ธธ ์ฝ๋ ์ถ์ถํ๊ธฐ" - "๊ธฐ์กด ํผํธ์ถ ํจ์ ์ฝ๋ ํธ์ถ์์ ์ธ๋ผ์ธ ํ๊ธฐ"์ ๊ฐ์ด ๋จ๊ณ์ ์ผ๋ก ๋ฆฌํฉํฐ๋ง ํ๋ ๊ฒ์ด ๋์์ด ๋ ๊ฒ์ด๋ผ ์๊ฐํ๋ค.
1.5 ์ธ๋ผ์ธ ์ฝ๋๋ฅผ ํจ์ ํธ์ถ๋ก ๋ฐ๊พธ๊ธฐ
์ด ๋ฆฌํฉํฐ๋ง ๋ฐฉ์์ด ํจ์ ์ถ์ถํ๊ธฐ์ ๋ค๋ฅธ์ ์ ์ธ๋ผ์ธ ์ฝ๋๋ฅผ ๋์ฒดํ ํจ์๊ฐ ์ด๋ฏธ ์๋๋ ์๋๋์ด๋ค. ์ด ๋ฐฉ์์ ์ธ๋ผ์ธ ์ฝ๋๋ฅผ ๋์ฒดํ ํจ์๊ฐ ์์๊ฒฝ์ฐ ์ ์ฉํ๋ ์์๋ค. ๋ง์ฝ ์๋ค๋ฉด ํจ์ ์ถ์ถํ๊ธฐ๋ฅผ ํตํด ์๋ก์ด ํจ์๋ฅผ ๋ง๋ค๊ณ ํจ์๋ฅผ ๋์ฒดํ ๊ฒ์ด๋ค. ์์๋ฅผ ๋ณด๋ฉด ๋ ํ์คํ ๋ฌด์จ๋ง์ ํ๋์ง ์ ๊ฒ ๊ฐ๋ค.
// ๋ฆฌํฉํฐ๋ง ์ let appliesToMass = false;for(const s of states) { if (s === "MA") appliesToMass = true;}// ๋ฆฌํฉํฐ๋ง ํconst appliesToMass = states.includes("MA");
ํฉ๋นํ ์๋ ์์ง๋ง ๊ตณ์ด ๋งํ๊ณ ์ถ์ ์ ์ ์ฌ์ฉ์ค์ธ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ API๋ฅผ ์ ํ์ ํ๊ณ ์๋ค๋ฉด ์ฝ๋๋ฅผ ๊ฐ์ ํ๋๋ฐ ๋ ์์ํ๋ค๋ ๊ฒ์ ์๋ ค์ฃผ๊ณ ์ถ๋ค.
1.6 ๋ฌธ์ฅ ์ฌ๋ผ์ด๋ํ๊ธฐ (์กฐ๊ฑด๋ฌธ ๊ณตํต ์คํ์ฝ๋ ๋ด๋นผ๊ธฐ)
๊ด๋ จ๋ ์ฝ๋๋ค์ด ๊ฐ๊น์ด ๋ชจ์ฌ ์๋ค๋ฉด ์ดํดํ๊ธฐ๊ฐ ๋ ์ฝ๋ค. ์๋ฅผ ๋ค๋ฉด ํ๋์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ๋ ๋ฌธ์ฅ๋ค์ ๋ค๋ฅธ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ ๋ฌธ์ฅ ์ฌ์ด์ ํฉ์ด์ ธ ์๊ธฐ ๋ณด๋ค๋ ํ๋ฐ ๋ชจ์ฌ์๋๊ฒ ์ข๋ค. ๋ฌธ์ฅ ์ฌ๋ผ์ด๋ํ๊ธฐ ๋ฆฌํฉํฐ๋ง์ด ์ด๋ฐ ์ฝ๋๋ค์ ํ๋ฐ ๋ชจ์๋๋ค.
๋ฌธ์ฅ ์ฌ๋ผ์ด๋ํ๊ธฐ๋ฅผ ๊ฐ๋จํ ๋งํ๋ฉด ์ฝ๋ ์์น๋ฅผ ์ ๋ฆฌํ์ฌ ๋ฆฌํฉํฐ๋ง ํ๊ฒ ํธํ๊ณ ์ดํดํ๊ธฐ ๋ ์ฝ๊ฒ ๋ง๋๋ ๊ฒ์ด๋ค.
๋ฌผ๋ก ๋ชจ๋ ๋ณ์ ์ ์ธ์ ํจ์ ์ฒซ๋จธ๋ฆฌ์ ๋ชจ์๋๋ ์ฌ๋๋ ์์ง๋ง, ๋ฆฌํฉํฐ๋ง ์ ์๋ ๋ณ์๋ฅผ ์ฒ์ ์ฌ์ฉํ ๋ ์ ์ธํ๋ ์คํ์ผ์ ์ ํธํ๋ค.
๋ฌธ์ฅ ์ค๋ผ์ด๋ ์ฃผ์์
์ฝ๋ ์กฐ๊ฐ์์ ์ฐธ์กฐํ๋ ์์๋ฅผ ์ ์ธํ๋ ๋ฌธ์ฅ ์์ผ๋ก๋ ์ด๋์ด ๋ถ๊ฐํ๋ค.
์ฝ๋ ์กฐ๊ฐ์ ์ฐธ์กฐํ๋ ์์์ ๋ค๋ก๋ ์ด๋ํ ์ ์๋ค.
์ฝ๋ ์กฐ๊ฐ์์ ์ฐธ์กฐํ๋ ์์๋ฅผ ์์ ํ๋ ๋ฌธ์ฅ์ ๊ฑด๋๋ฐ์ด ์ด๋ํ ์ ์๋ค.
์ฝ๋ ์กฐ๊ฐ์ด ์์ ํ๋ ์์๋ฅผ ์ฐธ์กฐํ๋ ์์๋ฅผ ๊ฑด๋๋์ด ์ด๋ํ ์ ์๋ค.
๊ทธ๋ฆฌ๊ณ ์ฝ๋ ์กฐ๊ฐ์ ์ฌ๋ผ์ด๋ํ ๋๋ ๋ ๊ฐ์ง๋ฅผ ํ์ธํด์ผํ๋ค. "๋ฌด์์ ์ฌ๋ผ์ด๋"ํ ๊ฒ์ธ๊ฐ์ "์ฌ๋ผ์ด๋ ๊ฐ๋ฅ"ํ์ง ์ฌ๋ถ์ด๋ค. "๋ฌด์์"์ ๋งฅ๋ฝ๊ณผ ๊ด๋ จ์ด ๊น์ผ๋ฉฐ, ์ฌ๋ผ์ด๋ ๊ฐ๋ฅ ์ฌ๋ถ๋ ์ฝ๋ ์กฐ๊ฐ ์์์ ๋ฐ๋ผ ๋์์ด ๋ฌ๋ผ์ง๋ ์ง๋ฅผ ํ์ธํด์ผ ํ๋ค. ๋ค์์ ์์์ด๋ค.
// Before : ์ฝ๋๊ฐ ๊ด์ฌ์ฌ์ ์๊ด์์ด ๋ฐฐ์น๋ ๊ฒฝ์ฐ๋ค์ด ์์. ์ค๊ฐ์ ์ด๋ค ๊ณผ์ ์ด ์ถ๊ฐ๋๋ฉด ์ถ์ ํ๊ธฐ๋ ํ๋ค๊ฒ์ด๋ค.// ๋ชฉํ : ์ฝ๋๋ฅผ ๋น์ทํ ๊ด์ฌ์ฌ๋ผ๋ฆฌ ๋ฌถ์ด๋ณด์const pricingPlan = retrievePricingPlan();const order = retreiveOrder();const baseCharge = pricingPlan.base;let charge;const chargePerUnit = pricingPlan.unit;const units = order.units;let discount;charge = baseCharge + units * chargePerUnit;let discountableUnits = Math.max(units - pricingPlan.discountThreshold, 0);discount = discountableUnits * pricingPlan.discountFactor;if(order.isRepeat) discount += 20;charge = charge - discount;chargeOrder(charge);// 9๋ฒ ์ค๊น์ง๋ ์ ์ธ๋ฌธ์ผ๋ก ๋ณด์ธ๋ค. ๊ทธ๋ค์ ์ค๋ถํฐ๋ ์๊ธ ๊ณ์ฐ์ด ์์๋๋ค. 12๋ฒ ์ค์ ๋ discount๋ฅผ ๊ณ์ฐํ๋ค.// ์์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ํ๋ฒ ์ฌ๋ผ์ด์ฑ ํด๋ณด์. ๋จ ์์น ๋ณ๊ฒฝ์ด ๊ฐ๋ฅํ์ง ๋ฐ๋์ ํ์ธํ๋ฉด์ ํด์ผํ๋ค.// After : ๊ด์ฌ์ฌ ๋ผ๋ฆฌ ๋ฌถ์ด๋ณด์const pricingPlan = retrievePricingPlan();const order = retreiveOrder(); // ์ฃผ๋ฌธconst units = order.units; // ์ฃผ๋ฌธ ๋จ์ ์let discountableUnits = Math.max(units - pricingPlan.discountThreshold, 0); // ํ ์ธ ๊ฐ๋ฅ ๊ฐ์let discount; // ํ ์ธ๊ฐdiscount = discountableUnits * pricingPlan.discountFactor; // ํ ์ธ๊ฐ ๊ณ์ฐif(order.isRepeat) discount += 20; // ํ ์ธ๊ฐ ๊ณ์ฐ2const baseCharge = pricingPlan.base; // ์๊ธ ๊ธฐ๋ณธconst chargePerUnit = pricingPlan.unit; // ์๊ธ ๋จ์let charge; // ์๊ธcharge = baseCharge + units * chargePerUnit; // ์๊ธ ๊ณ์ฐ1charge = charge - discount;// ์๊ธ ๊ณ์ฐ2chargeOrder(charge);// ์ฃผ๋ฌธ ์๊ธ ๋ถ๊ณผ
์์์ ์ฃผ๋ฌธ, ํ ์ธ, ์๊ธ ์ด๋ ๊ฒ 3๊ฐ์ง๋ก ๋๋ ์ ์ฌ๋ผ์ด์ฑํ๋ค. ์ ๋ ๊ฒ ๋ณด๋ ๊ทธ ๋ค์ ๋ฌด์์ ์ด๋ป๊ฒ ๋ฆฌํฉํฐ๋งํด์ผํ ์ง ๋ ๋ช ํํด์ง๋ค.(ํ์คํ ์ ๋ณด์ธ๋ค) ์ด์ ํฉ์น ๊ฑฐ ํฉ์น๊ณ ์ถ์ถํ ๊ฑฐ ์ถ์ถํ๋ฉด ํจ์ฌ ๊น๋ํ ์ฝ๋๊ฐ ๋์ฌ ๊ฒ์ด๋ค. ๊ทธ๋ฆฌ๊ณ ๋ง์ฝ ์ฌ๋ผ์ด์ฑ์ด ๊ฐ๋ฅํ์ง ๋ ๋น ๋ฅด๊ฒ ํ๋จํ๊ธฐ ์ํด์๋ "๋ช ๋ น-์ง์ ๋ถ๋ฆฌ ์์น(Command-Query Separation)"์ ์ง์ผ์ ์ฝ๋๋ฅผ ์ง๋ฉด ์ข๋ค.
๋ค์์ ์กฐ๊ฑด๋ฌธ์ด ์์ ๊ฒฝ์ฐ ์ฌ๋ผ์ด์ฑ ์์์ด๋ค. ์กฐ๊ฑด๋ฌธ์ ์๋ฐ์ผ๋ก ์ฌ๋ผ์ด๋ํด์ผํ ๊ฒฝ์ฐ๊ฐ ์๋๋ฐ, ๋ฐ์ผ๋ก ์ฌ๋ผ์ด๋ํ๋ฉด ์ค๋ณต ๋ก์ง์ด ์ ๊ฑฐ๋ ๊ฒ์ด๊ณ , ์กฐ๊ฑด๋ฌธ ์์ผ๋ก ์ฌ๋ผ์ด๋ํ ๋๋ ๋ฐ๋๋ก ์ค๋ณต ๋ก์ง์ด ์ถ๊ฐ๋ ๊ฒ์ด๋ค.
// Before : allocatedResources.push๊ฐ ์กฐ๊ฑด๋ฌธ ๋ง๋ค ์ค๋ณต๋๋ค.// ๋ชฉํ : ๋ฐ์ผ๋ก ์ฌ๋ผ์ด์ฑ ํ์ฌ ์ค๋ณต์ ์ ๊ฑฐํด๋ณด์.let result;if (availableResources.length ===0) { result = createResource(); allocatedResources.push(result);} else { result = availableResources.pop(); allocatedResources.push(result);}return result;// After : ์กฐ๊ฑด๋ฌธ๋ง๋ค allocatedResouces.push๊ฐ ์ฌ์ ํ ์คํ๋์ง๋ง, ์ค๋ณต์ด ์ ๊ฑฐ๋์๋ค.let result;if (availableResources.length ===0) { result = createResource();} else { result = availableResources.pop();}allocatedResources.push(result);return result;
1.7 ๋ฐ๋ณต๋ฌธ ์ชผ๊ฐ๊ธฐ
์ข ์ข ๋ฐ๋ณต๋ฌธ ํ๋์์ ๋ ๊ฐ์ง ์ผ์ ์ํํ๋ ๊ฒฝ์ฐ๊ฐ ์๋ค. ํ์ง๋ง ์ด๋ ๊ฒ ํ๋ฉด ๋ฐ๋ณต๋ฌธ์ ์์ ํด์ผ ํ ๋๋ง๋ค ๋ ๊ฐ์ง ์ผ ๋ชจ๋ ์ ์ดํดํ๊ณ ์งํํด์ผ ํ๋ค. ๋ฐ๋๋ก ๊ฐ๊ฐ์ ๋ฐ๋ณต๋ฌธ์ผ๋ก ๋ถ๋ฆฌํด๋๋ฉด ์์ ํ ๋์ ํ๋๋ง ์ดํดํ๋ฉด ๋๋ค. ์ด๊ฑด ์ฐ์ ์์๋ฅผ ๋ณด์ฌ์ฃผ๊ณ ๊ทธ ๋ค์ ์๋ฌธ์ ๋ํด์ ๋งํด๋ณด๊ณ ์ ํ๋ค.
// Before : ํ๋์ ๋ฐ๋ณต๋ฌธ์ 2๊ฐ์ง ์ผ์ ํ๋ค.// ๋ชฉํ : ๋ฐ๋ณต๋ฌธ์ ์ชผ ๊ฐ์ ํ ๊ฐ์ ๋ฐ๋ณต๋ฌธ์ด ํ๋์ ์ฑ
์์ ์ํํ๊ฒ ํด๋ณด์.let averageAge = 0;let totalSalary = 0;for (const p of people) { averageAge += p.age; totalSalary += p.salary;}averageAge = averageAge / people.length;// After : ํ๋์ ๋ฐ๋ณต๋ฌธ์ 1๊ฐ์ง ์ผ์ ์ฒ๋ฆฌํ๋ค.let totalSalary = 0;for (const p of people) { totalSalary += p.salary;}let averageAge = 0;for (const p of people) { averageAge += p.age;}averageAge = averageAge / people.length;
์ ์ฝ๋๋ฅผ ๋ณด๋ฉด ๊ด์ฌ์ฌ ๋ณ๋ก ์ฝ๋ ์กฐ๊ฐ์ด ์กด์ฌํ๋ ๊ฒ์ ๋ณผ ์ ์๋ค. ๊ทธ๋ฌ๋ฉด ์ด ๋ฆฌํฉํฐ๋ง์ ๋งค์ฐ ๋ถํธํดํ๋ ์ฌ๋์ด ๋ง์ ๊ฒ ๊ฐ๋ค. ์๋ํ๋ฉด ๋ฐ๋ณต๋ฌธ์ 2๋ฒ ์คํํ์ฌ ๋ณ๋ชฉ ํ์์ ์ ๋ฐํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค(์ด ๊ธ์ ์ฐ๋ ์ ๋ ์ด๊ฑด ์ซ...). ์ ์๋ ๋ฆฌํฉํฐ๋ง๊ณผ ์ต์ ํ๋ฅผ ๊ตฌ๋ถํ๋ผ๊ณ ํ๋ค. ์๋ํ๋ฉด ์ต์ ํ๋ ์ฝ๋๋ฅผ ๊น๋ํ ์ ๋ฆฌํ ํ์ ์ ์ฉํ๋ ๊ฒ์ด๋ผ ํ๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๋ฆฌ๊ณ ๊น๋ํ๊ฒ ์ ๋ฆฌ๋ ํ์๋ ์ต์ ํ๋ก ๋ for๋ฌธ์ ํฉ์น๋ ๊ฒ์ ์์ ์ฃฝ ๋จน๊ธฐ๋ผ๊ณ ํ๋ค. ๊ทธ๋ฆฌ๊ณ ๋ณ๋ชฉ ํ์์ผ๋ก ์ด์ด์ง๋ ๊ฒฝ์ฐ๊ฐ ๋๋ฌผ๊ธฐ ๋๋ฌธ์ ์คํ๋ ค ๋ฐ๋ณต๋ฌธ ์ชผ๊ฐ๊ธฐ๊ฐ ๋ค๋ฅธ ๋ ๊ฐ๋ ฅํ ์ต์ ํ๋ฅผ ์ ์ฉํ ์ ์๋ ๊ธธ์ ์ด์ด์ฃผ๊ธฐ๋ ํ๋ค๊ณ ํ๋ค.
๋ฌผ๋ก ๋๋ ์ ์ ์๊ฒฌ์ ๋์ํ์ง๋ง, ๊ฐ๋จํ for๋ฌธ ์ฝ๋๋ผ๋ฉด ๊ตณ์ด ์ ์ฉํ ํ์๊ฐ ์์๊น ๋ผ๋ ์๊ฐ์ด ๋ ๋ค. ๊ทธ๋ฆฌ๊ณ ์ ๋ฐ ์ฝ๋๊ฐ 1๊ฐ์ผ ๋๋ ๋ณ๋ชฉ์ด ์๊ฒ ์ง๋ง "์ด๊ณณ ์ ๊ณณ์์ for๋ฌธ์ด ๋ชจ๋ ๋ถ๋ฆฌ๋์ด ์กด์ฌํ๋ค๋ฉด ๊ทธ ๋์ ์น๊ฐ ๋ณ๋ชฉ์ผ๋ก ์์ฉํ์ง ์์๊น?"๋ผ๋ ์๊ฐ๋ ๋ ๋ค.
๋ฌผ๋ก ์๋ ์์๋ฅผ ๋ณด๋ฉด ๊ฐ๋ ์ฑ์ด ์๋นํ ์ข๋ค๋ ์ฅ์ ์ ๋ณผ ์ ์๊ธฐ๋ ํ๋ค.
// Before : ๋ฐ๋ณต๋ฌธ ์ชผ๊ฐ๊ธฐ ์ ์ฉ ์ let youngest = people[0] ? people[0].age : Infinity;let totalSalary = 0;for (const p of people) { totalSalary += p.salary;}for (const p of people) { if (p.age < youngest) youngest = p.age;}return `youngestAge: ${youngest}, totalSalary: ${totalSalary}`;// After : ๋ฐ๋ณต๋ฌธ ์ชผ๊ฐ๊ธฐ์ youngestAge์ totalSalary ํจ์๋ก ์ถ์ถํ๊ธฐ ๊น์ง ์ ์ฉ.return `youngestAge: ${youngestAge()}, totalSalary: ${totalSalary()}`;function totalSalary() { return people.reduce((total, p) => total + p.salary, 0);}function youngestAge() { return Math.min(...people.map(p => p.age));}
1.8 ๋ฐ๋ณต๋ฌธ์ ํ์ดํ๋ผ์ธ์ผ๋ก ๋ฐ๊พธ๊ธฐ
๊ฐ์ฒด ์ปฌ๋ ์ ์ ์ํํ ๋ ๋ฐ๋ณต๋ฌธ์ ๋ง์ด ์ฌ์ฉํ ๊ฒ์ด๋ค. ๊ทธ๋ฐ๋ฐ ์ธ์ด๊ฐ ๋ฐ์ ํ๋ฉด์ ์ด๋ฌํ ์ฒ๋ฆฌ ๊ณผ์ ์ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ผ๋ก ์ผ๋ จ์ ์ฐ์ฐ ๊ณผ์ ์ผ๋ก ํํํ ์ ์๋ค. ๋์ด์ ์ธ ์ปฌ๋ ์ ํจ์๊ฐ map๊ณผ filter๊ฐ ์๋ค. ๋ ผ๋ฆฌ๋ฅผ ํ์ดํ๋ผ์ธ์ผ๋ก ํํํ๋ค๊ณ ์ดํดํ๋ฉด ํจ์ฌ ์ฌ์์ง๋ค.
์์๋ฅผ ๋ณด๋ฉด ๋๋ถ๋ถ ๋ฌด์จ ๋ง์ธ์ง ์์ค ๊ฒ ๊ฐ๋ค.
// Before : ๋จ์ for๋ฌธ ์ฌ์ฉ// ๋ชฉํ : ์ปฌ๋ ์
ํ์ดํ๋ผ์ธ์ ์ด์ฉํ์ฌ ๋
ผ๋ฆฌ์ ํ๋ฆ ํ์
์ ์ฝ๊ฒ ๋ง๋ค์ด ๋ณด์.function acquireData(input) { const lines = input.split('\n'); let firstLine = true; const result = []; for (const line of lines) { // line ๋ณ ์ํ if (firstLine) { firstLine = false; // 1๋ฒ์งธ line์ด๋ฉด ๋ฒ๋ฆฌ๊ธฐ continue; } if (line.trim() === '') continue; // trimํ ๊ฒฝ์ฐ ๋น ๋ผ์ธ์ด๋ฉด ๋ฒ๋ฆฌ๊ธฐ const record = line.split(','); // ,์ ๊ตฌ๋ถ์๋ก ๋ ์ฝ๋ ๋ถ๋ฆฌ if (record[1].trim() === 'India') { // India์ธ ๋ ์ฝ๋๋ฉด ๊ฒฐ๊ณผ์ ์ ์ฅ result.push({ city: record[0].trim(), phone: record[2].trim() }); // ์ ์ฅ๋ ๋ ์ฝ๋์ ๋์์ ์ ํ๋ฒํธ๋ง ์ ์ฅ } } return result;}// After : ๋ด์ฅ Array ํจ์ ์ฌ์ฉfunction acquireData(input) { const lines = input.split('\n'); return lines .slice (1) // 1๋ฒ์งธ ๋ผ์ธ ๋ฒ๋ฆฌ๊ธฐ .filter (line => line.trim() != '') // line์ ํธ๋ฆผํ ๊ฒฝ์ฐ ๋น๋ผ์ธ์ด๋ฉด ๋ฒ๋ฆฌ๊ธฐ .map (line => line.split(',')) // ,์ ๊ตฌ๋ถ์๋ก ๋ ์ฝ๋ ๋ถ๋ฆฌ .filter (fields => fields[1].trim() === 'India') // ๋ ์ฝ๋๊ฐ India๊บผ๋ฉด ์ ์ฅ .map (fields => ({city: fields[0].trim(), phone: fields[2].trim()})); // ์ ์ฅ๋ ๋ ์ฝ๋์ ๋์์ ์ ํ๋ฒํธ๋ง ์ ์ฅ}
์์ ๊ฐ์ด ํ์ดํ๋ผ์ด๋ํ์ฌ ๋ฌด์จ ๋ ผ๋ฆฌ๋ก ์ปฌ๋ ์ ์ ๊ฐ๊ณตํ๋์ง ํ๋์ ๋ณผ ์ ์๋ค.
๋ง๋ฌด๋ฆฌ
์ด๋ฒ ์ฅ์์๋ ์ฝ๋๋ ๊ธฐ๋ฅ์ ์์น ๋ณ๊ฒฝ์ ๋ํด์ ์ด์ผ๊ธฐ ํ๋ค. ๋ค ์์๋ค์ ๋ณด๋ฉด ์์ํ ๊ฑฐ๋ผ ์๊ฐํ๋ค. ๊ทธ๋ฆฌ๊ณ ๋ฌด์์ ์ค์ ํ๊ณ ์๋ ๋ฆฌํฉํฐ๋ง ๋ฐฉ๋ฒ๋ ๋ง์ ๊ฑฐ๋ผ๊ณ ์๊ฐํ๋ค. ํ์ง๋ง ๋ฆฌํฉํฐ๋ง ์ฑ ์์๋ ๋ฆฌํฉํฐ๋ง ๋ฐฉ๋ฒ์ ์ ์ฐจ์ ๋ฐ๋ผ ํ๋์ฉ ์ค๋ช ํด์ค๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ ์ค๋ช ์์ ๊ฐ ๋จ๊ณ์์ ๋ฌด์์ ๊ณ ๋ คํด์ผํ ์ง ์ค๋ช ์ด ํจ๊ป ์๋ค. ๊ทธ๋์ ๊ทธ ๊ณ ๋ คํด์ผํ ์ ๋ค์ ํ๋ฒ ์ฏค ๋ณด๊ณ ๋๊ผ์ผ๋ฉด ๋์ค์ ๋ฆฌํฉํฐ๋งํ ๋ ๋ ๋์์ด ๋ ๊ฒ์ด๋ผ๋ ๋ง์ฐํ ์๊ฐ์ ํ๋ค.