메서드 호출 단순화 - ChoDragon9/posts GitHub Wiki

메서드 호출 단순화

객체에서 가장 중요한 것은 인터페이스다. 이해와 사용이 쉬운 인터페이스를 작성하는 기술이야 말로 좋은 객체지향 소프트웨어 개발이다.

메서드명 변경(Rename Method)

메서드명을 봐도 기능을 알 수 없을 땐 직관적인 이름으로 바꾸자.

// Before
class Person {
  getTelephoneNumber () {
    return `(${officeAreaCode}) ${officeNumber}`
  }
}

// After
class Person {
  getOfficeTelephoneNumber () {
    return `(${officeAreaCode}) ${officeNumber}`
  }
}

매개변수 추가(Add Parameter)

메서드가 자신을 호출한 부분의 정보를 더 많이 알아야 할 땐 객체에 그 정보를 전달할 수 있는 매개변수를 추가하자

// Before
const getContract = () => {}

// After
const getContract = (Date) => {}

매개변수 제거(Remove Parameter)

메서드가 어떤 매개변수를 더 이상 사용하지 않을 땐 그 매개변수를 제거하자

// Before
const getContract = (Date) => {}

// After
const getContract = () => {}

상태 변경 메서드와 값 반환 메서드를 분리(Separate Query from Modifier)

값 반환 기능과 객체 상태 변경 기능이 한 메서드에 들어 있을 땐 질의 메서드와 변경 메서드로 분리하자

// Before
const getTotalOutStandingAndSetReadyForSummaries = () => {}

// After
const getTotalOutStanding = () => {}
const setReadyForSummaries = () => {}

메서드를 매개변수로 전환(Parameterize Method)

여러 메서드가 기능은 비슷하고 안에 든 값만 다를 땐 서로 다른 값을 하나의 매개변수로 전달받는 메서드를 하나 작성하자

// Before
const fivePercentRaise = () => {}
const tenPercentRaise = () => {}

// After
const raise = (percentage) => {}

매개변수를 메서드로 전환(Replace Parameter with Explicit Methods)

매개변수로 전달된 값에 따라 메서드가 다른 코드를 실행할 땐 그 매개변수로 전달될 수 있는 모든 값에 대응하는 메서드를 각각 작성하자

// Before
const setValue = (name, value) => {
  if (name === 'height') {
    height = value
    return
  }
  if (name === 'width') {
    width = value
    return
  }
}

// After
const setHeight = (value) => {
  height = value
}
const setWidth = (value) => {
  width = value
}

객체를 통째로 전달(Preserve Whole Object)

객체에서 가져온 여러 값을 메서드 호출에서 매개변수로 전달할 땐 그 객체를 통째로 전달하게 수정하자.

객체가 나중에 새 데이터 값을 필요로 할 때마다 이 메서드 호출하는 모든 부분을 찾아서 수정해야 하는 문제가 있다.

// Before
const low = daysTempRange().getLow()
const high = daysTempRange().getHigh()
const withinPlan = plan.withinRange(low, high)

// After
const withinPlan = plan.withinRange(daysTempRange())

매개변수 세트를 메서드로 전환(Replace Parameter with Method)

객체가 A 메서드를 호출해서 그 결과를 B 메서드에 매개변수로 전달하는데, 결과를 매개변수로 받는 B 메서드로 직접 A 메서드를 호출할 수 있을 땐 매개변수를 없애고 A 메서드를 B 메서드가 호출하게 하자.

// Before
const getDiscountLevel = () => 0.5
const discountedPrice = (basePrice, discountLevel) => {
  return basePrice - discountLevel * 10
} 
const basePrice = quantity + itemPrice
const discountLevel = getDiscountLevel()
const finalPrice = discountedPrice(basePrice, discountLevel)

// After
const getDiscountLevel = () => 0.5
const discountedPrice = (basePrice) => {
  return basePrice - getDiscountLevel() * 10
} 
const basePrice = quantity + itemPrice
const finalPrice = discountedPrice(basePrice)

매개변수 세트를 객체로 전환(Introduce Parameter Object)

여러 개의 매개변수가 항상 붙어 다닐 땐 그 매개변수를 객체로 바꾸자.

// Before
const amountInvoicedIn = (startDate, endDate) => {}
const amountReceivedIn = (startDate, endDate) => {}
const amountOverdueIn = (startDate, endDate) => {}

// After
const amountInvoicedIn = (DateRange) => {}
const amountReceivedIn = (DateRange) => {}
const amountOverdueIn = (DateRange) => {}

쓰기 메서드 제거(Remove Setting Method)

생성시 지정한 필드 값이 절대로 변경되지 말아야 할 땐, 그 필드를 설정하는 모든 쓰기 메서드를 삭제하자

// Before
class Employee {
  setImmutableValue () { }
}

// After
class Employee { }

메서드 은폐(Hide Method)

메서드가 다른 클래스에 사용되지 않을 땐 그 메서드의 반환 타입을 private로 만들자

// Before
class Employee {
  aMethod () { }
}

// After
class Employee {
  _aMethod () { }
}

생성자를 팩토리 메서드로 전환(Replace Constructor with Factory Method)

객체를 생성할 때 단순한 생성만 수행하게 해야 할 땐 생성자를 팩토리 메서드로 교체하자.

// Before
class Employee {
  constructor (type) {
    this.type = type
  }
}

const employee = new Employee('Manager')

// After
class Employee {
  constructor (type) {
    this.type = type
  }
  static create (type) {
    return new Employee(type)
  }
}

const employee = Employee.create('Manager')

에러 부호를 예외 통지로 교체(Replace Error Code with Exception)

메서드가 에러를 나타내는 특수한 부호를 반환할 땐 그 부호 반환 코드를 예외 통지 코드로 바꾸자.

// Before
const withDraw = (amount) => {
  if (amount > this.balance) {
    return -1
  } else {
    this.balance -= amount
    return 0
  }
}

// After
const withDraw = (amount) => {
  if (amount > this.balance) {
    throw "BalanceException"
  }
  this.balance -= amount
}

예외 처리를 테스트로 교체(Replace Exception with Test)

호출 부분에 사전 검사 코드를 넣으면 될 상황인데 예외 통지를 사용했을 땐 호출 부분이 사전 검사를 실시하게 수정하자.

예외 처리는 예외적 기능, 즉 예기치 못한 에러에 사용해야 한다. 예외 처리를 조건문 대용으로 사용해서는 안된다.

// Before
const getValueForPeriod = (periodNumber) => {
  try {
    return this.value[periodNumber]
  } catch (error) {
    return 0
  }
}

// After
const getValueForPeriod = (periodNumber) => {
  if (periodNumber >= this.value.length) {
    return 0
  }
  return this.value[periodNumber]
}