상속 다루기

2025. 6. 12. 06:52·Programming/Refactoring

메서드 올리기

배경

상속 구조에서 여러 하위 클래스에 동일하거나 거의 동일한 메서드가 존재할 때, 이 중복은 유지보수 비용을 높이고 버그 가능성을 증가시킨다.
메서드 올리기는 이런 중복된 메서드를 상위 클래스로 옮겨 중복을 제거하고, 공통 동작을 하나의 위치에서 관리할 수 있도록 한다.

절차

  1. 중복된 메서드 탐색
    하위 클래스들에 동일하거나 유사한 메서드가 존재하는지 확인한다.
  2. 메서드 본문 통일화
    두 메서드가 완전히 같지 않다면, 먼저 메서드 본문을 같도록 리팩터링한다. 필요 시 Parameterize Function, Extract Function 등의 기법을 사용할 수 있다.
  3. 상위 클래스에서 사용 가능한지 확인
    메서드 내부에서 참조하는 필드나 메서드가 상위 클래스에도 존재하는지 점검한다. 없을 경우 필드 올리기, 메서드 올리기 등을 먼저 적용한다.
  4. 시그니처 통일화
    메서드 이름이나 인자가 다르면 함수 선언 변경(Change Function Declaration)으로 통일한다.
  5. 상위 클래스에 메서드 추가
    하나의 메서드 본문을 상위 클래스로 복사하여 새로운 메서드를 만든다.
  6. 하위 클래스 메서드 제거 및 테스트
    하위 클래스에서 해당 메서드를 하나씩 제거하고, 그때마다 테스트를 수행하여 문제가 없는지 확인한다.

예시

리팩터링 전, 두 하위 클래스에 같은 동작을 하는 메서드가 존재한다.

class Employee extends Party {
  get annualCost() {
    return this.monthlyCost * 12;
  }
}

class Department extends Party {
  get totalAnnualCost() {
    return this.monthlyCost * 12;
  }
}
  1. 이름을 통일한다 (totalAnnualCost → annualCost):
class Department extends Party {
  get annualCost() {
    return this.monthlyCost * 12;
  }
}
  1. 메서드 본문이 동일하므로, 상위 클래스인 Party로 메서드를 옮긴다:
class Party {
  get annualCost() {
    return this.monthlyCost * 12;
  }
}
  1. 하위 클래스에서 메서드를 제거하고 테스트한다:
// Employee, Department에서 annualCost 제거

추가적으로, monthlyCost가 상위 클래스에 존재하지 않는다면 다음과 같이 추상 책임을 명시할 수 있다:

class Party {
  get monthlyCost() {
    throw new SubclassResponsibilityError();
  }

  get annualCost() {
    return this.monthlyCost * 12;
  }
}

 

필드 올리기

배경

여러 하위 클래스에서 동일한 역할을 하는 필드가 선언되어 있다면, 이를 상위 클래스로 옮기는 것이 좋다.
이렇게 하면 중복을 제거하고, 관련 동작(메서드)도 상위 클래스로 올릴 수 있는 기반을 마련하게 된다.
필드 이름이 다르더라도 사용하는 방식이 같다면, 필드 이름 바꾸기(Rename Field) 후 이 리팩터링을 적용할 수 있다.

절차

  1. 필드 후보 식별
    하위 클래스들에 유사한(또는 동일한) 필드가 있는지 확인한다. 이름이 다르더라도 역할이나 사용 방식이 같다면 후보가 될 수 있다.
  2. 필드 이름 통일
    필드 이름이 다르다면 Rename Field를 사용해 같은 이름으로 맞춘다.
  3. 사용 방식 확인
    해당 필드가 모든 하위 클래스에서 동일하게 사용되는지 점검한다. 접근 방식이나 연관된 메서드가 비슷해야 한다.
  4. 상위 클래스에 필드 추가
    공통 필드를 상위 클래스에 선언한다. 정적 타입 언어에서는 접근 제어자를 protected로 설정하면 하위 클래스에서 사용할 수 있다.
  5. 하위 클래스에서 필드 제거
    각 하위 클래스에서 중복 필드를 제거한다.
  6. 테스트
    변경 이후 기존 기능이 정상 동작하는지 테스트한다.

