Notice
Recent Posts
Recent Comments
Link
관리 메뉴

김종권의 iOS 앱 개발 알아가기

[Refactoring] 5-3. 기본적인 리펙토링 (여러 함수를 하나의 함수로 묶기) 본문

Refactoring (리펙토링)

[Refactoring] 5-3. 기본적인 리펙토링 (여러 함수를 하나의 함수로 묶기)

jake-kim 2023. 3. 19. 02:30

리펙토링 핵심

  • 각 방법들을 '왜' 수행해야 하는지 깨닫고 유연하게 적용하기

함수들을 클래스로 묶기

  • 함수는 데이터를 입력받아서 여러가지 정보를 얻는데, 이렇게 입력받는 데이터들의 중복을 줄이기 위한 방법
  • 매개변수 같은 중심(공통 데이터)으로 긴밀하게 엮여 작동하는 함수 무리를 하나의 함수로 묶는 것
    • 장점 - 중복코드를 막고 함수들이 공유하는 공통 환경을 더욱 명확하게 표현이 가능

여러 함수를 클래스로 묶기

ex) 여러 함수를 묶기

- 보일러 사용량과 기간에 대해 세금을 계산하는 코드

// 보일러 사용 정보
struct UseInfo {
    let quantity = 1
    let month = 2
    let year = 3
}

// 보일러 정보 획득
func getUseInfo() -> UseInfo {
    UseInfo()
}

// 기본적으로 내야하는 비율
func baseRate(month: Int, year: Int) -> Int {
    month + year
}

// 세금의 최댓값
func taxThreshold(year: Int) -> Int {
    year * 3
}
  • a 고객의 세금 계산
    • 문제점: baseRate를 구할때 month, year 모두 aUserInfo 하나만 받으면 내부에서 .month, .year 접근해서 사용 가능하므로 파라미터를 하나만 받도록 수정해도 처리가 가능
let aUserInfo = getUseInfo()
let aBaseCharge = baseRate(month: aUserInfo.month, year: aUserInfo.year) * aUserInfo.quantity
let aTexableCharge = max(0, bBaseCharge - taxThreshold(year: 2023))
  • calculateBaseCharge(userInfo:) 를 만들어서 리펙토링
func calculateBaseCharge(useInfo: UseInfo) -> Int {
    baseRate(month: useInfo.month, year: useInfo.year)
}

let bUseInfo = getUseInfo()
let bBaseCharge = calculateBaseCharge(useInfo: aUseInfo) * bUseInfo.quantity
let bTexableCharge = max(0, bBaseCharge - taxThreshold(year: 2023))
  • 하나의 함수로 묶어서, 사용하는 쪽(=클라이언트 코드)에서는 단순히 useInfo와 year만 넣으면 되도록 구현
func calculateTotalCharge(useInfo: UseInfo, year: Int) -> Int {
    let baseCharge = calculateBaseCharge(useInfo: useInfo)
    let textableCharge = max(0, baseCharge, taxThreshold(year: year))
    return textableCharge
}

let cTexableCharge = calculateTotalCharge(useInfo: getUseInfo(), year: 2023)
  • 결과
    • 중복 제거 - 리펙토링전에 클라이언트 코드에서 baseCharge와 textableCharge를 계산하는 코드가 a 클라이언트 코드, b 클라이언트 코드가 생성되지만 리펙토링 후에는 이런 중복 작업이 불필요
  • 주의
    • 파라미터의 데이터들이 중복으로 생길때 함수로 묶을수도 있지만, 원본 데이터가 코드 안에서 갱신될때는 함수가 아닌 클래스로 묶을 것 (상태가 변경된다는 것은 함수가 아닌 인스턴스의 성격을 갖는 클래스로 묶는것이 더욱 적합)
    • * 클래스는 상태(state)와 동작(method)로 이루어져 있기 때문에 상태를 변경할땐 이러한 인스턴스로 관리하는게 논리적으로 더욱 코드를 읽는 입장에서 예측하기 쉬움

* 참고

- Refactoring (Marting Flowler)

Comments