
하나의 값이 여러 목적으로 사용된다면 변수를 쪼개 용도별로 분리하도록 한다.
📜 절차
다음은 일반적인 물리 법칙을 이용해 전파 거리를 계산한 코드다.
const distanceTravelled = (scenario, time) => {
let result;
let acc = scenario.primaryForce / scenario.mass; // 가속도(a) = 힘(F) / 질량(m)
let primaryTime = Math.min(time, scenario.delay);
result = 0.5 * acc * primaryTime * primaryTime; // 전파된 거리
let secondaryTime = time - scenario.delay;
if (secondaryTime > 0) {
// 두 번째 힘을 반영해 다시 계산
let primaryVelocity = acc * scenario.delay;
acc = (scenario.primaryForce + scenario.secondaryForce) / scenario.mass;
result +=
primaryVelocity * secondaryTime +
0.5 * acc * secondaryTime * secondaryTime;
}
return result;
};
acc 변수에 두 번 대입되는 것을 볼 수 있는데 첫 번째는 힘이 유발한 초기 가속도를 저장하는 역할이고, 다른 하나는 두 번째 힘까지 반영된 후의 가속도를 저장하는 역할이다. 이 변수를 쪼개보자.
첫 번째 용도로는 primaryAcceleration 으로 변수 이름을 바꾼다. 또한 값을 다시 대입하지 못하도록 const로 선언한다. 그리고 두 번째 용도로 사용할 acc 변수를 다시 선언한다.
const distanceTravelled = (scenario, time) => {
let result;
let primaryAcceleration = scenario.primaryForce / scenario.mass; // 이름 수정
let primaryTime = Math.min(time, scenario.delay);
result = 0.5 * primaryAcceleration * primaryTime * primaryTime; // 변수 대입
let secondaryTime = time - scenario.delay;
if (secondaryTime > 0) {
let primaryVelocity = primaryAcceleration * scenario.delay; // 변수 대입
let acc = (scenario.primaryForce + scenario.secondaryForce) / scenario.mass; // 다시 선언
result +=
primaryVelocity * secondaryTime +
0.5 * acc * secondaryTime * secondaryTime;
}
return result;
};
다음으로 두 번째 용도에 적합한 이름으로 수정해 acc 변수를 제거한다.
const distanceTravelled = (scenario, time) => {
let result;
let primaryAcceleration = scenario.primaryForce / scenario.mass;
let primaryTime = Math.min(time, scenario.delay);
result = 0.5 * primaryAcceleration * primaryTime * primaryTime;
let secondaryTime = time - scenario.delay;
if (secondaryTime > 0) {
let primaryVelocity = primaryAcceleration * scenario.delay;
const secondaryAcceleration = (scenario.primaryForce + scenario.secondaryForce) / scenario.mass; // 이름 수정, const로 변경
result +=
primaryVelocity * secondaryTime +
0.5 * secondaryAcceleration * secondaryTime * secondaryTime; // 변수 대입
}
return result;
};
📚 입력 매개변수의 값을 수정할 때
다음의 코드를 보자.
const discount = (inputValue, quantity) => {
if (inputValue > 50) {
inputValue = inputValue - 2;
}
if (quantity > 100) {
inputValue = inputValue - 1;
}
return inputValue;
};
inputValue는 함수에 데이터를 전달하는 용도와 결과를 호출자에 반환하는 용도로 쓰였다. inputValue 변수를 쪼개보자.
첫 번째 if문에서 inputValue와 비교하도록 수정한다. 입력 값에 기초해, 결과값을 누적해 계산한다는 사실을 명확히 드러내도록 한다.
const discount = (inputValue, quantity) => {
let result = inputValue; // result 선언 및 inputValue 대입
if (inputValue > 50) { // inputValue와 비교
result = result - 2;
}
if (quantity > 100) {
result = result - 1;
}
return result;
};

이름은 프로그램을 이해하는 데 큰 역할을 한다.
📜 절차

가변 데이터의 유효 범위는 가능한 한 좁혀야 한다.
📜 절차
변수 쪼개기를 활용해 각 갱신 지점에서 변수를 분리한다.죽은 코드 제거하기로 없앤다.다음의 코드를 보자.
class ProductionPlan {
get production() {
return this._production;
}
applyAdjustment(anAdjustment) {
this._adjustments.push(anAdjustment);
this._production += anAdjustment.amount;
}
}
adjustment 값을 적용하는 과정에서, 관련없는 production 값까지 갱신했다. 이 클래스에서 발생한 데이터 중복을 제거해보자.
production 값을 계산하는 함수를 만든다.
class ProductionPlan {
// ...
get calculatedProduction() {
return this._adjustments.reduce((sum, a) => sum + a.amount, 0);
}
}
그런 다음 calculatedProduction 함수를 인라인하고, 옛 변수를 참조하는 모든 코드를 정리한다.
class ProductionPlan {
get production() {
return this._adjustments.reduce((sum, a) => sum + a.amount, 0);
}
applyAdjustment(anAdjustment) {
this._adjustments.push(anAdjustment);
}
}

객체를 다른 객체에 중첩하면 내부 객체를 참조 혹은 값으로 취급할 수 있는데,
값으로 다루는 경우에는 새로운 속성을 담은 객체로 기존 내부 객체를 통째로 대체한다.
이런 값 객체는 불변이기 때문에, 다른 곳에서 값을 변경하지 않을까 걱정할 필요가 없다.
📜 절차

데이터의 일관성이 필요한 경우에는 값을 참조로 바꾸도록 한다.

의미를 알기 어려운 리터럴이 보이면 명확하게 바꿔주도록 한다.
매직 리터럴(magic literal)이란 의미를 알 수 없는 리터럴 값을 말한다. aValue === 'M' 이라는 코드가 있을 때, M이 매직 리터럴이다.
매직 리터럴 바꾸기 기법을 이용하면 다음과 같이 리팩터링할 수 있다.
aValue === MALE_GENDERisMale(aValue)