3장. 타입과 추상화
추상화의 대표적인 예시는 '지하철 노선도'를 보면 알 수 있다.
지하철 노선도의 핵심은 지도가 당연히 가져야 한다고 생각되는 '정확성'을 버리고 그 '목적'에 집중하였다.
역과 역 사이에 연결성을 얼마나 직관적으로 표현했느냐가 핵심이다.
사람들이 지하철을 갈아 탈 때 지형은 중요한 것이 아니다. 중요한 것은 연결, 즉 열차를 갈아타는 것이다.
객체지향의 핵심 중 추상화를 설명할 때 필요한 것은 강조하고, 불필요한 것은 버리는 것이라고 하는데 이것을 의미하는 것 같음!
추상화를 통한 복잡성 극복
추상화의 목적은 불필요한 부분을 무시함으로써 현실에 존재하는 복잡성을 극복하는 것이다.
추상화는 복잡한 현실을 단순화하기 위해 사용하는 인간의 기본적인 인지 수단
훌륭한 추상화는 목적에 부합하는 것
이 책에서는 추상화를 다음과 같이 정의한다.
추상화어떤 양상, 세부 사항, 구조를 좀 더 명확하게 이해하기 위해 특정 절차나 물체를 의도적으로 생략하거나 감춤으로써 복잡도를 극복하는 방법이다.
복잡성을 다루기 위해 추상화는 두 차원에서 이뤄진다.
첫 번째 차원은 구체적인 사물들 간의 공통점을 취하고 차이점은 버리는 일반화를 통해 단순하게 만드는 것이다.
두 번째 차원은 중요한 부분을 강조하기 위해 불필요한 세부 사항을 제거함으로써 단순하게 만드는 것이다.
모든 경우에 추상화의 목적은 복잡성을 이해하기 쉬운 수준으로 단순화하는 것이라는 점을 기억하자.
객체지향과 추상화
정원사, 병사, 신하, 왕자와 공부, 하객으로 참석한 왕과 왕비들, 하트 잭, 하트 왕과 하트 여왕이 존재하는 세상을 생각해보자.
위의 나열한 것들은 모두 '트럼프'라는 하나의 개념으로 단순화해서 바라볼 수 있다.
다양한 인물들을 계급, 나이, 성격 등의 차이점은 무시한 채 '트럼프'라는 유사성을 기반으로 추상화해서 바라본 것이다.
그룹으로 나누어 단순화하기
객체지향 패러다임에서의 객체는 명확한 경계를 가지고 서로 구별할 수 있는 구체적인 사람이나 사물을 말한다.
위에 나열한 인물들은 '트럼프' 라는 명확한 경계를 가지고 있다. 트럼프인 것과 트럼프가 아닌 그룹으로 나누어 복잡성을 효과적으로 감소시킨다.
개념
이처럼 공통점을 기반으로 객체들을 묶기 위한 그릇을 개념(concept) 라고 한다. 하나의 개념으로 묶음으로써 여러 객체를 개별적으로 다뤄야하는 복잡한 상황을 피할 수 있다.
개념을 이용하면 객체를 여러 그룹으로 분류(classification) 할 수 있다.
객체에 어떤 개념을 적용하는 것이 가능해서 개념 그룹의 일원이 될 때 객체를 그 개념의 인스턴스(instance) 라고 한다.
이러한 내용을 기반으로 객체를 다시 정의한다면: 객체란 특정한 개념을 적용할 수 있는 구체적인 사물을 의미한다. 개념이 객체에 적용됐을 때 객체를 개념의 인스턴스라고 한다.
개념 은 특정한 객체가 어떤 그룹에 속할 것인지를 결정한다. 이처럼 객체의 분류 장치로서 개념을 이야기할 때에는
심볼(symbol): 개념을 가리키는 간략한 이름 혹은 명칭
내연(intension): 개념의 완전한 정의, 내연의 의미를 이용해 객체가 개념에 속하는지 판단
외연(extension): 개념에 속하는 모든 객체의 집합 (set)
3가지 관점을 함께 언급하게 된다.
간단하게 위의 3가지 관점을 트럼프에 대입해본다면:
심볼: 트럼프
내연: 몸이 납작하고 두 손과 두 발은 네모 귀퉁이에 달려있는 등장인물
정원사, 병사, 신하, 왕자와 공주 ...
이러한 개념을 이용해 객체를 분류할 수 있다는 사실을 통해 객체지향 패러다임의 복잡성을 극복할 수 있다. (분류 는 객체에 특정한 개념을 적용하는 작업이다.)
또한, 분류는 추상화를 위한 도구다.
트럼프에 속하는 객체들의 공통점 중에서도 우리가 중요하다고 생각하는 특징만을 추리는 추상화 작업을 통해 불필요한 세부 사항을 제거하여 복잡한 '트럼프'라는 개념을 단순화할 수 있다.
타입
타입은 개념과 동일하다.
타입은 공통점을 기반으로 객체들을 묶기 위한 틀이다. 개념과 마찬가지로 심볼, 내연, 외연을 이용해 서술할 수 있으며 타입에 속하는 객체 역시 타입의 인스턴스라고 한다.
데이터 타입
컴퓨터가 어떤 작업을 수행하기 위해서는 작업에 필요한 데이터를 메모리 안으로 불러야 한다. (데이터는 0, 1로 이루어져있으며 질서가 존재하지 않는다.)
실제로 '타입이 없다(Untyped)'는 말은 메모리 안의 데이터를 다룰 수 있는 단 하나의 타입만이 존재한다는 의미
이 때, 메모리 안에 저장된 '10010001' 이라는 값은 숫자인가, 문자인가, 특정 메모리 주소값인가?
타입 없는 무질서로 인해 데이터를 목적에 따라 분류하기 시작하면서 타입 시스템이 등장하게 된다.
데이터 타입은 메모리 안에 저장된 데이터의 종류를 분류하는데 사용하는 메모리 집합에 관한 메타데이터이다. 데이터에 대한 분류는 암시적으로 어떤 종류의 연산이 해당 데이터에 대해 수행될 수 있는지를 결정한다.
객체와 타입
객체지향 프로그램을 작성할 때 우리는 객체를 일종의 데이터처럼 사용한다. 하지만, 객체는 행위에 따라 변할 수 있는 상태를 가지고 있다는 사실 을 기억하자. 객체는 데이터가 아니라 행동을 중심으로 바라봐야 한다.
객체가 이웃 객체와 협력하기 위해 어떤 행동을 해야하는지가 중요하다.
즉, 객체가 협력을 위해 어떤 책임을 갖느냐가 객체지향 설계의 핵심!
객체의 타입은:
어떤 객체가 어떤 타입에 속하는지를 결정하는 것은 객체가 수행하는 행동
객체의 내부적인 표현은 외부로부터 철저하게 감춰짐
행동이 우선이다
객체의 내부 표현 방식이 다르더라도 어떤 객체들이 동일하게 행동한다면? 그 객체들은 동일한 타입에 속한다.
어떤 객체를 다른 객체와 동일한 타입으로 분류하는 기준은?
동일한 행동을 하기만 하면 된다.
어떤 데이터를 가지고 있는지는 우리의 관심사가 아니다.
다른 행동을 한다면? 다른 타입이다.
여기서 말하는
동일한 행동은 동일한 책임을 의미하며
동일한 책임은 동일한 메시지 수신을 의미한다.
이것은 동일한 요청에 대해 서로 다른 방식으로 응답할 수 있는 능력을 말하는 '다형성' 에 의미를 부여한다.
데이터의 내부 표현 방식과 무관하게 행동만이 고려 대상이라는 사실은 '캡슐화' 원칙을 말하낟.
책임-주도 설계(Responsibility-Driven Design) 는 객체가 외부에 제공해야하는 책임을 먼저 결정하고 그 책임을 수행하는데 적합한 데이터를 나중에 결정한 후 , 책임을 수항하는데 필요한 외부 인터페이스 뒤로 데이터를 감추는 캡슐화 원칙을 따르는 방법론이다.
책임-주도 설계 vs 데이터-주도 설계
타입의 계층
객체가 동일한 타입으로 분류되기 위해서는 '공통의 행동'을 가져야만 한다.
하지만 등장인물들의 외양은 트럼프와 유사하지만 행동 자체는 트럼프와 완벽하게 동일하지 않다. 등장인물과 트럼프 카드의 행동이 완전히 일치하는가?
트럼프 카드는 납작 엎드릴 수 있고 뒤집어질 수는 있지만 걸어다닐 수는 없다.
트럼프 타입으로 불렸던 객체들을 좀 더 정확하게 트럼프 인간이라는 타입으로 분류하는 것이 옳다.
외연이라는 객체 집합의 관점에서 트럼프와 트럼프 인간을 살펴본다면,
트럼프 인간은 트럼프이다.
따라서, 모든 트럼프 인간은 동시에 트럼프이기도 하다.
이러한 관계를 일반화/특수화(generalization/specialization) 관계라고 한다.
일반화/특수화 관계
트럼프는 트럼프 인간보다 더 일반적인 개념이다. 즉 더 포괄적인 의미
트럼프 인간은 좀 더 특수하게 표현한 것
이러한 관계를 결정하는 것은 객체의 상태를 표현하는 데이터가 아닌 '행동'이라는 것이다.
일반적인 타입은 특수한 타입에 비해 더 적은 수의 행동을 가지며 특수한 타입은 일반적인 타입에 비해 더 많은 행동을 가진다. 단, 특수한 타입은 일반적인 타입이 할 수 있는 모든 행동을 동일하게 수행할 수 있어야 한다.
슈퍼타입과 서브타입
일반적인 타입 = 슈퍼타입(Supertype)
특수한 타입 = 서브타입(Subtype)
이러한 일반화는 추상화를 위한 도구 이다.
차이점을 배제하고 공통점만을 강조함으로써 공통의 타입을 찾아내는 것이 추상화 작업의 핵심
좀 더 단순한 관점에서 바라보기 위해 불필요한 특성을 배제하고 좀 더 포괄적인 개념을 찾아낸다.
이처럼 객체지향 패러다임을 통해 세상을 바라보는 대부분의 경우에 분류와 일반화/특수화 기법을 동시에 적용하게 된다.
일반화는 추상화를 위한 도구다
일반화/특수화 계층은 객체지향 패러다임에서 중요한 부분을 강조하기 위해 불필요한 세부 사항을 제거시켜 단순하게 만드는 추상화를 적절하게 활용하는 대표적인 예다.
차이점은 배제하고 공통점만을 강조함으로써 공통의 타입으로 묶어 분류함
좀 더 단순한 관점에서 바라보기 위해 불필요한 특성을 배제하고 좀 더 포괄적인 개념을 찾아낸다.
정적 모델
타입의 목적
타입을 왜 사용해야 할까? 인간의 인지 능력으로는 시간에 따라 동적으로 변하는 '객체의 복잡성'을 극복하기 어렵기 때문이다.
예를 들어, 앨리스의 키는 음식을 먹을 때마다, 어떤 행동을 할 때마다 변하지만 여전히 앨리스는 앨리스이다. 이렇듯 객체의 상태는 변하지만 식별성은 동일하게 유지된다.
타입은 시간에 따라 동적으로 변하는 상태를 시간과 무관한 정적인 모습으로 다룰 수 있게 해준다.
그래서 결국 타입은 추상화다
이런 관점에서 타입은 불필요한 시간이라는 요소와 상태 변화라는 요소를 제거하고 정적인 관점에서 앨리스의 모습을 묘사하는 것을 가능하게 하는 추상화다.
타입을 이용하면 객체의 동적인 특성을 추상화할 수 있다.
타입은 시간에 따른 객체 상태 변경이라는 복잡성을 단순화할 수 있는 효과적인 방법이다.
동적 모델과 정적 모델
우리는 두 가지 모델을 동시에 고려한다는 사실을 알 수 있다.
1. 객체가 특정한 시점에 구체적으로 어떤 상태를 가지는지
이를 객체의 스냅샷(snapshot) 이라고 하며, 객체지향 모델링을 위한 표준 언어인 UML에서는 객체 다이어그램(object diagram) 이라고 불린다.
스냅샷처럼 객체가 살아 움직이는 동안 상태가 어떻게 변하고 행동하는지를 포착하는 것을 동적 모델(dynamic model) 이라고 한다.
2. 객체가 가질 수 있는 상태와 모든 행동을 시간에 독립적으로 표현하는 것
이런 모델을 타입 모델(type diagram) 이라고 한다.
동적으로 변하는 객체의 상태가 아니라 객체가 속한 타입의 정적 모습을 표현
정적 모델(static model) 이라고도 한다.
클래스
객체지향 프로그래밍 언어에서 정적인 모델은 클래스를 이용해 '구현'된다.
클래스와 타입은 동일한 것이 아니다.
타입은 객체를 분류하기 위해 사용하는 개념!
반면 클래스는 단지 타입을 구현할 수 있는 여러 구현 매커니즘 중 하나일 뿐
클래스와 타입을 동일시하는 것은 많은 오해와 혼란을 불러 일으키니 주의하자.
정리해보자면,
객체를 분류하는 기준: 타입
타입을 나누는 기준: 객체가 수행하는 행동
타입을 구현하는 방법: 클래스
객체지향에서 중요한 것은 동적으로 변하는 객체의 '상태'와 상태를 변경하는 '행위'인 것을 잊지말자.
Last updated
Was this helpful?