[오브젝트] 챕터 10: 상속과 코드 재사용

✏️, 💡,❓ 해당 이모지는 저의 생각임을 나타냅니다.

 

객체지향 프로그래밍은 코드를 재사용하기 용이하다는 장점이 있다. 코드를 재사용하려는 동기 이면에는 중복된 코드를 제거하려는 욕망이 있다. 이번 장에서는 상속에 대해 알아본다. (전체 코드)

 

01 상속과 중복 코드

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

 

DRY 원칙

프로그램의 본질은 비즈니스와 관련된 지식을 코드로 변환하는 것이다. 안타깝게도 이 지식은 항상 변하며 그에 맞춰 코드 역시 변경해야 한다.

중복 코드는 코드를 수정하는 데 필요한 노력을 몇 배로 증가시킨다. 

 

중복을 판단하는 기준은 변경이다. 요구사항이 변경됐을 때 두 코드를 함께 수정해야 한다면 이 코드는 중복이다. 

신뢰할 수 있고 수정하기 쉬운 소프트웨어를 만드는 효과적인 방법은 중복을 제거하는 것이며, DRY(Don't Repeat Yourself) 원칙을 따라야 한다.

 

중복과 변경

중복 코드 문제점을 이해하기 위해 한달에 한번 가입자별로 전화 요금을 계산하는 애플리케이션을 개발한다. (코드)

 

처음에는 전화라는 클래스를 만들었다가, 새로운 요구사항인 밤에 전화를 할 경우 할인이 된다를 계산하기 위해 밤 전화 클래스를 만들었다. 그리고 세금 계산이라는 요구사항이 들어왔을 경우 두개의 클래스를 변경한다. 여기서 우리는 중복은 중복을 부른다는 것을 알 수 있다.

 

두 클래스 사이의 중복을 제거하는 한 가지 방법은 클래스를 하나로 합치는 것이다. 요금제를 구분하는 타입 코드를 사용할 수 있다.

그러나 타입 코드는 낮은 응집도와 높은 결합도를 가진다. (코드)

 

또 다른 방법은 상속을 이용하는 것이다. (코드)

그러나 상속은 결합도를 높인다. 오버라이딩 하는 메서드가 있는데, '세금을 부과하는 요구사항'이 추가될 경우 부모 클래스와 자식 클래스 둘 다 변경이 필요하다. * super 클래스를 사용하면 두 클래스는 강하게 결합되므로 super 호출을 제거할 수 있는 방법을 찾아라.

 

02 취약한 기반 클래스 문제

부모 클래스의 작은 변경에도 자식 클래스는 컴파일 오류와 실행 에러라는 고통에 시달려야 할 수도 있다. 이런 현상을 취약한 기반 클래스 문제라고 부른다. 이는 상속이란 문맥 안에서 결합도가 초래하는 문제점을 가리키는 용어이다. 우리는 상속 관계를 추가할수록 전체 시스템의 결합도가 높아진다는 사실을 알아야 한다.

 

불필요한 인터페이스 상속 문제

자바 초기 버전에서 상속을 잘못한 사례를 볼 수 있다.

그림 10.1

이렇게 상속받게 되면 Vector의 add, get을 Stack에서 쓸 수 있게 되기 때문에 Stack 규칙을 위반하게 된다.

-> 이렇게 상속 받은 부모 클래스 메서드가 자식 클래스의 내부 구조에 대한 규칙을 깨트릴 수 있다.

 

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

결합도란 다른 대상에 대해 알고 있는 지식의 양이다. 상속은 기본적으로 부모 클래스의 구현을 재사용하기 때문에 자식 클래스가 부모 클래스에 대해 알도록 강요한다.

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

 

03 Phone 다시 살펴보기

다시 예제로 돌아와서 상속으로 인한 피해를 최소화하는 방법을 찾아보자.

 

추상화에 의존하자

가장 일반적인 해결 방법은 자식 클래스가 부모 클래스의 구현이 아닌 추상화에 의존하도록 만드는 것이다. 아래는 상속을 도입할 때 따르는 두 가지 원칙이다.

- 메서드가 유사하게 보인다면 차이점을 메서드로 추출하라. (코드)

- 부모 클래스의 코드를 하위로 내리지 말고 자식 클래스의 코드를 상위로 올려라. (코드)

 

추상화가 핵심이다

메서드를 추출하고, 공통 코드를 이동시킨다면 각 클래스는 서로 다른 변경의 이유를 가진다. 그리고 추상화에 의존하게 되면 부모 클래스의 내부 구현이 변경되어도 자식 클래스는 영향을 받지 않는다.

 

상속으로 인한 클래스 결합을 피하는 방법은 없다. 메서드 구현에 대한 결합은 추상 메서드를 추가함으로써 완화할 수 있지만 인스턴스 변수에 대한 잠재적인 결합을 제거하는 방법은 없다.

 

04 차이에 의한 프로그래밍

상속이 강력한 이유는 익숙한 개념을 이용해서 새로운 개념을 쉽게 추가할 수 있기 때문이다.

이처럼 기존 코드와 다른 부분만을 추가함으로써 애플리케이션 기능을 확장하는 방법을 차이에 의한 프로그래밍이라고 한다. 

 

코드를 재사용하는 것은 단순히 문자를 타이핑하는 수고를 덜어주는 수준의 문제가 아니다. 재사용 가능한 코드란 심각한 버그가 존재하지 않는 코드다.

 

상속은 강력한 도구로 코드의 양을 최소화할 수 있지만, 맹목적인 상속 사용은 위험하다. 정말로 필요한 경우에만 상속을 사용하라. 객체지향에 능숙한 개발자들은 상속의 단점을 피하면서 코드를 재사용할 수 있는 더 좋은 방법을 알고 있는데, 바로 합성이다.