JavaScript - 임시 변수를 제거하자
어떤 값을 조작한 뒤 그 값을 반환하는 함수를 작성해야 할 때 값을 변경하기 위해 함수 내부에 임시 변수를 생성하는 방법이 있다. 임시 변수에 변경해야 할 값을 할당하고, 요구사항에 맞춰 변경한 뒤 해당 변수를 반환하는 것이다. 이러한 방법은 변경에 취약하고, 가독성이 떨어지며, 함수가 비대해져 역할이 불분명해질 수 있으므로 되도록 피해야 한다.
요약
임시 변수를 제거하자
이유
- 명령형 코드가 되기 쉽다.
- 변경 사항이 생기면 추가적인 코드를 작성하게 되기 쉽다. 즉 코드가 변경되기 쉽다.
해결책
- 역할이 분명한 여러 함수로 나누고 이들의 구성을 활용할 것
- 반환 값을 바로 반환할 것
- 고차함수를 사용할 것
- 명령형이 아닌 선언형 코드를 작성할 것
변경에 열려 있는 함수는 믿고 사용할 수 없다.
function getMonth(targetDate) {
let month = targetDate.getMonth();
month = month > 10 ? month : '0' + month;
return month;
}
위 코드는 정상적으로 동작하겠지만, 변경에 열려있는 코드가 된다. 변경에 열려있다는 말은 언뜻 들으면 긍정적인 것 같지만, 바꿔말하면 언제든지 바뀔 가능성이 있다는 불안정성을 의미한다(개방-폐쇄 원칙). 만약 요구사항이 변경된다면, 개발자는 함수의 내부를 변경하려고 할 것이다. 개발자가 목표한 요구사항은 해결할 수 있겠지만, 만약 해당 함수를 사용하는 다른 코드가 있다면, 그 코드에서 문제가 발생할 수 있다. 왜냐하면 다른 코드에서 해당 함수를 사용할 때는 항상 같은 동작과, 반환 값을 반환할 것이라는 가정을 하고 작성한 것이기 때문이다. 따라서 변경이 가능한 임시변수를 사용하기보다는 상수인 const
를 활용하거나 아예 변수 자체를 생략하는 것도 좋은 방법이다. 그리고 변경이 필요할 때는 기존 함수를 활용하는 추가 함수를 만들어 기존 함수의 변경을 최소화하는 것이다. 예를 들면 아래와 같이 수정할 수 있다.
function getMonth(targetDate) {
const month = targetDate.getMonth(); // 상수를 사용
return month > 10 ? month : '0' + month; // 변수 생성 없이 바로 반환
}
function getMonthKR(targetDate) { // 기존 함수를 활용하는 추가 함수를 작성
const month = getMonth(targetDate);
return month + '월'
}
명령형 코드가 되기 쉽다.
임시 변수를 사용하면 이후 코드는 이 변수를 직접 변경하는 방향으로 나아가게 된다. 이러한 코드는 절차 위주의 명령형 코드가 되기 쉽다.
function foo(array) {
let temp = 0;
for (let i = 0; i < array.length; i++) {
if (temp === someCondition1) {
temp += 56756;
} else {
temp *= 23423;
}
}
if (temp === someCondition2) {
temp += 9876;
} else {
temp *= 5432;
}
return temp;
}
위와 같은 명령형 코드는 가독성이 떨어진다는 단점이 있다. 코드가 어떤 작업을 실행하는지를 단번에 알기 어렵고, 이해하기 위해서는 많은 코드를 순서대로 따라가며 읽어보아야 한다. 하지만 차분하게 읽어간다고 하더라도, 반복문, 조건문 등 식이 복잡해지면 마지막 결괏값을 예상하기 매우 힘들다. 이를 해결하기 위해서는 map()
, reduce()
등과 같은 고차함수를 이용하는 방법이 있다.