예시

리팩터링 전, 두 하위 클래스에 _name이라는 필드가 중복 선언되어 있다:

class Employee extends Party {
  constructor(name, id, monthlyCost) {
    super();
    this._name = name;
    this._id = id;
    this._monthlyCost = monthlyCost;
  }
}

class Department extends Party {
  constructor(name, staff) {
    super();
    this._name = name;
    this._staff = staff;
  }
}
  1. _name 필드가 두 클래스에서 동일한 역할로 사용되므로 상위 클래스 Party로 올린다:
class Party {
  constructor(name) {
    this._name = name;
  }

  get name() {
    return this._name;
  }
}
  1. 하위 클래스들은 super(name) 호출로 필드를 초기화한다:
class Employee extends Party {
  constructor(name, id, monthlyCost) {
    super(name);
    this._id = id;
    this._monthlyCost = monthlyCost;
  }
}

class Department extends Party {
  constructor(name, staff) {
    super(name);
    this._staff = staff;
  }
}
  1. _name 필드가 하위 클래스에서 제거되었으므로, 중복이 사라지고 관련 메서드(get name() 등)도 Party에서 재사용 가능해진다.

 

생성자 본문 올리기

배경

하위 클래스의 생성자들이 공통적인 초기화 코드를 포함하고 있다면, 이를 상위 클래스의 생성자로 옮기는 것이 좋다.
이렇게 하면 중복을 제거하고, 하위 클래스는 고유한 초기화만 담당할 수 있어 더 명확한 역할 분리가 가능하다.

단, 생성자는 일반 메서드와 달리 super() 호출이 필요하고 순서 제약이 있기 때문에, 리팩터링 시 주의가 필요하다.

절차

  1. 상위 클래스 생성자 정의
    상위 클래스에 생성자가 없다면 먼저 생성자를 정의한다.
  2. 공통 코드 식별
    하위 클래스들의 생성자에서 중복되는 초기화 코드를 확인한다.
  3. 슬라이드 구문(Slide Statements)
    하위 클래스의 공통 코드를 super() 호출 직후로 이동시켜 실행 순서를 맞춘다.
  4. 상위 클래스 생성자로 이동
    공통 코드를 상위 클래스의 생성자로 이동하고, 필요한 생성자 인자도 함께 추가한다.
  5. 하위 클래스 생성자에서 공통 코드 제거
    하위 클래스 생성자에서 해당 코드를 삭제하고, 상위 생성자로 인자를 넘겨준다.
  6. 테스트
    모든 기능이 정상적으로 동작하는지 테스트한다.
  7. (선택)
    공통 코드가 생성자 중간 또는 끝부분에 있는 경우, Extract Function과 Pull Up Method를 조합해 리팩터링한다.

예시

리팩터링 전

class Employee extends Party {
  constructor(name, id, monthlyCost) {
    super();
    this._name = name;
    this._id = id;
    this._monthlyCost = monthlyCost;
  }
}

class Department extends Party {
  constructor(name, staff) {
    super();
    this._name = name;
    this._staff = staff;
  }
}

두 클래스 모두 this._name = name이라는 공통 코드가 존재한다.

리팩터링 절차

  1. Employee에서 _name 할당을 super() 바로 다음으로 이동:
constructor(name, id, monthlyCost) {
  super();
  this._name = name;
  this._id = id;
  this._monthlyCost = monthlyCost;
}
  1. _name 필드를 상위 클래스 Party로 이동:
class Party {
  constructor(name) {
    this._name = name;
  }
}
  1. 하위 클래스에서 super(name)으로 변경하고 중복 제거:
