해당 글은 마틴 파울러의 리팩토링 2판 6.1 함수 추출하기의 리뷰 포스팅입니다.
function printOwing(invoice) {
let outstanding = calcuateOutstanding();
// 세부사항 출력
console.log(`고객명: ${invoice.customer}`);
console.log(`채무액: ${outstanding}`);
}
< 함수 추출하기 전 >
function printOwing(invoice) {
let outstanding = calcuateOutstanding();
// 세부사항 출력
printDetails(outstanding);
function printDetails(outstanding) {
console.log(`고객명: ${invoice.customer}`);
console.log(`채무액: ${outstanding}`);
}
}
< 함수 추출하기 후 >
함수 추출하기는 코드 조각을 찾아 무슨 일을 하는지 파악한 다음, 독립된 함수로 추출하고 목적에 맞는 이름을 붙히는 리팩토링 기법이다.
이 때, 코드를 언제 독립된 함수로 묶어야 할지에 관해 다음과 같은 의견들이 있다.
1. 길이를 기준으로 일정 수준 이상이면 함수로 추출한다.
2. 재사용성을 기준으로 추출한다. 예를 들어, 반복되는 코드는 함수로 추출한다.
하지만 마틴 파울러는 '목적과 구현의 분리'를 하는 방식이 가장 합리적인 기준이라고 말한다.
이 때, 목적과 구현의 분리란 코드를 보고 무슨일을 하는지를 기준으로 함수로 추출되어야 한다는 것이다. 만약 어떤 코드를 보고 무슨 일을 하는지 파악하는데 한참 시간이 걸린다면 함수 추출하기가 필요한 때이다.
이러한 함수 추출은 수많은 작은 함수들을 생성하게 되는데, 이 때문에 성능이 느려진다거나 하는 오해가 있다고 한다.
실제로는 함수가 짧으면 캐싱하기가 더 쉽기 때문에 컴파일러가 최적화하는데 더 유리하다고 한다.
예시: 유효범위를 벗어나는 변수가 없을 때
function printOwing(invoice) {
let outstanding = 0;
console.log('*****************')
console.log('**** 고객 채무 ****')
console.log('*****************')
// 미해결 채무(outstanding)를 계산한다.
for (const o of invoice.orders) {
outstanding += o.amount;
}
// 마감일 (dueDate)을 기록한다.
const today = new Date();
invoice.dueDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 30);
// 세부 사항을 출력한다.
console.log(`고객명 ${invoice.customer}`)
console.log(`채무액 ${outstanding}`)
console.log(`마감일 ${invoice.dueDate.toLocaleDateString()}`)
}
< 함수 추출하기 전 >
해당 코드에서 배너와 세부사항을 출력하는 코드를 쉽게 함수 추출하기로 리팩토링 할 수 있다.
function printOwing(invoice) {
let outstanding = 0;
printBanner();
// 미해결 채무(outstanding)를 계산한다.
for (const o of invoice.orders) {
outstanding += o.amount;
}
// 마감일 (dueDate)을 기록한다.
const today = new Date();
invoice.dueDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 30);
// 세부 사항을 출력한다.
printDetails();
function printDetails() {
console.log(`고객명 ${invoice.customer}`);
console.log(`채무액 ${outstanding}`);
console.log(`마감일 ${invoice.dueDate.toLocaleDateString()}`);
}
}
function printBanner() {
console.log('*****************');
console.log('**** 고객 채무 ****');
console.log('*****************');
}
< 출력 관련 함수 추출하기 후 >
이 때, printDetails()함수가 printOwing()에 중첩되어 있는 점에 유의하자. 이렇게 내부에 함수를 전언하게 되면 printOwing()에 정의되어 있는 모든 변수에 접근 할 수 있다.
예시: 지역변수를 사용할 때
function printOwing(invoice) {
let outstanding = 0;
printBanner();
// 미해결 채무(outstanding)를 계산한다.
for (const o of invoice.orders) {
outstanding += o.amount;
}
// 마감일 (dueDate)을 기록한다.
recodeDueDate(invoice);
// 세부 사항을 출력한다.
printDetails(nvoice, outstanding);
}
function recordDueDate(invoice) {
const today = new Date();
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()}`);
}
function printBanner() {
console.log('*****************');
console.log('**** 고객 채무 ****');
console.log('*****************');
}
printDetails()가 사용하는 변수들을 지역변수로 사용하기 위해 인자로 넘겼다. 또한 지역변수가 데이터 구조라면 매개 변수로 넘긴 후 필드 값을 수정할 수 있다.
예시: 지역 변수의 값을 변경할 때
// 미해결 채무(outstanding)를 계산한다.
let outstanding = 0;
for (const o of invoice.orders) {
outstanding += o.amount;
}
< 리팩토링을 위해 outstanding을 사용하는 곳에 모은다. // 문장 슬라이드 >
지역 변수 outstanding의 값은 변한다. 이를 함수화 하기 위해서 일단 문장 슬라이드하기를 통하여 사용되는 변수를 한 곳에 모은다.
function printOwing(invoice) {
printBanner();
// 미해결 채무(outstanding)를 계산한다.
const outstanding = calculateOutstanding(invoice);
// 마감일 (dueDate)을 기록한다.
recodeDueDate(invoice);
// 세부 사항을 출력한다.
printDetails(nvoice, outstanding);
}
function calculateOutstanding(invoice) {
let result = 0;
for (const o of invoice.orders) {
result += o.amount;
}
return result;
}
이 후에 outstanding을 연산하는 함수를 추출한다. 이 때, 결과 값인 outstanding은 더 이상 변하지 않기 때문에 const(상수) 선언을 하였고, 계산 결과를 나타내는 outstanding을 함수 내에서 result라는 네이밍으로 변경하였다.
'Develop' 카테고리의 다른 글
AWS Lambda 기본 기능 파악하기 (1) (0) | 2021.01.27 |
---|---|
API Gateway를 사용하여 API 구축하기 (3) REST API 생성 (0) | 2021.01.26 |
API Gateway를 사용하여 API 구축하기 (2) HTTP API 생성 (0) | 2021.01.25 |
API Gateway를 사용하여 API 구축하기 (1) 기본 개념 (0) | 2021.01.24 |
도커 SEARCH CLI 명령어 정리 (0) | 2021.01.23 |