여러 함수를 클래스로 묶기 Combine Functions into Class

0

리팩터링 카탈로그

목록 보기
9/10

배경

클래스는 대다수의 최신 프로그래밍 언어가 제공하는 기본적인 빌딩 블로깅다. 클래스는 데이터와 함수를 하나의 공유 환경으로 묶은 후, 다른 프로그램 요소와 어우러질 수 있도록 그중 일부를 외부에 제공한다. 클래스는 객체 지향 언어의 기본인 동시에 다른 패러다임 언어에도 유용하다.

나는 (흔히 함수 호출 시 인수로 전달되는) 공통 데이터를 중심으로 긴밀하게 엮여 작동하는 함수 무리를 발견하면 클래스를 하나로 묶고 싶어진다. 클래스로 묶으면 이 함수들이 공유하는 공통 환경을 더 명확하게 표현할 수 있고, 각 함수에 전달되는 인수를 줄여서 객체 안에서의 함수 호출을 간결하게 만들 수 있다. 또한 이런 객체를 시스템의 다른 부분에 전달하기 위한 참조를 제공할 수 있다.

이 리펙터링은 이미 만들어진 함수들을 재구성할 때는 물론, 새로 만든 클래스와 관련하여 놓친 연산을 찾아서 새 클래스의 메서드로 뽑아내는 데도 좋다.

함수를 한데 묶는 또 다른 방법으로 여러 함수를 변환 함수로 묶기도 있다. 어느 방식으로 진행할지는 프로그램 문맥을 넓게 살펴보고 정해야 한다. 클래스로 묶을 때의 두드러진 장점은 클라이언트가 객체의 핵심 데이터를 변경할 수 있고, 파생 객체들을 일관되게 관리할 수 있다는 것이다.

이런 함수들을 중첩 함수 형태로 묶어도 된다. 나는 중첩 함수보다 클래스를 선호하는 편인데, 중첩 함수는 테스트하기가 까다로울 수 있기 때문이다. 또한 한 울타리로 묶을 함수들 중 외부에 공개할 함수가 여러 개일 때는 클래스를 사용할 수밖에 없다.

절차


  1. 함수들이 공유하는 공통 데이터 레코드를 캡슐화한다.
  • 공통 데이터가 레코드 구조로 묶여 있지 않다면 먼저 매개변수 객체 만들기로 데이터를 하나로 묶는 레코드를 만든다.
  1. 공통 레코드를 사용하는 함수 각각을 새 클래스로 옮긴다(함수 옮기기).
  • 공통 레코드의 맴버는 함수 호출문의 인수 목록에서 제거한다.
  1. 데아터를 조작하는 로직들은 함수로 추출해서 새 클래스로 옮긴다.

예시


before

const aReading = acquireReading();
const basicChargeAmount = calculateBaseCharge(aReading);
const taxablecharge = Math.max(0, aReading.baseCharge - 
                   taxThreshold(aReading.year));
function calculateBaseCharge(aReading) {
    return baseRate(aReading.month, aReading.quantity);
}

after


class Reading {
	constructor(data) {
       this._customer = data.customer;
       this._quantity = data.quantity;
       this._month = data.month;
       this._year = data.year;
    }
  
  //getters ~

  function getBaseCharge() {
     return baseRate(this.month, this.year_ * this.quantity;
  }
  
  function taxableCharge(aReading){
   return Math.max(0, aReading.baseCharge - 
                   taxThreshold(aReading.year));
  }
  
}

출처


마틴 파울러 저 리팩터링 2판

0개의 댓글