class Employee extends Party {
  constructor(name, id, monthlyCost) {
    super(name);
    this._id = id;
    this._monthlyCost = monthlyCost;
  }
}

class Department extends Party {
  constructor(name, staff) {
    super(name);
    this._staff = staff;
  }
}

예외적인 상황: 공통 코드가 생성자 끝에 있을 경우

아래처럼 공통 동작이 중간 이후에 위치할 경우에는 메서드를 추출한 뒤 올리는 방식으로 처리한다:

class Manager extends Employee {
  constructor(name, grade) {
    super(name);
    this._grade = grade;
    if (this.isPrivileged) this.assignCar();  // 공통 코드
  }
}
  1. assignCar() 조건문을 메서드로 추출:
finishConstruction() {
  if (this.isPrivileged) this.assignCar();
}
  1. 상위 클래스 Employee로 메서드 올리기:
class Employee {
  finishConstruction() {
    if (this.isPrivileged) this.assignCar();
  }
}

메서드 또는 필드 내리기

배경

상위 클래스에 정의된 필드, 메서드가 일부 하위 클래스에서만 사용될 경우, 그 필드, 메서드는 상위 클래스에 두기에 적절하지 않다.
이런 상황에서는 해당 필드 또는 메서드를 해당 하위 클래스로 이동(Push Down) 함으로써 클래스 구조를 명확하게 만들 수 있다.
이는 불필요한 일반화 제거와 책임 분산에 도움이 된다.

절차

  1. 사용 범위 확인
    해당 메서드 또는 필드가 상위 클래스의 모든 하위 클래스에서 사용되는지, 일부만 사용하는지 확인한다.
  2. 메서드, 필드 복사
    메서드 또는 메서드를 사용 중인 하위 클래스들에 복사한다.
  3. 상위 클래스에서 메서드, 필드 제거
    상위 클래스의 원본 메서드 또는 필드를 삭제한다.
  4. 사용하지 않는 하위 클래스에서도 제거
    메서드, 필드를 사용하지 않는 하위 클래스에는 복사하지 않는다.
  5. 테스트
    모든 관련 기능이 정상 동작하는지 확인한다.

타입 코드를 서브클래스로 바꾸기

배경

어떤 클래스가 type과 같은 필드를 사용하여 여러 종류의 동작을 구분하고 있다면,
그 구분은 서브클래스를 통해 더 명확하고 객체지향적으로 표현할 수 있다.
특히, 타입 코드에 따라 조건문(if/switch) 으로 분기되는 코드가 많아질수록 유지보수성이 떨어진다.

이런 경우, 타입 코드를 서브클래스로 바꾸면 조건문 없이 다형성(polymorphism) 으로 기능을 분리할 수 있어
코드를 더 명확하고 확장 가능하게 만들 수 있다.

절차

  1. 타입 코드 캡슐화
    타입 필드를 접근자(getter)로 감싼다 (Encapsulate Variable).
  2. 서브클래스 생성
    타입 코드의 각 값을 대표하는 서브클래스를 만든다. 각 서브클래스는 타입 값을 반환하는 접근자를 오버라이드한다.
  3. 팩토리 함수 생성
    타입 값에 따라 적절한 서브클래스를 생성하는 팩토리 함수를 만든다 (Replace Constructor with Factory Function).
  4. 점진적 전환 및 테스트
    하나씩 서브클래스를 생성하고, 팩토리 함수에 타입 분기 로직을 추가한다. 각 변경 후 테스트를 수행한다.
  5. 기존 타입 코드 제거
    서브클래스로 완전히 대체되면, 원래의 타입 필드 및 관련 조건문을 제거한다.
  6. 다형성 적용
    조건문을 Replace Conditional with Polymorphism 으로 교체하고, 서브클래스에 각각의 동작을 구현한다.

예시

리팩터링 전

class Employee {
  constructor(name, type) {
    this._name = name;
    this._type = type;
  }

