본 글은 리팩터링 2판을 읽으며 생객했던 과정을 기록한 것입니다.
const format = new Intl.NumberForamt(...).format;
위 format 임시 변수에 담김 함수를 아래 처럼 함수화 했다.
function format (aNumber) {
return new Intl.NumberForamt(...).format(aNumber);
}
여기서 드는 의문은 이렇게 바꾸는 것이 어떤 개선 효과가 있는가? 이다.
이 코드가 필자가 말한 이유로 리팩터링 하기에는 적절한 예제라고 생각이 들지 않았다. 하지만 나름의 이유를 유추해 보자면
let volumeCredits = 0;
for (let perf of invoice.performances) {
...
totalAmount += amountFor(perf);
volumeCredits += volumeCreditsFor(perf);
}
result += `적립 포인트: ${volumeCredits}점₩n`;
function volumeCreditsFor(perf) {
let volumeCredits = 0;
volumeCredits += Math.max(perf.audience - 30, 0);
if ("comedy" === playFor(perf).type)
volumeCredits += Math.floor(perf.audience / 5);
return volumeCredits;
}
위 코드를 보면 어떤 생각이 드는가? for 반복문 내에서 volumeCredits 변수는 함수를 호출하여 값을 누적하고 있다. 함수가 추출되었기 때문에 기능적으로도 분리가 잘 돼있는 듯 하다.
하지만 여기서 더 응집도를 높일 수 있다. 바로 volumeCredits를 반복문에서 분리하여 새로운 반복문을 만들고 이 코드를 함수화 시키는 것이다.
// 제거 let volumeCredits = 0;
for (let perf of invoice.performances) {
...
totalAmount += amountFor(perf);
// 제거 volumeCredits += volumeCreditsFor(perf);
}
result += `적립 포인트: ${totalVolumeCredits()}점₩n`;
------------------------------------------------------
function totalVolumeCredits() {
let volumeCredits = 0;
for (let perf of invoice.performances) {
volumeCredits += volumeCreditsFor(perf);
}
}
function volumeCreditsFor(perf) {
let volumeCredits = 0;
volumeCredits += Math.max(perf.audience - 30, 0);
if ("comedy" === playFor(perf).type)
volumeCredits += Math.floor(perf.audience / 5);
return volumeCredits;
}
어떠한가? 반복문이 쪼개졌기 때문에 성능이 정말 미미하게 저하됐을 수는 있으나, 응집도가 높아졌고 때문에 추후 유지보수하기는 더 용이할 것으로 판단된다. 필자는 혹여나 성능에 영향을 미치더라도 리팩터링을 진행한다고 한다. 이유는 잘 다듬어진 코드가 성능 개선 작업에도 훨씬 수월하기 때문이다. 너무 멋있는 말이지 않은가? 이 과정에서 다시 이전 코드로 돌아갈 수 도 있지만 대체적으로는 추후 성능 개선에 들어가고 성공하여 깔끔한 코드와 더 빠른 프로젝트로 마무리 된다.
위 4단계를 요약하면 응집도를 높이고 응집된 코드를 함수화시켜 임시 변수 volumeCredits를 제거하는 동시에 인라인으로 호출한 것이다.
우선 리팩터링으로 인한 성능 문제에 처할지라도, 우선 리팩터링을 마무리해보자. 그리고 나서 성능을 다시 개선키셔 보자.