[Refactoring] # 클래스 추출하기

mechaniccoder·2021년 10월 18일
0
post-thumbnail

지난 시간에 배웠던, 함수 추출하기/함수 인라인하기와 비슷하게 클래스도 추출과 인라인을 할 수가 있다. 이번 시간에는 클래스 추출하기 리팩토링 기법을 배워보자.

클래스를 작성할때는 객체의 역할과 책임을 고려하며 설계를 하는데, 코드가 변경되고 여러 로직이 추가되면서 클래스가 비대해지는 경우가 있다.

이럴때는 너무 많은 역할을 하지 않도록, 클래스로 추출해주는 것이 좋다. 코드를 살펴보자.

Code

/**
 *  클래스를 처음 작성할때는 역할과 책임을 명확하게 수행하지만, 코드가 변경되면서 여러가지 메서드들이 추가되며 매우 비대해진다.
 *  역할도 덧 씌어지고 말이다. 그럴때는 클래스 추출하기 리팩토링 기법을 활용해서 분리하자.
 */

class Person {
  constructor(data) {
    this._name = data.name;
    this._officeAreaCode = data.officeAreaCode;
    this._officeNumber = data.officeNumber;
  }
  get name() {
    return this._name;
  }
  set name(arg) {
    this._name = arg;
  }
  get telephoneNumber() {
    return `${this.officeAreaCode} ${this.officeNumber}`;
  }
  get officeAreaCode() {
    return this._officeAreaCode;
  }
  set officeAreaCode(arg) {
    this._officeAreaCode = arg;
  }
  get officeNumber() {
    return this._officeNumber;
  }
  set officeNumber(arg) {
    this._officeNumber = arg;
  }
}

// 전화번호 관련 오퍼레이션을 클래스로 추출해보자.
class TelephoneNumber {
  constructor(data) {
    this._officeAreaCode = data.officeAreaCode;
    this._officeNumber = data.officeNumber;
  }
  get officeAreaCode() {
    return this._officeAreaCode;
  }
  set officeAreaCode(arg) {
    this._officeAreaCode = arg;
  }
  get officeNumber() {
    return this._officeNumber;
  }
  set officeNumber(arg) {
    this._officeNumber = arg;
  }
  get telephoneNumber() {
    return `${this.officeAreaCode} ${this.officeNumber}`;
  }
}

class Person {
  constructor(data) {
    this._name = data.name;
    this._telephoneNumber = new TelephoneNumber();
  }
  get name() {
    return this._name;
  }
  set name(arg) {
    this._name = arg;
  }
  get telephoneNumber() {
    return this._telephoneNumber.telephoneNumber();
  }
  get officeAreaCode() {
    return this._telephoneNumber.officeAreaCode;
  }
  set officeAreaCode(arg) {
    this._telephoneNumber._officeAreaCode = arg;
  }
  get officeNumber() {
    return this._telephoneNumber._officeNumber;
  }
  set officeNumber(arg) {
    this._telephoneNumber._officeNumber = arg;
  }
}

// 메서드 이름을 간소화해주자.

class TelephoneNumber {
  constructor(data) {
    this._areaCode = data.areaCode;
    this._number = data.number;
  }
  get areaCode() {
    return this._areaCode;
  }
  set officeAreaCode(arg) {
    this._areaCode = arg;
  }
  get officeNumber() {
    return this._number;
  }
  set officeNumber(arg) {
    this._number = arg;
  }
  get toString() {
    return `${this.areaCode} ${this.number}`;
  }
}

class Person {
  constructor(data) {
    this._name = data.name;
    this._telephoneNumber = new TelephoneNumber();
  }
  get name() {
    return this._name;
  }
  set name(arg) {
    this._name = arg;
  }
  get telephoneNumber() {
    return this._telephoneNumber.toString();
  }
  get officeAreaCode() {
    return this._telephoneNumber.areaCode;
  }
  set officeAreaCode(arg) {
    this._telephoneNumber.areaCode = arg;
  }
  get officeNumber() {
    return this._telephoneNumber.number;
  }
  set officeNumber(arg) {
    this._telephoneNumber.number = arg;
  }
}

느낀점

확실히 클래스의 역할을 명확하게 하면, 변동사항이 있을때 코드를 유지 보수하기 쉬운 구조가 된다고 생각한다. 위에서는 현재 TelephoneNumber라는 구체를 Person의 내부에서 생성하여 의존관계를 이루고 있는데, 이를 개선한다면 dependency injection을 활용해서 클라이언트에서 Person의 구체를 생성할때 TelephoneNumber의 구체도 함께 생성하여 인자로 넘겨주면, 더 좋은 코드를 작성할 수 있다고 생각한다.

profile
세계 최고 수준을 향해 달려가는 개발자입니다.

0개의 댓글