Book

[객체지향의 사실과 오해] 03 타입과 추상화

YATTA! 2024. 10. 1. 19:50

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

 

지하철은 점점 더 복잡한 미로로 변해가고 있다. 그럼에도 지하철을 큰 어려움 없이 이용할 수 있는 이유는 지하철 노선도가 있기 때문이다. 그리고 지하철 노선도는 유사한형태를 띠기 때문에 한 도시의 지하철 노선도를 이해하면 다른 도시의 노선도 역시 잘 이해할 수 있다.

 

해리 백(노선도 창조)은 지하철 노선도를그릴 때 지도가 당연히 가져가야한다고 생각되는 '정확성'을 버리고 그 '목적'에 집중했다. (지하철 노선도 추상화) 그리고 자신의 견해를 이렇게 설명했다. "지하철을 갈아탈 때 지형때문에 골치아플 일이 있을까요? 지형은 중요한 것이 아닙니다. 중요한 것은 연결, 즉 열차를 갈아타는 것입니다.

💡 특별히 프로그래밍에 해당하거나 지하철 노선도에 해당하는 것은 아닌 것 같다. 무언갈 만들어낼 때 항상 중요한 부분인 것 같다. 우리는 무언갈 하고 싶을 때 '본질'에 집중하고 나머지는 과감히 버릴 필요가 있다.

 

추상화를 통한 복잡성 극복

진정한 의미에서 추상화란 현실에서 출발하되 불필요한 부분을 도려내가면서 사물의 놀라운 본질을 드러나게 하는 과정이라고 할 수 있다. 추상화의 목적은 불필요한 부분을 무시함으로써 현실에 존재하는 복잡성을 극복하는 것이다.

 

추상화의 수준, 이익, 가치는 목적에 의존적이다. 리처드 파인만의 말처럼 "현상은 복잡하다. 법칙은 단순하다. 버릴 게 무엇인지 알아내라."

 

복잡성을 다루기 위해 추상화는 두 차원에서 이뤄진다.

1) 구체적인 사물의 공통점은 취하고 차이점은 버리는 일반화를 통해 단순하게 만드는 것이다.

2) 중요한 부분을 강조하기 위해 불필요한 세부 사항을 제거함으로써 단순하게 만드는 것이다.

=> 결국 목적은 복잡성을 이해하기 쉬운 수준으로 단순화하는 것임을 기억하라.

 

객체지향과 추상화

수많은 객체를 개별적인 단위로 취급하기엔 인간의 인지능력은 턱없이 부족하다. 따라서 사람들은 본능적으로 공통적인 특성을 기준으로 객체를 여러 그룹으로 묶어 단순화하려고 노력한다.

 

이처럼 공통점을기반으로객체들을 묶기 위한 그릇을 개념concept이라고 한다.  

개념을 이용하면 객체를 여러 그룹으로 분류classification할 수 있다.  (개념에 적합한 객체가 각 그룹에 포함되도록 분류)

그 개념 그룹의 일원이 될 때 객체를 그 개념의 인스턴스instance라고 한다.

개념을 통해 세상을 바라보면 세상을 엄청나게 단순화 할 수 있다.

 

분류는 객체지향의 가장 중요한 개념이다. 어떤 객체를 어떤 개념으로 분류할지가 객체지향의 품질을 결정한다.

객체는 소중하다. 따라서 소중한 객체를 안전하고 적절한 장소에 보관할 수 있도록 여러분의 인지능력을 발휘해 최대한 직관적으로 분류하라.

 

타입

❓ 90p~ 다시 읽어보면 좋을 것 같다.

타입은 개념이다. 타입의 정의는 개념과 완전히 동일하다. 

 

데이터 타입에 대해 이야기해보자.

첫째, 타입은 데이터가 어떻게 사용되느냐에 관한 것이다. 

숫자형 데이터 = 데이터를 더하거나 빼거나 곱하거나 나눌 수 있기 때문

문자형 데이터 = 두 데이터를 연결해 새로운 문자열을 만들 수 있기 때문

 

둘째, 타입에 속한 데이터를 메모리에 어떻게 표현하는지는 외부로부터 철저하게 감춰진다. (0과 1로 어떻게 표현될까?) 데이터 타입의 표현은 연산 작업을 수행하기에 가장 효과적인 형태가 선택되며, 개발자는 해당 데이터 타입의 표현 방식을 몰라도 데이터를 사용하는데 지장이 없다.

 

객체지향 프로그램을 작성할 때 우리는 객체를 일종의 데이터처럼 사용한다. (그렇다고 객체가 데이터인 것은 아니다.)

첫째, 객체가 어떤 타입에 속하는지를 결정하는 것은 객체가 수행하는 행동이다. 어떤 객체들이 동일한 행동을 수행할 수 있다면 그 객체들은 동일한 타입으로 분류될 수 있다.

💡 데이터 타입과 같다. 타입은 데이터가 어떻게 사용되느냐에 따라 나누어진다.

 

둘째, 객체의 내부적인 표현은 외부로부터 철저하게 감춰진다. 행동을 효과적으로 수행할 수만 있다면 내부 상태는 어떤 식으로 표현해도 무방하다.

 

위 조언들에 따라서 객체의 내부 표현 방식이 다르더라도, 어떤 객체들이 동일하게 행동한다면 그 객체들은 동일한 타입에 속한다. (동일 책임 동일 타입)