  toString() {
    return `${this._name} (${this._type})`;
  }
}

type 값에 따라 서로 다른 동작을 하도록 분기하는 코드가 있다고 가정하자.

1. 타입 코드 캡슐화

get type() {
  return this._type;
}

2. 서브클래스 생성

class Engineer extends Employee {
  get type() { return "engineer"; }
}

class Manager extends Employee {
  get type() { return "manager"; }
}

class Salesman extends Employee {
  get type() { return "salesman"; }
}

3. 팩토리 함수 생성

function createEmployee(name, type) {
  switch (type) {
    case "engineer": return new Engineer(name);
    case "manager": return new Manager(name);
    case "salesman": return new Salesman(name);
    default: throw new Error(`Unknown type: ${type}`);
  }
}

4. 타입 기반 조건문 제거

// 기존: employee.type === 'manager' ? ...
// 리팩터링 후: 다형성을 사용하여 서브클래스에 위임

5. 필요 시 타입 필드 완전 제거

// this._type 제거
// type() 접근자는 서브클래스에서만 유지

서브 클래스 제거하기

배경

상속은 데이터 구조와 동작의 변형을 명확히 표현할 수 있는 강력한 도구다. 하지만 시간이 지나면서 다음과 같은 문제가 생길 수 있다:

  • 서브 클래스가 거의 아무 일도 하지 않거나,
  • 초기엔 의미 있었지만 더 이상 차별화된 기능이나 속성을 갖지 않을 때,
  • 혹은 과거의 과도한 일반화로 인해 오히려 구조가 복잡해졌을 때.

이럴 땐 상속을 유지하는 것이 오히려 코드를 이해하기 어렵게 만들 수 있으므로, 서브 클래스를 제거하고 필드로 대체하는 것이 좋다.

절차

  1. 생성자 → 팩토리 함수로 대체
    각 서브 클래스의 생성자 호출을 팩토리 함수로 감싼다 (Replace Constructor with Factory Function).
  2. 객체 생성 분기 로직 캡슐화
    팩토리 함수 내에 타입 분기(switch/case)를 사용하여 어떤 객체를 생성할지 결정하도록 만든다.
  3. 타입 판별 로직 캡슐화
    instanceof 또는 서브 클래스 타입을 검사하는 코드가 있다면, 이를 메서드로 추출하고 슈퍼클래스로 이동시킨다.
  4. 타입을 나타내는 필드 추가
    서브 클래스 간의 차이를 나타내는 필드를 슈퍼클래스에 추가한다.
  5. 서브 클래스 동작을 슈퍼클래스로 이동
    각 서브 클래스의 오버라이딩된 동작을 슈퍼클래스에 병합하고, 조건문 또는 필드 값 기반으로 동작하도록 수정한다.
  6. 서브 클래스 제거 및 테스트
    모든 기능이 정상 동작함을 확인한 뒤, 서브 클래스를 삭제한다.

예시

리팩터링 전

class Person {
  constructor(name) {
    this._name = name;
  }

  get genderCode() {
    return "X";
  }
}

class Male extends Person {
  get genderCode() {
    return "M";
  }
}

class Female extends Person {
  get genderCode() {
    return "F";
  }
}

1. 팩토리 함수 도입

function createPerson(record) {
  switch (record.gender) {
    case 'M': return new Male(record.name);
    case 'F': return new Female(record.name);
    default:  return new Person(record.name);
  }
}

2. instanceof 검사 제거

// Before
const numberOfMales = people.filter(p => p instanceof Male).length;

// After
const numberOfMales = people.filter(p => p.isMale).length;

class Person {
  get isMale() {
    return this instanceof Male;
  }
}

3. 타입 필드 추가 및 조건 기반 동작으로 대체

class Person {
  constructor(name, genderCode = "X") {
    this._name = name;
    this._genderCode = genderCode;
  }

  get genderCode() {
    return this._genderCode;
  }

