객체 바로알기 - 협력, 행동, 상태, 식별자
객체지향 세계는 실세계와 유사하다. 허나 면밀히 살펴보면 기이한 세상이다.
객체지향 세계에서 객체는 단순히 실세계를 모방하고 추상화한 존재가 아니다.
하나하나가 생명이 부여되어 살아 숨시고 있다. 모든 사물이 영화 아이언 맨의 '자비스'처럼 스스로 생각하고 해동한다. 객체지향 세계에서 객체는 실세계의 객체보다 훨씬더 많은 능력과 특성을 보유하고 있다.
오늘은 이 객체에 대해 면밀히 살펴보도록 하겠다.
객체지향 세계에서 객체는 식별이 가능한 개체나 사물을 뜻한다. 객체는 컴퓨터, 키보드같은 사물이 될 수도 있고 사랑, 우정 같은 추상적인 개념이 될 수도 있다. 객체는 구별가능한 식별자, 객체만의 특징을 가진 행동, 행동에 따라 변경되는 상태로 구성된다.
객체를 행동, 상태 그리고 식별자의 관점에서 살펴보자.
행동, 그리고 상태
객체의 행동은 상태를 변화시킨다.
물통의 물 양(상태)이 줄어드려면, 물을 마시는 행동을 해야한다.
몸무게(상태)를 줄이려면, 운동이라는 행동을 해야한다.
이처럼 객체지향 세계에서도 상태는 행동을 통해 변한다.
그리고 행동의 결과는 상태에 의존적이다.
물 마시기 전에 물통의 양이 얼마였느냐가 물을 마실수 있을지 없을지에 대한 행동에 영향을 주고, 마시고 나서의 상태가 얼마나 될지를 결정한다는 것이다. 어떤 행동 이전의 상태가 행동 이후의 상태로 바뀐다.
이를 통해 우리는 행동의 순서가 큰영향을 미친다는 것을 알 수 있다. 유기적인 객체 지향 설계를 위해서는 행동의 순서를 적절하게 정하는 것이 중요하다.
행동의 결과는 과거의 행동에 의존한다고 말했었는데 모든 행동들을 기억하고 관리하는 것은 불가능에 가깝다. 그래서 상태를 아는 것이 중요하다. 과거의 행동 히스토리를 관리하지 않아도 과거의 행동들에 대한 마지막 상태가 어떤지만 알면 된다.
운전을 하려면 집에서 차키를 가지고, 주차장으로 가서, 차를 찾아서, 시동을 거는 행동을 해야하는데, 우리는 단지 시동이 걸려있는지 유무만 알면 차를 운전할 수 있다. 시동이 걸려있는지에 대한 상태만 가지고, 운전을 할 수 있을지 없을지에 대한 행동의 결과가 예측이 가능해진다는 말이다.
즉, 상태를 통해 복잡한 객체지향 세계를 단순하게 이해할 수 있따. 과거 어떤 행동을 했는지는 상관없이 현재의 상태를 통해 행동의 결과가 쉽게 예상된다. 이는 객체지향 세계의 복잡성을 완화시켜주는 요소가 된다.
상태는 숫자,문자열, 속도, 시간, 날짜, 양, 참/거짓 등 단순한 값을 통해 객체의 상태를 표현하는 요소이다.
예를 들어 자동차는 객체이고, 자동차의 속도는 상태가 된다.
지나가는 학생은 객체가 되고, 학생의 나이는 상태가 된다.
자고있는 아기는 객체가 되고, 아기의 이름은 문자열인 상태가 될 수 있다.
때로는 상태로 객체자체가 사용되기도 한다.
예를 들어 자동차라는 객체 안에 연료탱크라는 자동차 부품이 객체로 사용될 수도 있다.
자동차 객체와 연료 탱크 객체는 서로 연결되어 있다. 이를 링크(link)라고 한다.
링크와는 다르게 객체를 구성하는 연료량이나 자동차 이름 같은 단순한 값은 속성(attribute)이라고 한다.
링크와 속성을 합쳐 객체 프로퍼티 (object property) 라 부른다.
연료량이나 자동차이름 자체는 정적인 프로퍼티이고, 20리터나 소나타 같은 값은 동적인 프로퍼티 값이다. 객체의 상태는 정적인 프로퍼티와 동적인 프로퍼티 값으로 구성된다.
그리고 외부의 객체가 직접 객체의 상태를 변경하거나 볼 수 없기 때문에 조회하거나 변경할 수 있는 간접적인 방법을 객체가 외부에 제공해야한다.
상태의 관점에서 객체 바라보기
위의 내용으로 비추어 볼때 상태가 변경되기 위해서는 행동이 수반되어야 한다.
자동차의 연료는 자동차가 움직이는 행동을 해야 줄어들고, 사람이 기름을 넣는 행동을 해야 늘어난다.
즉, 행동은 상태변경이라는 부수효과를 일으킨다.
행동은 상태에 전적으로 의존한다. 연료량이 0이면 자동차는 움직일 수 없다. 객체의 행동은 상태에 영향을 받는다는 것이다.
자동차가 움직일 수 있는지 없는지를 과거의 자동차의 행동 이력을 몰라도 연료량이라는 현재 상태만 확인하면 알 수 있다. 이러한 특성은 객체지향 세계의 복잡성을 줄여준다.
협력의 관점에서 객체 바라보기
객체는 다른 객체와 서로 협력하는 상호작용을 통해 객체 세계에서 살아나간다.
객체가 다른 객체와 협력하기 위해서 다른 객체에 요청 메시지를 보낸다. 요청을 수신한 객체는 요청에 대한 문제를 해결하기 위해 적잡한 방법을 선택하여 행동하고 자신 혹은 타 객체의 상태를 변경한다. 메시지를 송신하는 객체는 메시지를 수신하는 객체의 상태변경에 대해서는 알 수가 없다. 이를 객체지향 세계에서 캡슐화라 일컫는다. 객체지향 세계에서 객체가 외부에 자신을 노출하는 방법은 오직 행동 뿐이고, 외부에서 객체에 접근하는 방법도 행동 뿐이다.
객체는 서로 행동만 전달할 뿐 상태가 어떻게 변할지는 전혀 신경쓰지 않는다. 이는 객체의 자율성 극대화로 이어진다. 객체의 자율성이 높으면 높을 수록 객체의 협력은 유연해지고 간결해진다. 캡슐화를 하는 이유는 객체의 자율성을 높혀 협력을 단순하고 유연하게 하기 위함이다.
식별자
객체는 어떻게 구분할 수 있을까?
객체와 단순한 값의 가장 큰 차이는 식별자가 있느냐 없느냐이다.
값의 상태는 변하지 않는 불변 상태 (immutable state)이다. 값의 상태가 같으면 동일한 것으로 판단하는데 이를 동등성(equality) 비교라고한다.
그러나 객체의 상태는 변하는 가변 상태(mutable state)를 가진다. 타입이 같은 객체가 상태가 같다하더라도 두 객체는 아예 다른 객체로 바라봐야한다. 지나가는 자동차들이 같은 종의 차라도 전혀 다른 차이듯 말이다. 자동차에는 자동차를 식별할 수 있는 식별자가 있다. 이 식별자를 통해 우리는 주차된 차량 중 내 차를 손쉽게 찾을 수 있다. 이처럼 식별자를 바탕으로 객체의 같음을 판별하는 것을 동일성(identical) 비교라 한다.
객체지향 설계 시 유의할 점
"협력을 먼저 생각하고, 행동을 정하고, 마지막으로 상태를 결정하라"
이것만 지키면 여러분은 훌륭한 객체지향 설계를 해낼 수 있다.
협력을 먼저 결정함으로서 설계의 목표를 명확하게 하자. 그래야 누구나 이해할 수 있는 깔끔한 설계를 해낼수 있다.
다음은 행동을 정하라. 행동에 초점을 맞춰야 캡슐화를 원할하게 할 수 있다. 상태를 먼저 정해버리면 상태가 쉽사리 노출된다.
행동이 결정 되면 적당한 상태를 정하라. 여기서 행동은 책임과 같은말로 이해해도된다.
이러한 순서로 설계를 진행하면 응집도 높고 재사용 가능한 객체를 만들어 낼 수 있으리라 확신한다.