함수 리팩터링 158p ~ 172p
코드를 언제 함수로 묶어야 할지에 대해서는 의견이 수없이 많다.
1. 길이를 기준으로 묶는다.
2. 두 번 이상 사용될 코드는 함수로 만든다.
가장 합리적인 판단은 '목적과 구현을 분리'하는 방식이 가장 합리적인 기준이다.
만약 어떤 코드를 보고 무슨 일을 하는지 파악하는데 한참이 걸린다면 함수로 추출한 뒤 '무슨 일'에 걸맞는 이름을 짓는게 효율적이다.
그럼 다음에 코드를 다시 읽을 때 함수의 목적이 눈에 들어오고, 본문코드에 대해서는 신경쓰지 않아도 된다.
경험상 대여섯 줄을 넘어가면 함수로 만드는게 좋다고 생각된다.
혹 어떤이는 함수를 짧게 만들면 함수 호출이 많아져서 성능이 느려질까 걱정하는 사람도 있다. 요즘은 그럴일이 거의 없다. 함수가 짧으면 캐싱하기가 더 쉽기 때문에 컴파일러가 최적화하는데 유리할 때가 많다. 성능 최적화에 대해서는 항상 일반지침을 따르자.
절차방법
1. 함수를 새로 만들고 목적을 잘 드러내는 이름을 붙인다('어떻게'가 아닌 '무엇을' 하는지가 드러나야 한다.)
2. 추출할 코드를 원본 함수에서 복사하여 새 함수에 붙여넣는다.
3. 추출한 코드 중 원본 함수의 지역 변수를 참조하거나 추출한 함수의 유효범위를 벗어나는 변수는 없는지 검사한다. 있다면 매개변수로 전달한다.
4. 변수를 다 처리했다면 컴파일한다.
5. 원본 함수에서 추출한 코드 부분을 새로 만든 함수를 호출하는 문장으로 바꾼다.(즉, 호출한 함수로 일을 위임한다.)
6. 테스트한다.
7. 다른 코드에 방금 추출한 것과 똑같거나 비슷한 코드가 없는지 살핀다. 있다면 방금 추출한 새 함수를 호출하도록 바꿀지 검토한다(인라인 코드를 함수 호출로 바꾸기)
예시 : 유효범위를 벗어나는 변수가 없을 때
function printOwing(invoice) {
let outstanding = 0;
console.log("===============");
console.log("=== current ===");
console.log("===============");
for (const o of invoice.orders) {
outstanding += o.amount;
}
const today = new Date();
invoice.dueDate = {
today.getFullYear(),
today.getMounth(),
today.getDate() + 30
};
console.log(`username: ${invoice.customer}`);
console.log(`amount: ${outstanding}`);
console.log(`finishDate: ${invoice.dueDate.toLocaleDateString()}`);
}
위에 코드와 아래 코드를 비교해보자.
위의 한 함수 안에서 있는 코드들을 각각 함수로 추출해서 작업을 했을때, 함수명만 보고도 어떤 일을 하는지 알 수 있게 된다.
function printOwing(invoice) {
printBanner();
let outstanding = culcurlateSum(invoice.orders);
recordDueDate(invoice);
printDetails(invoice, outstanding);
}
function printBanner() {
console.log("===============");
console.log("=== current ===");
console.log("===============");
}
function culcurlateSum(orders) {
let result = 0;
for (const value of orders) {
result += value.amount;
}
return result;
}
function recordDueDate(invoice) {
const today = new Date();
invoice.dueDate = {
today.getFullYear(),
today.getMounth(),
today.getDate() + 30
};
}
function printDetails(invoice, outstanding) {
console.log(`username: ${invoice.customer}`);
console.log(`amount: ${outstanding}`);
console.log(`finishDate: ${invoice.dueDate.toLocaleDateString()}`);
}
함수 인라인
function getRating(driver) {
return moreThanFiveLateDeliveries(driver) ? 2 : 1;
}
function moreThanFiveLateDeliveries(driver) {
return driver.numberOfLateDeliveres > 5;
}
굳이 한 줄 씩 함수로 하는것보다 함수 안에 한 줄로 바로 가능하지 않을까?
너무 함수화가 되어있다면 아래와 같이 인라인하게 만들 수 있다.
function getRating(driver) {
return (driver.numberOfLateDeliveries > 5) ? 2 : 1;
}
절차방법
1. 다형 메서드인지 확인한다.
2. 인라인할 함수를 호출하는 곳을 모두 찾는다.
3. 각 호출문을 함수 본문으로 교체한다.
4. 하나씩 교체할 때마다 테스트한다.
5. 함수 정의(원래 함수)를 삭제한다.
이 부분에서 핵심은 항상 단계를 잘게 나눠서 처리하는데 있다. 평소 내 스타일대로 함수를 작게 만들어뒀다면 인라인을 단번에 처리할 수 있을 때가 많다. (물론 약간 다듬어야 할 수 있다) 그러다 상황이 복잡해지면 다시 한 번에 한 문장씩 처리한다.
'refactoring' 카테고리의 다른 글
캡슐화 (0) | 2022.08.03 |
---|---|
여러 함수를 변환 함수로 묶기, 단계 쪼개기 (0) | 2022.08.02 |
변수 캡슐화하기, 이름바꾸기, 매개변수 객체 만들기 (0) | 2022.08.01 |
변수 추출하기(Extract), 인라인하기(Inline), 선언바꾸기(change) (0) | 2022.07.28 |