리팩토링 8장에서 가장 와닿았던 부분이 이 반복문 쪼개기다. 반복문 안에서 여러가지 일을 처리해버리면 좋다고 생각하는데, 사실 이는 좋지 않다.
반복문 쪼개기는 서로 다른 일들이 한 함수에서 이뤄지고 있다는 뜻이기도 하다. 그래서 반복문 쪼개기와 함수 추출하기는 연이어 수행하는 일이 잦다.
반복문을 각각의 반복문으로 분리해두면 수정할 동작 하나만 고려하면 된다.
// Before
let average = 0;
let totalSalary = 0;
for (const p of people) {
average += p.average;
totalSalary += p.salary;
}
averageAge = averageAge / people.length;
// After
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;
거의 뭐 보자마자 이해가 되는 리팩토링 기법이다. 내가 그동안 써왔던 코드들을 뒤돌아보게 만든다. 사실 반복문을 쪼개게 되면 당연히 수정과 보수가 용이하게 되는게 당연한데 생각을 못했던 것 같다.
예시: 전체 급여와 가장 어린 나이를 계산하는 코드
let youngest = people[0] ? people[0].age : Infinity;
let totalSalary = 0;
for (const p of people) {
if (p.age < youngest) youngest = p.age; // 가장 어린 사람을 찾는 코드
totalSalary += p.salary; // 총 급여를 구하는 코드
}
return `최연소: ${youngest}, 총 급여 : ${totalSalary}`;
최연소인 사람을 구하는 코드와 총 급여를 구하는 코드 이 반복문이 두개가 쓰여있다. 리팩토링 기법은 간단하다.
단계 1. 그냥 복제한다.
let youngest = people[0] ? people[0].age : Infinity;
let totalSalary = 0;
for (const p of people) {
if (p.age < youngest) youngest = p.age;
totalSalary += p.salary;
}
for (const p of people) { // 그냥 단순히 복사
if (p.age < youngest) youngest = p.age;
totalSalary += p.salary;
}
return `최연소: ${youngest}, 총 급여 : ${totalSalary}`;
단계2. 중복을 제거한다.
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 `최연소: ${youngest}, 총 급여 : ${totalSalary}`;
이렇게까지 하면 일단 1차로 리팩토링한 것인데 뭔가 좀 아쉽다.
추가로 가다듬기: 반복문을 함수로 추출
return `최연소: ${youngestAge()}, 총 급여 : ${totalSalary()}`;
function totalSalary() {
let totalSalary = 0;
for (const p of people) {
totalSalary += p.salary;
}
return totalSalary;
}
function youngestAge() {
let youngest = people[0] ? people[0].age : Infinity;
for (const p of people) {
if (p.age < youngest) youngest = p.age;
}
return youngest;
}
위처럼 반복문을 함수로 추출해주면 중복도 제거가능하고 재사용도 쉽다.
추가로 가다듬기 : 반복문을 파이프라인으로 바꾸고 , 최연소 계산 코드에는 알고리즘을 변경한다.
function totalSalary() {
return people.reduce((total, p) => total + p.salary, 0);
}
function youngestAge() {
return Math.min(...people.map((p) => p.age));
}
위처럼 깔끔하게 가다듬고 나니 확연히 좋아졌다.