✏️ 사람 객체를 상속받아 숨쉬기를 오버라이딩 한 경우가 있을 수 있다. 숨 쉬는 방법은 모두 다 다를테지만 '행동'은 같기 때문에 해당 행동을 하는 객체는 다 같은 타입일 수 있다.

 

어떤 객체를 다른 객체와 동일한 타입으로 분류하는 기준은 무엇인가? 그 객체가 타입에 속한 다른 객체와 동일한 행동을 하기만 하면 된다. 어떤 데이터를 가지고 있는지는 우리의 관심사가 아니다.

타입이 데이터가 아니라 행동에 의해 결정된다는 것은 객체지향 패러다임을 특징 짓는 몇 가지 원리원칙에 의미를 부여한다.

 

1) 같은 타입에 속한 객체는 행동만 동일하면 서로 다른 데이터를 가질 수 있다. 동일 행동 = 동일 책임 = 동일한 메시지 수신을 의미한다. 하지만 메시지를 처리하는 방식은 다를 수도 있다. 이것은 다형성에 의미를 부여한다. 다형성이란 동일한 요청에 서로 다른 방식으로 응답할 수 있는 능력을 뜻한다. 결과적으로 다형적인 객체들은 동일한 타입에 속하게 된다.

 

2) 행동에 따라 객체를 분류하기 위해서는 내부적인 데이터보다 외부에 제공해야 하는 행동을 먼저 생각한다. 먼저 외부에 제공해야 하는 책임을 결정하고 데이터를 나중에 결정한 후, 외부 인터페이스 뒤로 캡슐화 해야한다. 책임-주도 설계(RDD)가 가능해진다. 데이터 주도 설계 단점을 개선할 수 있다.

💡 저번 스터디에서 어떻게 행동을 먼저 결정할 수 있을까에 대한 이야기를 했는데, 객체는 행동으로 분류된다라는 개념을 알고 있다면 좀 더 행동 중심적으로 생각하는 게 쉬워질 것 같다.

 

타입의 계층

앨리스에 보면 트럼프와 트럼프 인간(왕비, 왕자, 공주)이 있다. 트럼프는 트럼프 인간을 포괄하는 좀 더 일반적인 개념이다. 이 두 개념 사이의 관계를 일반화/특수화(generalization/specialization) 관계라고 한다. 

 

여기서 중요한 것은 객체지향에서 일반화/특수화 관계를 결정하는 것은 데이터가 아니라 행동이라는 것이다. 

행동의 관점에서 더 일반적인 타입은 무엇이고 더 특수한 타입이란 무엇인가?

일반적인 타입 = 특수한 타입이 가진 모든 행동들 중에서 일부 행동만을 가지는 타입

특수한 타입 = 일반적인 타입이 가진 모든 행동을 포함하지만 거기에 더해 자신만의 행동을 추가하는 타입

따라서 일반적인 타입은 특수한 타입보다 더 적은 수의 행동을 가지고, 특수한 타입은 일반적인 타입보다 더 많은 수의 행동을 가진다.

✏️ 쉽게 생각하면 수학의 집합을 생각하면 된다. 일반적 타입의 행동은 모두가 포함하는 공통된 부분이다. 행동으로 보면 일반적 타입의 행동 ⊂ 특수한 타입의 행동이 된다. 대신 일반적 타입은 일반적인 개념이기 때문에 더 큰 크기의 집합을 가진다.

 

일반화/특수화 관계는 일반적인 한 타입과 좀 더 특수한 타입간의 관계이다. 이때 좀 더 일반적 타입을 슈퍼타입이라고 하고, 특수한 타입을 서브타입이라고 한다.

일반적으로 서브타입은 슈퍼타입의 행위와 호환되기 때문에 서브타입은 슈퍼타입을 대체할 수 있어야 한다.

 

이런 일반화는 추상화를 위한 도구이다. (불필요한 특성 배제하고 일반화) 객체지향 패러다임을 통해 세상을 바라보는 대부분의 경우에 분류와 일반화/특수화 기법을 동시에 적용하게 된다.

 

정적 모델

객체지향 프로그래밍 언어에서 정적인 모델은 클래스를 이용해 구현된다. 따라서 타입을 구현하는 가장 보편적 방법은 클래스를 이용하는 것이다. 클래스와 타입은 동일한 것이 아니다. 타입은 객체를 분류하기 위해 사용하는 개념이다. 클래스는 단지 타입을 구현할 수 있는 여러 구현 메커니즘 중 하나이다. 클래스는 타입 구현 외에도 코드를 재사용하는 용도로 사용되기 때문에 클래스와 타입을 동일시하는 것은 수많은 오해를 불러일으킨다.

지금은 객체를 분류하는 기준은 타입이며, 타입을 나누는 기준은 객체가 수행하는 행동이라는 사실만을 기억해라.

결국 객체지향에서 중요한 것은 동적으로 변하는 객체의 상태와 상태를 변경하는 행위다.

 


 

아직 '타입'이라는 것이 조금 애매모호하다. 101p ~ 103p를 다시 읽어보면 좋을 것 같다.

 

우리는 세상을 볼 때 자연스럽게 추상화를 해서 본다. 그럴 때 우리가 각각 객체들을 구분하는 것은 '행동'이라는 사실을 아는 것이 중요한 것 같다.