서적/Object

10장 상속과 코드 재사용

Mo_bi!e 2026. 3. 8. 11:45

개요

  • 객체지향 프로그램 장점은 코드 재사용에 용이
    • 전통적인 프로그래밍의 재사용 방법은 복사한 후 수정하기
  • 재사용 관점에서 상속이란 : 클래스 안에 정의된 인스턴스 변수와 메서드를 자동으로 새로운 클래스에 추가하는 구현 기법
  • 합성 : '새로운 클래스의 인스턴스 안'에 '기존 클래스의 인스턴스'를 포함시키는 방법

1. 상속과 중복코드

  • 중복코드는 사람들의 마음속에 의심과 불신의 씨앗을 뿌린다.

DRY 원칙

  • 중복코드는 변경을 방해한다. 이것이 중복코드를 제거해야하는 이유
    • 프로그램의 본직은 비즈니스 지식을 코드로 변경인데, 지식은 항상 변한다 -> 코드도 변한다
  • 중복코드의 가장큰 문제는 코드 수정에 노력을 몇배로 증가시킨다.
    • 모든코드 수정 + 개별적 테스트로 동일한 결과확인 필요
  • 중복 여부 판단 기준은 '변경'
    • 요구 사항 변경 시 두 코드 함께 수정한다면 코드 중복
  • Don't Repeat Yourself : 반복하지 마라
    • 동일한 지식을 중복하지 말라
    • 단일 지점 제어

중복과 변경 (과제 1)

  • 기존 가입자별로 전화 요금 계산 어플리케이션
    • 여기에 추가로 '심야요금 할인제' 추가시 중복으로 구현
  • 문제점
    1. 세금계산 로직 추가 시 Phone, NightlyDiscountPhone 모두 함께 수정
    2. 하지만 서로 다르게 수정하기가 쉽다. (plus 대신에 minus 메서드 호출할수도)
    3. 중복코든는 새로운 중복 코드를 부른다.
    • 코드의 일관성이 무너질 위함이 상존 + 코드 변경속도 점점 느려진다.
    • 그러므로 DRY 하게 만들기 위해 노력하라
  • 타입 코드 사용하기
    • 중복 코드 제거하기 위해 클래스 합치는 방법도 있다.
    • 하지만 타입 코드는 낮은 응집도와 높은 결합도 문제가 있다
    • OOP 에는 상속이 그 해결 방법이다.

상속을 이용해서 중복 코드 제거하기

  • 코드를 복사하지 말고 상속을 이용해 코드를 재사용해라
    • 그런데 상속으로 구현 시 '개발자의 의도와 가정'을 이해하기 전에는 코드를 이해하기 어렵다
  • 상속을 염두에 두지 않고 설계되지 않은 클래스를 상속으로 재사용하면 어렵다
    • 코드 이해가 어렵고, 직관에도 어긋난다
    • 그 결과 요구사항과 구현 사이의 차이크 크게 된다
  • 깊고 깊은 상속 계층의 계단을 하나씩 내려 올 때 마다 이해하기 어려운 가정과 마주치는것은 어렵다.

상속을 위한 경고 1
자식 클래스의 메서드 안에서 super 참조를 이용해 부모 클래스의 메서드를 직접 호출할 경우 두 클래스는 강하게 결합된다
super 호출을 제거할 수 있는 방법을 찾아 결합도를 제거하라

  • 자식클래스가 부모 클래스의 변경에 취약해지는 현상을 '취약한 기반 클래스 문제' 라고 한다

2. 취약한 기반 클래스 문제 (Fragile Base Clasee Problem)

  • 상속은 결합도를 높이는데, 자식클래스는 부모의 불필요한 세부사항에 엮이게 된다.
    • 캡술화를 약화시킴
      • 파급효과 제어와 내부 변경이 어려워짐
  • 상속관계가 추가할수록 전체 시스템의 결합도가 높아진다
    • 장점은 자식 클래스를 점진적으로 추가해서 기능 확장
    • 단점은 높은 결합도로 부모 클래스를 점진적으로 개선은 어렵다 + 모든 클래스 동시 수정과 테스트

불필요한 인터페이스 상속문제 (과제 2)

  • 자바 초기 버전 불필요한 인터페이스 상속의 대표적 사례인 java.util.Stack과 java.util.Properties

java.util.Stack

  • 자바 초기 컬렉션 프레임웍 개발자들은 요소의 추가, 삭제 오퍼레이션을 제공하는 Vector 재사용 위해 Stack 을 Vetcor의 자식클래스로 구현함
    • 그 결과 Verctor의 퍼블릭 인터페이스도 합쳐진다.
    • stack 규칙을 위반하게 된다
  • 인터페이스 설계는 제대로 쓰기엔 쉽게, 엉터리로 쓰기엔 어렵게 만들어야한다

