개발공부

[리팩터링] 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