All Articles

반복문 쪼개기

리팩토링 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));
}

위처럼 깔끔하게 가다듬고 나니 확연히 좋아졌다.