  get isMale() {
    return this._genderCode === "M";
  }
}

4. 팩토리 함수에서 서브 클래스 대신 슈퍼클래스 생성

function createPerson(record) {
  return new Person(record.name, record.gender);
}

5. 서브 클래스 제거

Male, Female 클래스는 더 이상 필요하지 않으므로 삭제한다.

슈퍼 클래스 추출하기

배경

두 개 이상의 클래스가 공통된 필드나 메서드를 가지고 있다면,
이 중복 코드를 새로운 상위 클래스(슈퍼 클래스) 로 옮김으로써 중복을 제거하고 설계를 단순화할 수 있다.

이 기법은 코드 재사용을 가능하게 하고, 공통 인터페이스를 제공함으로써 다형성 활용도 가능하게 만든다.
상속 구조를 미리 설계하지 않았더라도, 프로그램이 진화하면서 자연스럽게 생성된 유사한 클래스들을 통합하는 데 효과적이다.

절차

  1. 공통 요소 식별
    여러 클래스에 중복된 필드나 메서드, 생성자 코드가 있는지 확인한다.
  2. 새 슈퍼 클래스 생성
    비어 있는 슈퍼 클래스를 만들고, 기존 클래스들이 이를 상속하도록 변경한다.
  3. 필드, 메서드, 생성자 본문 올리기
    Pull Up Field, Pull Up Method, Pull Up Constructor Body 등의 기법을 사용해 공통 요소를 슈퍼 클래스로 옮긴다.
  4. 중복 제거
    기존 클래스에서 슈퍼 클래스로 이동한 코드들을 삭제한다.
  5. 클라이언트 코드 점검 및 테스트
    기존 클래스들을 사용하는 클라이언트 코드가 슈퍼 클래스의 인터페이스로도 작동 가능한지 확인하고 테스트한다.

예시

리팩터링 전

class Employee {
  constructor(name, id, monthlyCost) {
    this._name = name;
    this._id = id;
    this._monthlyCost = monthlyCost;
  }

  get name() { return this._name; }
  get id() { return this._id; }
  get monthlyCost() { return this._monthlyCost; }
  get annualCost() { return this.monthlyCost * 12; }
}

class Department {
  constructor(name, staff) {
    this._name = name;
    this._staff = staff;
  }

  get name() { return this._name; }
  get staff() { return this._staff.slice(); }
  get monthlyCost() {
    return this.staff.reduce((sum, e) => sum + e.monthlyCost, 0);
  }
  get annualCost() {
    return this.monthlyCost * 12;
  }
}

1. 공통 요소 식별

  • _name, get name(), get annualCost()는 두 클래스에 공통됨.
  • monthlyCost는 의미는 같지만 구현이 다름 → 이름 통일 필요.

2. 슈퍼 클래스 생성 및 상속 구조 변경

class Party {}

class Employee extends Party { ... }
class Department extends Party { ... }

3. 생성자 및 필드 올리기

class Party {
  constructor(name) {
    this._name = name;
  }

  get name() { return this._name; }
}

각 서브 클래스 생성자는 super(name)을 호출하도록 변경:

class Employee extends Party {
  constructor(name, id, monthlyCost) {
    super(name);
    this._id = id;
    this._monthlyCost = monthlyCost;
  }
  ...
}
class Department extends Party {
  constructor(name, staff) {
    super(name);
    this._staff = staff;
  }
  ...
}

4. 메서드 이름 통일 및 올리기

monthlyCost라는 이름으로 통일한 후, annualCost를 슈퍼 클래스로 올림:

class Party {
  ...
  get annualCost() {
    return this.monthlyCost * 12;
  }
}

서브클래스를 위임으로 바꾸기

배경

