이상한 나라의 앨리스 객체
- 앨리스는 작은 문 너머 아름다운 정원으로 이동하고 싶다.
- 작은 문의 높이는 40cm이며, 현재 앨리스는 이보다 크다.
- 작은 문은 열쇠로 열 수 있는데, 너무 작은 사람은 이 열쇠를 사용할 수 없다.
- 앨리스는 케이크/버섯/음료를 먹거나, 부채질을 하는 행동을 통해 자신의 키를 변화시킬 수 있다.
여기서 앨리스를 객체로 생각해보자.
앨리스는 문을 통과하기에 적당한 상태로 자신의 키를 계속해서 변화시킨다.
특정 시점의 앨리스의 상태란 특정 시점에서의 앨리스의 키를 의미한다.
앨리스는 무언가를 먹거나 부채질을 하면서 키를 변화시킨다. 앨리스의 키를 변화시키는 것은 앨리스의 행동이다.
앨리스가 하는 행동에 따라 앨리스의 상태가 변하게 된다.
앨리스의 상태를 결정하는 것은 행동이지만, 행동의 결과를 결정하는 것은 상태다.
상태에 따라 행동의 결과가 달라지는 예1
케이크를 먹으면 현재의 키보다 150센티미터 더 커진다고 해보자.
케이크를 먹기 전의 키가 케이크를 먹고 난 후의 키를 결정하는 것이다.
앨리스가 한 행동의 결과는 앨리스의 상태에 의존적이다.
상태에 따라 행동의 결과가 달라지는 예2
앨리스가 문을 통과할 수 있는지 여부는 앨리스의 키가 얼마인가에 달렸다.
문을 통과할 정도로 키가 작다면 정원에 갈 수 있겠지만, 키가 너무 크다면 정원을 쳐다볼 뿐이다.
어떤 행동이 성공 여부는 이전에 어떤 행동들이 발생했는지에 영향을 받는다.
행동 간의 순서가 중요하다. 문을 통과하는 행동이 성공하려면 음료나 케이크를 먹는 행동이 선행돼야만 한다.
행동에 의해 앨리스의 상태가 변경되더라도 앨리스가 앨리스임은 여전하다.
앨리스는 상태 변경과 무관하게 유리한 존재로 식별 가능하다.
즉, 객체의 특징은 다음과 같다.
- 객체는 상태를 가지며 상태는 변경 가능하다. - state
- 객체의 상태를 변경시키는 것은 객체의 행동이다. - behavior
- 행동의 결과는 상태에 의존적이며 상태를 이용해 서술할 수 있다.
- 행동의 순서가 결과에 영향을 미친다.
- 객체는 어떤 상태에 있더라도 유일하게 식별 가능하다. - identity
상태 = 특정 시점에 객체가 가지고 있는 정보의 집합 = 정적인 프로퍼티 + 동적인 프로퍼티 값
어떤 행동의 결과는 과거에 어떤 행동들이 일어났었느냐에 의존한다.
앨리스가 문을 통과한다는 행동의 결과를 예상할 수 있는 한 가지 방법은 과거에 케이크나 버섯을 먹었던 적이 있는지 살펴보는 것이다.
이는 매우 어렵다. 따라서 행동의 과정과 결과를 단순하게 기술하기 위해 상태라는 개념이 나왔다.
앨리스의 키와 문의 높이라는 두 가지 상태만 알면 문을 통과하는 행동의 결과를 쉽게 예측할 수 있다.
프로퍼티 = 링크 + 속성
모든 객체의 상태는 단순한 값과 객체의 조합으로 표현할 수 있다.
이때 객체의 상태를 구성하는 모든 특징을 통틀어 객체의 프로퍼티라고 한다.
프로퍼티는 변경되지 않고 고정되기 때문에 정적이지만,
프로퍼티 값은 시간의 흐름에 따라 변경되기 때문에 동적이다.
앨리스의 키가 변화할 순 있지만, 키라는 상태가 없어지진 않는다.
링크
앨리스가 음료를 가지고 있을 땐 음료에 관해 알고 있지만, 음료를 먹고나서 버리면 음료에 관해 알지 못하는 상태로 변경된다.
이처럼 객체와 객체 사이의 의미 있는 연결을 링크라고 한다.
링크가 존재해야 메시지를 주고받는 객체 간의 협력이 가능하다.
이는 일반적으로 한 객체가 다른 객체의 식별자를 알고 있는 것으로 표현된다.
속성
객체를 구성하는 값을 속성이라 한다. 앨리스의 키와 위치는 단순한 값으로 표현되기 때문에 속성이다.
행동 = 외부의 메시지에 응답하기 위해 동작하는 활동
객체는 자율적이다. 객체는 다른 객체의 상태에 직접적으로 접근/변경할 수 없다.
따라서 간접적으로 객체의 상태를 변경하거나 조회할 수 있는 방법이 필요하다.(행동)
행동에 의해 상태가 변경된다는 것은 행동이 사이드 이펙트를 초래한다는 것을 의미한다.
케이크를 먹는 행위는 키를 작게 변화시키고 케이크의 양을 줄이는 사이드 이펙트를 야기한다.
따라서 상태와 행동 사이에는 다음과 같은 관계가 있다.
- 객체의 행동은 상태에 영향을 받는다
- 객체의 행동은 상태를 변경시킨다.
상태를 이용해 행동을 두 관점에서 서술할 수 있다.
- 상호작용이 현재의 상태에 어떤 방식으로 의존하는가
(앨리스의 키가 40센티미터 이하라면 문을 통과할 수 있다) - 상호작용이 어떻게 현재의 상태를 변경시키는가
(문을 통과한 후에 앨리스의 위치는 아름다운 정원으로 바뀐어야 한다)
협력과 행동
어떤 객체도 섬이 아니다. 객체는 다른 객체와 적극적으로 상호작용한다.
객체의 행동은 객체가 협력에 참여할 수 있는 유일한 방법이다. 행동은 외부에 가시적이어야 한다.
객체가 어떤 행동을 하도록 만드는 것은 외부로부터 수신한 메시지다.
협력 과정에서 다른 객체의 상태 변경을 유발할 수도 있다.
앨리스가 음료를 마시는 행동은 자기 자신뿐만 아니라 음료의 상태 변경도 유발한다.
객체의 행동은 두 가지 관점의 사이드 이펙트를 서술해야 한다.
- 객체 자신의 상태 변경
- 행동 내에서 협력하는 다른 객체에 대한 메시지 전송
상태 캡슐화
객체지향에서 모든 객체는 (현실과 달리) 자신의 상태를 스스로 관리하는 자율적인 존재다.
앨리스는 직접적으로 음료의 상태를 변경할 수 없다. 음료에게 음료를 마셨다는 메시지를 전달할 뿐인다.
음료의 양을 줄이는 것은 메시지를 전달받은 음료 스스로의 몫이다. 앨리스와는 무관하다.
class Alice {
private juice: Juice;
constructor(juice: Juice) {
this.juice = juice;
}
drinkBeverage(quantity: number) {
return this.juice.drunken(quantity);
}
}
class Juice {
private amount;
constructor(initQuantity: number) {
this.amount = initQuantity;
}
drunken(quantity: number) {
this.amount -= quantity;
}
}
객체는 상태를 캡슐 안에 감춰둔 채 외부로 노출하지 않는다. 노출하는 것은 행동뿐이다.
캡슐화는 객체의 자율성을 높이고 협력을 단순하고 유연하게 만든다.
식별자
객체가 식별 가능하다는 것은 객체를 서로 구별할 수 있는 특정한 프로퍼티가 객체 안에 존재한다는 것을 의미한다.
이 프로퍼티를 식별자라고 한다. 값과 객체의 가장 큰 차이점이 식별자의 유무다.
값은 변하지 않는 양을 모델링한다. 불변 상태를 사진다.
두 인스턴스의 상태가 같다면 두 인스턴스는 같은 것이다.
값의 상태는 변하지 않기 때문에 상태로 값이 같은지를 판단할 수 있다. (동등성 equality)
객체는 시간에 따라 변경되는 상태를 포함하며, 행동을 통해 상태를 변경한다. 가변 상태를 가진다.
타입이 같은 두 객체의 상태가 완전히 똑같더라도, 두 객체는 독립적인 별개의 객체다.
완전한 쌍둥이더라도 두 사람은 별개의 인격체다.
객체는 식별자를 기반으로 객체가 같은지를 판단할 수 있다. (동일성 identical)
참조 객체 또는 엔티티는 식별자를 지닌 전통적인 의미의 객체를 가리키는 용어다.
값 객체는 식별자를 가지지 않는 값을 가리키는 용어다.
쿼리와 명령
객체의 상태를 조회하는 작업을 쿼리(query), 객체의 상태를 변경하는 작업을 명령(command)이라고 한다.
행동의 대부분은 쿼리와 명령으로 구성된다.
사용자는 객체가 제공하는 쿼리/명령 인터페이스를 통해서만 객체에 접근할 수 있다.
행동이 상태를 결정한다
상태를 먼저 결정하고 행동을 나중에 결정하는 방법은 설계에 나쁜 영향을 끼친다.
- 캡슐화가 저해된다.
상태에 초점을 맞추면 상태가 객체 내부로 깔끔하게 캡슐화되지 못하고 공용 인터페이스에 노출될 확률이 높아진다. - 객체를 협력자가 아닌 고립된 섬으로 만든다.
객체가 필요한 이유는 다른 객체와 협력하기 위해서다.
상태를 먼저 고려하는 방식은 협력이라는 문맥에서 벗어나게 된다. - 객체의 재사용성이 저해된다.
재사용성은 다양한 협력에 참여할 수 있는 능력에서 나온다. 상태에 초점을 맞춘 객체는 다양한 협력에 참여하기 어렵다.
객체의 적합성을 결정하는 것은 상태가 아닌 행동이다. 객체의 행동은 객체의 책임을 의미한다.
어떤 책임이 필요한가를 결정하는 과정이 전체 설계를 주도해야 한다. (책임-주도 설계)
객체지향은 현실 세계의 모방이 아니다
흔히 객체지향을 현실 세계의 추상화라고 하지만,
소프트웨어 객체는 실제 세계의 객체를 단순화하거나 추상화한 것이 아닌, 특성이 전혀 다른 어떤 것이다.
현실 객체는 수동적이지만 소프트웨어 객체는 능동적이다.
소프트웨어 객체는 현실 객체보다 더 많은 일을 할 수 있는 특징을 가진다. (의인화)
그렇다고 전혀 상관이 없는 건 아니다. 모방이나 추상화의 수준이 아닌 다른 관점에서 유사성을 가진다.
현실 세계와 객체지향 세계 사이의 관계를 좀 더 정확하게 설명하는 단어는 은유다.
앨리스에는 트럼프 카드가 나온다. 트럼프 카드는 현실 세계와 달리 손발이 달려 있다.
그럼에도 우리는 은유를 통해 트럼프 카드가 쉽게 뒤집힐 것이라는 것을 예상할 수 있다.