728x90
- 반대 리팩토링 : 함수 인라인하기
function printOwing(invocie) {
printBanner()
let outstanding = calculateOutstanding()
// 세부 사항 출력
console.log(`${invoice.customer}`)
console.log(`${outstanding}`)
}
function printOwing(invocie) {
printBanner()
let outstanding = calculateOutstanding()
printDetails(outstanding)
}
function printDetails(outstanding) {
console.log(`${invoice.customer}`)
console.log(`${outstanding}`)
}
함수 안에 들어갈 코드가 대 여섯 줄을 넘어갈 때부터 않좋은 냄새가 풍긴다.
함수가 짧으면 캐싱하기가 더 쉽기 때문에 컴파일러가 최적화 되는데 유리하다.
절차
- 함수를 새로 만들고 목적이 잘 드러나는 이름을 붙입니다.(’어떻게’가 아닌 ‘무엇을’ 하는지가 드러나야 한다.)
- 추출한 코드를 원본 함수에서 복사하여 새 함수에 붙여놓는다.
- 추출한 코드 중 원본 함수의 지역 변수를 참조하거나 추출한 함수의 유효범위를 벗어나는 변수는 없는지 있다면 매개변수로 전달
- 변수를 다 처리했다면 컴파일한다.
- 원본 함수에서 추출한 코드 부분을 새로 만든 함수를 호출하는 문장으로 바꾼다.(즉, 추출한 함수로 일을 위임한다.)
- 테스트한다.
- 다른 코드에 방금 추출한 것과 똑같거나 비슷한 코드가 없는지 살핀다. 있다면 방금 추출한 새 함수를 호출하도록 바꿀지 검토한다.(인라인 코드를 함수 호출로 바꾸기)
예시
function printOwing(invoice) {
let outstanding = 0
console.log('====================================')
console.log('고객 채무')
console.log('====================================')
// 미해결 채무(outstanding)를 계산한다.
for (let i of invoice.orders) {
outstanding += i.amount
}
// 마감일(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()}`)
}
Date.now()처럼 시스템 시간을 알려주는 함수는 직접 호출하지 않는다.
function printOwing(invoice) {
let outstanding = 0
printBanner()
// 미해결 채무(outstanding)를 계산한다.
for (let i of invoice.orders) {
outstanding += i.amount
}
// 마감일(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()}`)
}
function printBanner() {
console.log('====================================')
console.log('고객 채무')
console.log('====================================')
}
마찬가지로 세부 사항을 출력하는 코드도 간단히 추출할 수 있다.
function printOwing(invoice) {
let outstanding = 0
printBanner()
// 미해결 채무(outstanding)를 계산한다.
for (let i of invoice.orders) {
outstanding += i.amount
}
// 마감일(dueDate)을 기록합니다.
const today = Clock.today
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 printOwing(invoice) {
let outstanding = 0
printBanner()
// 미해결 채무(outstanding)를 계산한다.
for (let i of invoice.orders) {
outstanding += i.amount
}
// 마감일(dueDate)을 기록합니다.
const today = Clock.today
invoice.dueDate = new Date(
today.getFullYear(),
today.getMonth(),
today.getDate() + 30
)
// 세부 사항을 출력합니다.
printDetails(invoice, outstanding)
}
function printDetails(invoice, outstanding) {
console.log(`고객명: ${invoice.customer}`)
console.log(`채무액: ${outstanding}`)
console.log(`마감일: ${invoice.dueDate.toLocaleDateString()}`)
}
지역 변수가 데이터 구조라면 똑같이 매개변수로 넘긴 후 필드 값을 수정할 수 있다.
function printOwing(invoice) {
let outstanding = 0
printBanner()
// 미해결 채무(outstanding)를 계산한다.
for (let i of invoice.orders) {
outstanding += i.amount
}
// 마감일(dueDate)을 기록합니다.
recordDueDate(invoice)
// 세부 사항을 출력합니다.
printDetails(invoice, outstanding)
}
function recordDueDate(invoice) {
const today = Clock.today
invoice.dueDate = new Date(
today.getFullYear(),
today.getMonth(),
today.getDate() + 30
)
}
지역 변수의 값을 변경할 때
지역 변수에 값을 대입하게 되면 문제가 복잡해진다. 지금은 변수만을 취급하겠다. 만약 매개변수에 값을 대입하는 코드를 발견하면 곧바로 그 변수를 쪼개서 임시 변수를 새로 하나 만들어 그 변수에 대입하게 한다.
function printOwing(invoice) {
printBanner()
// 미해결 채무(outstanding)를 계산한다.
let outstanding = 0 // 맨 위에 있던 선언문을 이 위치로 이동
for (let i of invoice.orders) {
outstanding += i.amount
}
// 마감일(dueDate)을 기록합니다.
recordDueDate(invoice)
// 세부 사항을 출력합니다.
printDetails(invoice, outstanding)
}
그런 다음 추출할 부분을 새로운 함수로 복사한다.
function printOwing(invoice) {
printBanner()
// 미해결 채무(outstanding)를 계산한다.
let outstanding = calculateOutstanding(invoice)
// 마감일(dueDate)을 기록합니다.
recordDueDate(invoice)
// 세부 사항을 출력합니다.
printDetails(invoice, outstanding)
}
function calculateOutstanding(invocie){
let outstanding = 0 // 맨 위에 있던 선언문을 이 위치로 이동
for (let i of invoice.orders) {
outstanding += i.amount
}
return outstanding
}
outstanding의 선언문을 추출할 코드 앞으로 옮겼기 때문에 매개 변수로 전달하지 않아도 된다. 추출한 코드에서 값이 변경된 변수는 outstanding뿐이다. 따라서 이 값을 반환한다. 167p
다음으로 넘어가서 추출한 코드의 원래 자리를 새로 뽑아낸 함수를 호출하는 문장으로 교체한다.
function printOwing(invoice) {
printBanner()
// 함수 추출 완료
const outstanding = calculateOutstanding(invoice)
recordDueDate(invoice)
printDetails(invoice, outstanding)
}
function calculateOutstanding(invocie){
let outstanding = 0 // 맨 위에 있던 선언문을 이 위치로 이동
for (let i of invoice.orders) {
outstanding += i.amount
}
return outstanding
}
그 다음 변수명을 변경한다.
function printOwing(invoice) {
printBanner()
// 함수 추출 완료
const outstanding = calculateOutstanding(invoice)
recordDueDate(invoice)
printDetails(invoice, outstanding)
}
function calculateOutstanding(invocie){
let result = 0 // 맨 위에 있던 선언문을 이 위치로 이동
for (let i of invoice.orders) {
result += i.amount
}
return result
}
728x90