반응형

객체지향의 사실과 오해

 

"객체지향의 사실과 오해" 책의 3부 "타입과 추상화" 부문 리뷰이다.

 

2부에서는 객체의 정의에 대해 알아보았다. 객체는 상태와 행동을 가지고 있으며 서로 관련이 있다.

이제는 시스템 내에 있는 각 로직들을 어떠한 기준으로 합치고 나누어 객체로 만들어야 하는지 알아야 한다. 

 

 

이 2부에서 난 큰 충격을 받았다. 갑자기 추상화에 대한 일화가 나와서 당황하고 흐름이 끊기는 것 같았지만 신선한 충격을 가져다 주었다. 바로 영국이 처음에 지하철 노선도를 도입했을 때 일화이다.

 

 

처음에는 위와 같이 지형과 섞여 있는 지하철 노선도(1926)였다고 한다. (1919년에는 이것보다 더 단순했지만 설명을 위해 이 지도가 처음이라고 가정한다.) 지형(도로, 강)과 역의 위치, 역 간의 거리 모두 사실적으로 표현되어 있다. 모든 정보가 정확하지만 우리 눈에는 너무 보기가 어렵고 불편하다. 도시가 골고루 발전하지 않고 도심 중심에서 퍼지면서 개발되기 때문에 역이 특정 지역에 모여 있다. 역들이 서로 엉켜 제대로 정보를 표시해주지 못하고 있다.

 

 

1928년 지하철 노선도를 다시 그렸다. 지형 정보는 크게 중요한 것이 아니라서 얕게 표시하고 지하철 노선도만 명암을 주어 표시했다. 하지만 첫 번째 지도와 마찬가지로 도심(도시 중앙 지역)에 역이 몰려 있어 보기가 불편하다. 여러 개의 노선이 지나가는 구역들은 이름이 어떤 것인지 구별하기가 쉽지 않다. 

 

 

1933년에 이르러 디자이너 헤리 백이 새롭게 디자인하면서 이 노선도가 현재 모든 지하철 노선도에 사용되고 있다. 지하철 노선도를 보는 사람들은 지형 정보가 중요하지 않다. 역 간의 거리도 중요하지 않다. 지하철에서 딴 짓을 하며 가다보니 시간을 솔직히 신경을 안 쓰며 몇 번 정차했는지만 중요하다. 거리, 지형이라는 정보를 과감히 삭제하니 우리가 원하는 정보에 손 쉽게 다가갈 수 있다.

 

내가 현재 역에서 도착역으로 가려면 어떻게 가야 하는가?

몇 개의 정류장을 거치는가?

어떤 노선들을 사용할 수 있는가?

 

모든 요구사항을 충족시킨다. 놀라웠고 충격을 받았다.

 

나도 객체지향을 잘 안다고 생각했었다. 클래스는 틀이며 객체는 그 틀에서 나온 공산품이라고 생각하고 그에 맞게 잘 코딩하고 있었다고 생각했다. 그래서 클래스 대상 개체를 면밀히 분석하고 개체 프로퍼티들을 추가하며 만족했었다.

예를 들어 음료수를 클래스로 만든다고 가정해보자.

 

public class drink {
    // 용량
    private final int volume;

    // 유통기한
    private final String expirationDate;

    // 칼로리
    private final int calorie;

    // 구성 요소
    private final String[] content;

    // 병뚜껑
    private final boolean lid;
}

 

음료수 캔을 이리 저리 보면서 용량, 유통기한, 칼로리, 구성 요소, 병뚜껑 여부 등을 프로퍼티로 만들었다. 하지만, 이 클래스는 위 노선도와 같이 불필요한 정보를 가질 수도 있다는 것이다. 만약 이 음료수가 배틀 그라운드라는 게임에 사용된다고 생각해보자. 이 음료수에 있는 칼로리, 병뚜껑, 유통기한 항목들은 필요가 없다. 그냥 던져서 사람을 맞출 용도이니까.

 

다시 돌아가서 객체로 만드려면 어떠한 기준으로 모으고 나누어야 하는지 정해야 한다고 했다. 일단 구현하려고자 하는 시스템의 목적이 무엇인지, 요구사항이 무엇인지 확인한다. 그리고 아래와 같이 추상화한다.

 

개념들 간의 공통점은 취하고, 차이점은 버리는 일반화를 통해 단순화한다.

중요한 부분을 강조하기 위해 불필요한 세부 사항들을 제거한다.

 

목적이 있으니까 불필요한 세부사항들을 가려낼 수 있다는 점을 기억해야 한다.

 

개념은 다시 심볼, 내연, 외연으로 나뉜다. 심볼은 이름이나 명칭이라 하고, 내연은 정의를 뜻하며, 외연은 집합을 의미한다. 굳이 저렇게 나눌 필요가 있을까 싶다. 그 뒤에 나오는 "개념 == 타입(클래스)" 이라는 말이 더 중요해 보였다.

 

객체가 어떤 타입에 속하는지는 객체가 수행하는 행동에 달려있다. 그 객체들이 동일한 행동을 수행하면 동일한 타입으로 본다. 객체의 내부적인 표현 방식이 다르더라도 외부로 전달하는/전달받는 메세지가 같다면, 동일한 행동을 한다면 동일한 타입으로 본다. 결국 또 행위이다. 오로지 행위에 의해서만 분류할 수 있다.

 

이러한 타입은 클래스처럼 일반화/특수화 관계를 이루며 계층 구조를 가질 수 있다. 추상화를 수행하면서 세부 상항이지만 불필요하지 않을 때 슈퍼 타입과 서브 타입으로 분류하면 된다.

 

끝마치며...

행동/행위에 따라 객체를 분류하기 때문에 데이터를 먼저 생각하는 데이터 주도 설계가 아닌 책임 주도 설계를 해야 한다는 말이 여기서부터 나오게 된다. 앞으로 역할, 책임, 협력을 조금 더 자세히 살펴보게 된다.

반응형

+ Recent posts