개발공부
[리팩터링] Refactoring 2판 - 6장
햄❤️
2023. 2. 24. 17:51
728x90
6장 리팩터링의 기본 중에서 가장 많이 쓰인다는 함수 추출하기, 변수 추출하기, 함수 인라인하기에 대해 공부했다. 함수 추출하기는 개발자들이 흔히 하는 리팩터링 중 하나라 이해하기 쉬웠지만, 함수 인라인하기는 많이 해본적 없어서 어려웠다.
함수 인라인하기에서는 로직 상 a함수와 b함수가 무조건 같이 호출 되는 경우에, 굳이 분리하는 것 보다 하나의 함수로 묶는것이 더 낫다고 한다.
6-1. 함수 추출하기 (Extract Function) ⭐️⭐️⭐️⭐️⭐️
- 코드 조각이 하는 일에 따라 독립된 함수로 추출하고 목적에 맞는 이름을 붙이는 일
- 언제 추출하는가?
- 길이가 길 때,
- 재사용 가능 할 때,
- 목적과 구현을 분리할 때
- 절차
- 함수를 새로 만들고 목적을 잘 드러내는 이름을 붙인다(어떻게가 아닌 ‘무엇을’ 하는지 드러나게)
- 추출할 코드를 원본 함수에서 복사하여 새 함수에 붙인다.
- 추출 코드 중 원본 함수의 지역변수를 참조하거나 추출한 함수의 유효범위를 벗어나는 변수는 없는지 검사한다. 있다면 매개변수로 전달한다.
- 변수를 다 처리했다면 컴파일한다.
- 원본 함수에서 추출한 코드 부분을 새로 만든 함수를 호출하는 문장으로 바꾸고 테스트한다.
- 다른 코드에 방금 추출한 것과 비슷한 코드가 있는지 살피고, 있다면 방금 만든 새 함수로 바꿀지 검토한다.
👉🏻 리팩터링 전
function printOwing(invoice) {
let outstanding = 0;
console.log("********");
console.log("**고객 채무**");
console.log("********");
//미해결 채무(outstanding) 계산
for(const o of invoice.orders) {
outstanding += 0.amountl
}
//마감일(dueDate)을 기록한다.
const today = Clock.today;
invoice.dueDate = new Date(today.getFullYear(), today.getMonth(),
today.getDate() + 30);
//세부 사항을 출력한다.
console.log(`고객명: ${invoice.customer}`);
console.log(`채무액: ${outstanding}`);
console.log(`마감일: ${invoice.dueDate.toLocaleDateString()}`);
}
👉🏻 리팩터링 후
- outstanding은 calculateOutstanding에서 계산하는데 쓰이는 변수로, printOwing에서 굳이 지역변수로 선언하지 않아도 된다. return 되게끔만 처리해준다. 따라서 return 받은 outstanding을 let에서 const로 선언해줄 수 있다.
- 각자 목적에 따른 함수인 calculateOutstanding, recordDueDate, printBanner, printDetails로 쪼개서 리팩터링했다.
function printOwing(invoice) {
printBanner();
const outstanding = calculateOutstanding(invoice);
recordDueDate(invoice);
printDetails(invoice, outstading);
}
//*****************************************************************
function printBanner () {
console.log("********");
console.log("**고객 채무**");
console.log("********");
}
function calculateOutstanding (invoice) {
let result = 0;
for(const o of invoice.orders) {
outstanding += 0.amount;
}
return result;
}
function recordDueDate (invoice) {
const today = Clock.today;
invoice.dueDate = new Date(today.getFullYear(), today.getMonth(),
today.getDate() + 30);
}
function printDetails (invoice, outstanding) {
console.log(`고객명: ${invoice.customer}`);
console.log(`채무액: ${outstanding}`);
console.log(`마감일: ${invoice.dueDate.toLocaleDateString()}`);
}
6-2. 함수 인라인하기 (Inline Function) ⭐️⭐️⭐️⭐️
- 6-1의 함수 추출하기와 반대되는 개념으로 추출된 함수들을 원래 함수로 합치는 과정
- 간접 호출을 과하게 쓰거나, 단순히 다른 함수로 위임하는 함수들은 인라인의 대상이 된다.
- 절차
- 다형 메서드인지 확인한다. 오버라이드 메서드는 인라인하면 안된다.
- 인라인할 함수를 호출하는 곳을 모두 찾는다.
- 각 호출문을 함수 본문으로 교체한다.
- 하나씩 교체할 때마다 테스트한다.
- 함수 정의(원래 함수)를 삭제한다.
- 코드예시
👉🏻 리팩터링 전
function reportLines (aCustomer) {
const lines = [];
gatherCustomerData(lines, aCustomer);
return lines;
}
function gatherCustomerData(out, aCustomer){
out.push(["name", aCustomer.name]);
out.push(["location", aCustomer.location]);
}
👉🏻 리팩터링 후
- 리팩터링 시 다른 매개변수는 주의해서 변경해서 리팩터링 해준다.
- 단순히 배열에 추가하기만 하는 코드를 굳이 추출할 할 필요 없다.
function reportLines (aCustomer) {
const lines = [];
**lines.push(["name", aCustomer.name]);
lines.push(["location", aCustomer.location]);**
return lines;
}
6-3. 변수 추출하기 (Extract Variable) ⭐️⭐️⭐️⭐️⭐️
- 표현식이 너무 복잡해서 이해하기 어려울 때, 지역 변수를 활용하면 표현식을 쪼개 관리하기 더 쉽다. → 코드의 목적을 분명하고 명확하게 드러낸다.
- 절차
- 추출하려는 표현식에 부작용은 없는지 확인한다.
- 불변 변수를 하나 선언하고 이름을 붙일 표현식의 복제본을 대입한다.
- 원본 표현식을 새로 만든 변수로 교체한다.
- 테스트한다.
- 표현식을 여러 곳에서 사용한다면 각각 새로 만든 변수로 교체한다. 하나 교체할 때마다 테스트한다.
- 코드 예시
👉🏻 리팩터링 전
function price(order) {
// 가격(price) = 기본 가격 - 수량 할인 + 배송비
return order.quantity * order.itemPrice - Math.max(0, order.quantity - 500)
* order.itemPrice * 0.05
+ Math.min(order.quantity * order.itemPrice * 0.1, 100);
}
👉🏻 리팩터링 후
- 수식을 쪼개서 적절한 변수에 담아 교체해준다. 변수명을 지을 때는, 중복이 적으면서 의도가 잘 드러나게 짓는다.
function price(order) {
const basePrice = order.quantity * order.itemPrice;
const quantityDiscount = Math.max(0, order.quantity - 500) * order.itemPrice * 0.05;
const shipping = Math.min(order.quantity * order.itemPrice * 0.1, 100);
return basePrice - quantityDiscount + shipping;
}
728x90