java.util.Properties

  • HashTable 상속받는데, 제네릭 도입 이전에 만들어 졌다
    • 컴파일러가 key, value가 String 여부 체크 방법이 없었다.
      • String 타입 이외의 키와 값을 Properties 에 저장할 수있었다.
  • 그 결과 String이 아닌경우 null 이 반환되었다.
  • OOP의 핵심은 협력인데, 단순히 재사용위해 불필요 오퍼레이션이 인터페이스에 스며들도록 하면 안된다.

상속을 위한 경고 2
상속받은 부모 클래스의 메서드가, 자식 클래스의 내부 구조에 대한 규칙을 깨트릴 수있다.

메서드 오버라이징의 오작용 문제

상속을 위한 경고 3
자식 클래스가 부모 클래스의 메서드를 오버라이딩할 경우
부모 클래스가 자신의 메서드를 사용하는 방법에 자식 클래스가 결합될 수있다.

부모 클래스와 자식 클래스의 동시 수정 문제

상속을 위한 경고 4
클래스를 상속하면 결합도로 인해
자식 클래스와 부모 클래스의 구현을 영원히 변경하지 않거나, 자식 클래스와 부모 클래스를 동시에 변경하거나
둘중 하나를 선택할 수 밖에 없다.

3. Phone 다시 살펴보기

  • 상속으로 인해 발생하는 취약한 기반 클래스 문제로부터 위험을 완하 시키는 방법은 '추상화'

추상화에 의존하자

  • 자식클래스가 부모클래스가 아닌 '추상화'에 의존하도록 만들기
    • 자식, 부모 모두 추상화에 의존

차이를 메서드로 추출하라

  • '변경하는 것으로부터 변경하지 않는것을 분리하라'
    • 우선 두 클래스의 메서드에서 다른 부분을 별도의 메서드로 추출한다.
      • 예) 요금 계산 로직이 서로 다르다

중복 코드를 부모 클래스로 올려라

  • 공통코드를 부모 클래스로 옮길 때 인스턴스 변수보다 메서드를 먼저 이동시키는 것이 편하다
    • 컴파일 에러로 자동으로 알 수있다.
  • 공통 코드를 추상메서드로 선언하고 자식클래스에서 오버라이딩 할 수있도록 protected를 이용한다

추상화가 핵심이다.

  • 이후 각 클래스는 서로 다른 변경의 이유를 가진다.
    • 세 클래스는 각각 하나의 변경 이유만 가진다. SRP 준수하므로 응집도가 높다
    • 부모 클래스 역시 자신의 내부에 구현된 추상메서드 호출하므로 추상화에 의존한다 -> DIP 준수
    • 새로운 요금제 추가가 쉽다 -> OCP 준수

의도를 드러내는 이름 선택하기

  • 좋은 상속게층을 구성하기 위해서는 상속계층안에 속한 클래스들이 구현이 아닌 추상화에 의존하게 이름을 드러낸다

세금 추가하기

  • 세금 관련 인스턴스 변수를 추가하면 자식클래스의 초기화 로직에도 영향을 미친다.
    • 하지만 인스턴스 초기화 로직을 변경하는것이, 두 클래스에 동일한 세금 계산 코드를 중복시키는 것 보다 현명하다

상속은 어떤 방식으로든 부모 클래스와 자식 클래스를 결합시킨다. 메서드 구현에 대한 결합은 추상 메서드 추가함으로서 어느 정도 완화할 수있지만, 인스턴스 변수에 대한 잠재적인 결합을 제거할 수있는 방법은 없다

4. 차이에 의한 프로그래밍 (Programming By Difference)

  • 상속이 강력한 이유는 익숙한 개념을 이용해서 새로운 개념을 쉽고 빠르게 추가가 가능하다
    • 기존 코드와 다른 부분만을 추가함으로써 앱의 기능을 확장하는 방법을 '차이에 의한 프로그래밍'이라 한다
  • 차이에 의한 프로그래밍 목표
    • 중복 코드 제거하고 코드 재사용
      • 중복 코드 제거와 코드 재사용은 동일한 행동을 가르키는 다른 단어
    • 프로그래밍 세계에서 중복코든느 악의 근원
  • OOP 세계에서 중복코드 제거하고 코드 재사용의 가장 유명한 방법은 상속이다
    • 코드를 컴파일 하면 무대 뒤에서 마범이 일어나 상속 관계로 연결된 코드들이 하나로 합쳐진다.
    • 상속을 사용하면 여러 클래스 사이에서 재사용 가능한 코드를 하나의 클래스 안으로 모을 수있다.
  • 상속은 새로운 기능을 추가하기 위해 직접 구현해야하는 코드의 양을 최소화 할 수있다.
  • 하지만 오용과 남용은 앱을 이해하고 확장하기 어렵기 만든다.
    • 더 좋은 방법 '합성'

'서적 > Object' 카테고리의 다른 글

11장 합성과 유연한 설계  (7) 2026.03.18
9장 유연한 설계  (6) 2026.03.04
6장 메시지와 인터페이스 / 8장 의존성 관리하기  (8) 2026.02.24
5장 책임 할당하기  (3) 2026.02.08
4장 설계품질과 트레이드 오프  (3) 2026.02.03