상속은 객체지향의 핵심 개념 중 하나지만, 다음과 같은 문제가 있을 수 있다:

  • 하나의 클래스만 상속 가능하기 때문에 여러 축(axis)으로 확장해야 할 경우 유연하지 않다.
  • 서브클래스가 많아질수록 슈퍼클래스를 변경할 때 파급효과가 커진다.
  • 서브클래스 간 중복이 발생하거나, 조건문을 피하기 위해 억지로 분리한 서브클래스가 생기기도 한다.

이럴 땐 상속을 제거하고, 차별화된 동작을 위임 객체(delegate) 로 분리하면 더 유연한 구조를 만들 수 있다.
위임은 런타임에 유연하게 교체 가능하고, 여러 개를 조합할 수도 있다.

절차

  1. 서브클래스 생성자 → 팩토리 함수로 변경
    서브클래스 인스턴스 생성을 캡슐화하기 위해 팩토리 함수로 감싼다 (Replace Constructor with Factory Function).
  2. 위임 클래스 생성
    각 서브클래스의 고유 동작을 담당할 위임 클래스(delegate) 를 만든다. 서브클래스에 있던 데이터와 동작 일부를 이동시킨다.
  3. 슈퍼클래스에 delegate 필드 추가
    위임 객체를 참조할 수 있도록 슈퍼클래스에 필드를 추가한다.
  4. 메서드 위임 처리
    서브클래스에서 오버라이드하던 메서드를 위임 객체로 옮기고, 슈퍼클래스에서 해당 메서드를 delegate에 위임한다.
  5. 서브클래스 제거 및 팩토리 함수 수정
    위임으로 대체된 서브클래스를 삭제하고, 팩토리 함수에서 적절한 delegate를 생성해 슈퍼클래스에 주입한다.
  6. 테스트
    모든 변경 사항이 기존 기능을 손상하지 않는지 확인한다.

예시

리팩터링 전

class Booking {
  constructor(show, date) {
    this._show = show;
    this._date = date;
  }

  get hasTalkback() {
    return this._show.talkback && !this.isPeakDay;
  }

  get basePrice() {
    let result = this._show.price;
    if (this.isPeakDay) result += result * 0.15;
    return result;
  }
}

class PremiumBooking extends Booking {
  constructor(show, date, extras) {
    super(show, date);
    this._extras = extras;
  }

  get hasTalkback() {
    return this._show.talkback;
  }

  get basePrice() {
    return super.basePrice + this._extras.premiumFee;
  }

  get hasDinner() {
    return this._extras.dinner && !this.isPeakDay;
  }
}

리팩터링 후

  1. delegate 클래스 생성
class PremiumDelegate {
  constructor(hostBooking, extras) {
    this._host = hostBooking;
    this._extras = extras;
  }

  hasTalkback() {
    return this._host._show.talkback;
  }

  basePrice(base) {
    return base + this._extras.premiumFee;
  }

  hasDinner() {
    return this._extras.dinner && !this._host.isPeakDay;
  }
}
  1. Booking 클래스에서 delegate 사용
class Booking {
  constructor(show, date) {
    this._show = show;
    this._date = date;
  }

  _bePremium(extras) {
    this._premiumDelegate = new PremiumDelegate(this, extras);
  }

  get hasTalkback() {
    return this._premiumDelegate
      ? this._premiumDelegate.hasTalkback()
      : this._show.talkback && !this.isPeakDay;
  }

  get basePrice() {
    const base = this._show.price + (this.isPeakDay ? this._show.price * 0.15 : 0);
    return this._premiumDelegate
      ? this._premiumDelegate.basePrice(base)
      : base;
  }

  get hasDinner() {
    return this._premiumDelegate
      ? this._premiumDelegate.hasDinner()
      : null;
  }
}
  1. 팩토리 함수로 객체 생성
function createBooking(show, date) {
  return new Booking(show, date);
}

function createPremiumBooking(show, date, extras) {
  const booking = new Booking(show, date);
  booking._bePremium(extras);
  return booking;
}

슈퍼 클래스를 위임으로 바꾸기

배경

