서문
과거 최초의 지하철 노선도를 소개하며 이야기가 시작된다. 초기 지하철 지도는 실제 지형과 거리, 방향 등을 표시한 사실적인 지도였다. 그러나 사람들에게 중요한 것은 연결, 즉 열차를 갈아타는 것이기 때문에, 사실적인 지형은 무시하고 연결에만 초점을 맞춘 지하철 노선도가 탄생한다. 이는 오늘날에도 쓰이는 지하철 노선도의 기원이 되는데, 이렇게 꼭 알아야 하는 사실만 정확하게 표현하고 몰라도 되는 정보는 무시함으로써 이해하기 쉽고 단순하며 목적에 부합하는 지하철 노선도를 창조해낼 수 있었다. 지하철 노선을 추상화한 것이다.
추상화
현실에 존재하는 다양한 현상 및 사물과 상호작용하기 위해서는 우선 현실을 이해해야 한다. 그러나 인간의 인지 능력과 저장 공간은 이를 그대로 수용하기 힘들다. 따라서 사람은 본능적으로 이해하기 쉽고 예측 가능한 수준으로 현실을 분해하고 단순화한다.
진정한 의미에서 추상화란 현실에서 출발하되 불필요한 부분을 도려내가면서 사물의 놀라운 본질을 드러나게 하는 과정이다. 복잡한 현실을 단순화하기 위해 사용하는 인간의 가장 기본적인 인지 수단인 것이다.
다음은 추상화의 정의이다.
어떤 양상, 세부 사항, 구조를 좀 더 명확하게 이해하기 위해 특정 절차나 물체를 의도적으로 생략하거나 감춤으로써 복잡도를 극복하는 방법.
복잡성을 다루기 위해서 추상화는 두 차원에서 이뤄진다.
- 구체적인 사물들 간의 공통점은 취하고 차이점은 버리는 일반화를 통해 단순하게 만드는 것
- 중요한 부분을 강조하기 위해 불필요한 세부 사항을 제거함으로써 단순하게 만드는 것.
객체지향 패러다임은 객체라는 추상화를 통해 현실의 복잡성을 극복한다.
개념
추가적으로 앨리스의 얘기를 소개한다. 정원에 트럼프 카드 처럼 생긴 정원사와, 왕자, 공주, 병사 등이 나타나고 앨리스는 이들을 기껏해야 '트럼프'인데 뭐 라고 생각한다. 앨리스가 인물들의 차이점을 무시하고 공통점만을 취해 트럼프라는 개념으로 단순화한 것은 추상화의 일종이다.
이처럼 공통점을 기반으로 객체들을 묶기 위한 그릇을 개념(concept)이라고 한다. 개념이란 일반적으로 우리가 인식하고 있는 다양한 사물이나 객체에 적용할 수 있는 아이디어나 관념을 뜻한다.
예를 들어, 하늘을 나는 교통 수단을 지칭하는 개념은 '비행기'이고, 글을 쓰는 필자는 '인간'이다. 이렇게 우리는 주변에 존재하는 다양한 사물들에게 특정한 개념을 적용하는 게 익숙하다
개념을 이용하면 객체를 여러 그룹으로 분류(classification)할 수 있다. 개념은 공통점을 기반으로 객체를 분류할 수 있는 일종의 체인 것이다.
객체에 어떤 개념을 적용하는 것이 가능해서 개념 그룹의 일원이 될 때 객체를 그 개념의 인스턴스(instance)라고 한다.
객체란 특정한 개념을 적용할 수 있는 구체적인 사물을 의미한다. 개념이 객체에 적용됐을 때 객체를 개념의 인스턴스라고 한다.
개념의 세 가지 관점
객체의 분류 장치로서 개념을 이야기할 때 아래 세 가지 관점을 함께 언급한다.
- 심볼(symbol) : 개념을 가리키는 간략한 이름이나 명칭
- 내연(intension) : 개념의 완전한 정의를 나타내며 내연의 의미를 이용해 객체가 개념에 속하는지 여부를 확인할 수 있다.
- 외원(extension) : 개념에 속하는 모든 객체의 집합
예시를 들자면 심볼은 트럼프, 내연은 몸이 납작하고 두 손과 두 발은 네모 귀퉁이에 달려 있는 앨리스에서의 등장인물, 외연은 정원사, 병사, 왕자, 공주 등이다.
심볼, 내연, 외연은 객체의 분류 방식에 대한 지침을 제공한다. 중요한 것은 개념을 이용해 객체를 분류할 수 있다는 것이다. 분류가 객체지향 패러다임이 복잡성을 극복하는 기본적인 인지 수단이기 때문이다.
분류
분류란 객체에 특정한 개념을 적용하는 작업이다. 객체에 특정한 개념을 적용하기로 결심했을 때 우리는 그 객체를 특정한 집합의 멤버로 분류하고 있는 것이다.
분류는 객체지향의 중요한 개념 중 하나이다. 분류가 객체지향의 품질을 결정한다. 따라서 소중한 객체를 안전하고 적절한 장소에 보관할 수 있도록 최대한 직관적으로 분류하라.
타입
타입은 개념과 동일하다. 따라서 타입이란 우리가 인식하고 있는 다양한 사물이나 객체에 적용할 수 있는 아이디어나 관념을 의미한다. 어떤 객체에 타입을 적용할 수 있을 때 그 객체를 타입의 인스턴스라고 한다. 타입의 인스턴스는 타입을 구성하는 외연인 객체 집합의 일원이 된다.
타입에 대한 중요한 사실 두 가지가 있다.
- 타입은 데이터가 어떻게 사용되느냐에 관한 것이다. 숫자형 데이터는 데이터를 빼거나 더할 수 있기 때문이고, 문자형 데이터는 두 데이터를 연결해 문자열을 만들수 있기 때문이다. 즉 데이터에 어떤 연산자를 적용할 수 있느냐가 그 데이터의 타입을 결정한다.
- 타입에 속한 데이터를 메모리에 어떻게 표현하는지는 외부로부터 철저하게 감춰진다. 숫자형 데이터가 메모리 내부에 어떻게 저장되는지 개발자는 모르지만 지장이 없다.
데이터 타입은 메모리 안에 저장된 데이터의 종류를 분류하는 데 사용하는 메모리 집합에 관한 메타데이터다. 데이터에 대한 분류는 암시적으로 어떤 종류의 연산이 해당 데이터에 대해 수행될 수 있는지를 결정한다.
객체와 타입
앞에서 말한 타입에 대한 중요한 사실 두 가지는 객체의 타입에도 적용된다.
- 객체가 어떤 타입에 속하는지를 결정하는 것은 객체가 수행하는 행동이다.
- 객체의 내부적인 표현은 외부로부터 철저하게 감춰진다.
이 두가지 사실로부터 객체지향 설계에 대한 중요한 원칙을 이끌어 낼 수 있다.
행동이 우선이다.
객체의 타입을 결정하는 것은 객체의 행동뿐이다. 객체가 어떤 데이터를 보유하고 있는지는 타입을 결정하는 데 아무런 영향도 미치지 않는다. 객체는 행동만 동일하다면 서로 다른 데이터를 가질 수 있다. 동일한 메시지를 수신하더라도 다른 방식으로 처리할 수 있다. 이것이 다형성이다. 동일한 메시지를 다른 방식으로 처리하기 위해서 객체들은 동일한 메시지를 수신할 수 있어야 하기 때문에 다형적인 객체들은 동일한 타입에 속하게 된다.
데이터의 행동만이 고려 대상이라는 사실은 외부에 데이터를 감춰야 한다는 것을 의미한다. 이 원칙을 캡슐화라고 한다. 데이터가 캡슐의 벽을 뚫고 객체의 인터페이스를 오염시키는 순간 객체의 분류 체계는 위험에 노출되고 유연하지 못한 설계를 낳는다.
행동에 따라 객체를 분류하기 위해 객체는 외부에 제공해야 하는 행동을 먼저 생각해야 한다. 그 후에 행동에 적합한 데이터를 결정한 후 외부 인터페이스 뒤로 캡슐화해야 한다.
객체를 결정하는 것은 행동이다. 데이터는 단지 행동을 따를 뿐이다. 이것이 객체를 객체답게 만드는 가장 핵심적인 원칙이다.
타입의 계층
앞에서 말한 트럼프 인간 타입의 객체들은 트럼프 타입의 객체가 할 수 있는 모든 행동을 할 수 있을뿐만 아니라 추가적으로 걸어다니는 행동을 더 할 수 있다. 다시말해 트럼프 인간은 트럼프의 일종이지만 트럼프 카드보다 좀 더 특화된 행동을 하는 트럼프인 것이다.
트럼프는 트럼프 인간을 포괄하는 좀 더 일반적인 개념이고, 트럼프 인간은 트럼프보다 좀 더 트고하된 행동을 하는 특수한 개념이다. 이 두 개념 사이의 관계를 일반화/특수화(generalization/specialization)관계라고 한다.
일반화와 특수화는 동시에 일어난다. 더 특수하다는 것은 일반적인 개념보다 범위가 더 좁다는 것을 의미하므로, 트럼프 인간에 속하는 객체가 트럼프에 속하는 객체보다 수가 적을 수밖에 없다.
중요한 것은 일반화/특수화 관계를 결정하는 것은 객체의 상태를 표현하는 데이터가 아니라 행동이라는 것이다. 드 타입 간에 일반화/특수화 관계가 성립하려면 한 타입이 다른 타입보다 더 특수하게 행동해야 하고 반대로 한 타입은 더 일반적으로 행동해야 한다. 일반적인 타입은 특수한 타입이 가진 모든 행동 중에서 일부 행동만을 가지는 타입이고, 특수한 타입은 일반적인 타입이 가진 모든 행동에 자신만의 행동을 추가하는 타입을 가리킨다.
주의할 점은 타입의 내연을 의미하는 행동의 가짓수와 외연을 의미하는 집합의 크기는 서로 반대라는 점이다.
일반적인 타입을 슈퍼타입이라고 하고 좀 더 특수한 타입을 서브타입이라고 한다.
정적 모델
타입을 사용하는 이유는 인간의 인지 능력으로는 시간에 따라 동적으로 변하는 객체의 복잡성을 극복하기가 너무 어렵기 때문이다. 타입은 시간에 따라 동적으로 변하는 객체의 상태를 시간과 무관한 정적인 모습으로 다룰 수 있게 해준다.
결국 타입은 추상화다. 시간에 따른 객체의 상태 변경이라는 복잡성을 단순화할 수 있는 효과적인 방법인 것이다.
객체가 살아 움직이는 동안 상태가 어떻게 변하고 어떻게 행동하는지를 포착하는 것을 동적 모델이라고 한다.
객체가 가질 수 있는 모든 상태와 모든 행동을 시간에 독립적으로 표현하는 것을 정적 모델이라고 한다.
정적인 모델은 클래스를 이용해서 구현된다. 따라서 타입을 구현하는 가장 보편적인 방법은 클래스를 이용하는 것이다. 클래스와 타입은 동일한 것이 아니다. 타입은 객체를 분류하기 위해 사용하는 개념이고 클래스는 단지 타입을 구현할 수 있는 여러 메커니즘 중 하나일 뿐이다.
객체를 분류하는 기준은 타입이며 타입을 나누는 기준은 객체가 수행하는 행동이다. 타입을 결정한 후 프로그래밍 언어를 이용해 타입을 구현할 수 있는 한 가지 방법이 클래스일 뿐이다.
느낀점
추상화를 사용하는 이유를 더 잘 이해하게 되었다. 목적을 이루기 위해 복잡한 것을 의도적으로 단순하게 만드는 것이 필요하다는 것을 느꼈다.
개념, 개념의 세 가지 관점, 분류, 타입, 데이터 타입 등의 새로 나온 정의들을 잘 살펴보자.
책에서 계속 반복되는 행동의 중요성이 3장에서도 나왔다. 객체를 설계함에 있어서 가장 중요한 것을 행동이고, 이 객체를 일반화/특수화하는 기준 또한 행동이다. 객체지향 패러다임에서 행동이 가장 중요하다는 원칙을 잊지말고 기억하자.
'프로그래밍 이론 & 책 > 객체지향의 사실과 오해' 카테고리의 다른 글
[객체지향] 5. 책임과 메시지 (0) | 2020.06.22 |
---|---|
[객체지향] 4. 역할, 책임, 협력 (0) | 2020.06.19 |
[객체지향] 2. 이상한 나라의 객체 (0) | 2020.06.17 |
[객체지향] 1. 협력하는 객체들의 공동체 (0) | 2020.06.16 |
[객체지향] 개요 (0) | 2020.06.16 |