상속은 재사용과 기능 확장의 대표적 수단이지만, 다음과 같은 한계가 있다:

  • 상속 구조는 클래스 간 강한 결합을 만든다. 슈퍼클래스를 변경하면 서브클래스가 깨질 위험이 있다.
  • 클래스는 하나만 상속할 수 있으므로, 다중 기능이 필요한 경우 구조가 복잡해질 수 있다.
  • 상속된 기능 중 일부만 필요할 때도 전체 슈퍼클래스를 상속받아야 하므로 불필요한 책임이 생긴다.

이런 상황에서는 상속을 제거하고, 슈퍼클래스를 독립 객체로 분리한 뒤 위임(delegate) 하는 것이 더 유연한 설계를 가능하게 한다.

절차

  1. 슈퍼클래스를 새 위임 클래스로 복사
    기존 슈퍼클래스의 필드와 메서드를 새로운 클래스(delegate)로 복사한다.
  2. 위임 객체를 서브클래스에 필드로 추가
    서브클래스가 위임 객체를 참조할 수 있도록 필드를 추가한다.
  3. 생성자에서 위임 객체 생성
    서브클래스 생성자에서 delegate 객체를 생성하고 필드에 저장한다.
  4. 기존 슈퍼클래스의 기능을 delegate로 위임
    서브클래스의 각 메서드에서 delegate의 메서드를 호출하도록 변경한다.
  5. 슈퍼클래스 상속 제거
    서브클래스가 더 이상 상속하지 않도록 extends 제거.
  6. 테스트 및 리팩터링 마무리
    변경된 동작이 기존과 동일한지 테스트하고, 불필요한 코드를 정리한다.

예시

리팩터링 전

class Person {
  constructor(name) {
    this._name = name;
  }

  get name() {
    return this._name;
  }

  greeting() {
    return `Hi, I'm ${this.name}`;
  }
}

class Manager extends Person {
  constructor(name, department) {
    super(name);
    this._department = department;
  }

  get department() {
    return this._department;
  }

  greeting() {
    return `${super.greeting()} from ${this.department} department.`;
  }
}

리팩터링 후

  1. Person → PersonDelegate로 분리
class PersonDelegate {
  constructor(name) {
    this._name = name;
  }

  get name() {
    return this._name;
  }

  greeting() {
    return `Hi, I'm ${this.name}`;
  }
}
  1. Manager에서 상속 제거 및 위임 추가
class Manager {
  constructor(name, department) {
    this._person = new PersonDelegate(name);
    this._department = department;
  }

  get name() {
    return this._person.name;
  }

  get department() {
    return this._department;
  }

  greeting() {
    return `${this._person.greeting()} from ${this.department} department.`;
  }
}

'Programming > Refactoring' 카테고리의 다른 글

API 리팩터링  (1) 2025.06.04
조건부 로직 간소화  (0) 2025.05.19
데이터 조직화  (0) 2025.05.15
기능 이동  (0) 2025.05.08
캡슐화  (0) 2025.04.24
'Programming/Refactoring' 카테고리의 다른 글
  • API 리팩터링
  • 조건부 로직 간소화
  • 데이터 조직화
  • 기능 이동
Seung-o
Seung-o
공부한 것들을 정리하는 개발 블로그입니다.
  • Seung-o
    조그만 사람의 개발 주머니
    Seung-o
  • 전체
    오늘
    어제
    • 분류 전체보기 (54)
      • Database (20)
        • Real MySQL (4)
        • High Performance MySQL (14)
      • Programming (29)
        • Protocol (2)
        • Designing Data-Intensive Ap.. (5)
        • Unit Testing (4)
        • Refactoring (13)
        • Langchain (4)
      • Etc (5)
        • Thought (2)
        • Git (1)
        • Jira (1)
        • Experience (1)
  • 블로그 메뉴

    • 홈
    • 태그
  • 링크

    • Github
  • 인기 글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Seung-o
상속 다루기
상단으로

티스토리툴바