Book

[객체지향의 사실과 오해] 02 이상한 나라의 객체

YATTA! 2024. 9. 24. 23:10

✏️, 💡,❓ 해당 이모지는 저의 생각임을 나타냅니다.

 

사람은 태어난 지 얼마 안 된 시기부터 뚜렷한 경계를 가지고 함께 행동하는 물체를 하나의 개념으로 인지한다. (pinker 1997) 

물체가 여러 부분으로 구성돼 있더라도 함께 움직일 경우 그 물체를 하나의 유기적인 단위로 인식한다는 것이다.

 

객체지향과 인지 능력

인간은 본능적으로 세상을 독립적이고 식별 가능한 객체의 집합으로 바라본다. 

많은 사람들이 객체지향을 직관적이라고 말하는 이유는 객체지향이 세상을 자율적이고 독립적인 객체들로 분해할수 있는 인간의 기본적인 인지 능력에 기반을 두고 있기 때문이다.

✏️ 저자는 사람은 기본적으로 세상을 객체화해서 생각한다고 말하고 있다.

 

고개를 들어 주위를 둘러보면 객체라고 부를 수 있는 다양한 존재를 볼 수 있다. 하나의 단위로 인식할 수 있고 다른 사물과 구분할 수 있는 것들이 모여 객체의 스펙트럼을 형성한다.

 

세상을 작은 객체로 분해하는 것은 세상이 포함하고 있는 복잡성을극복하기 위한 인간의 작은 몸부림이다. 인간은 객체들로 주변을 분해함으로써 몸담고 있는 세상을 이해하려고 노력한다. 

 

소프트웨어 세계 역시 인간이 인지할 수 있는 다양한 소프트웨어 객체들이 모여 이뤄져 있다는 믿음에서 출발한다. 그러나 둘 사이의 유사성은 여기까지일 뿐이다. 객체지향 패러다임의 목적은 현실 세계를 모방하는 것이 아니라 현실 세계를 기반으로 새로운 세계를 창조하는 것이다. 따라서 소프트웨어의 객체는 현실 세계에 존재하는 객체와는 전혀 다른 모습을 보이는 것이 일반적이다.

 

객체지향 애플리케이션 내부를 본다면 겉으로는 우리의 세계와 유사해보이지만 실제로는 이질적임을 알게 될 것이다.

 

객체, 그리고 이상한 나라

앨리스 이야기를 아는가? 음료를 마시면 앨리스의 키가 작아지고, 케이크를 먹으면 앨리스의 키가 커진다. 앨리스가 하는 행동에 따라 앨리스의 상태가 변하게 된다.

앨리스의 상태를 결정하는 것 = 행동

행동의 결과를 결정하는 것 = 상태

말장난처럼 보이지만 후자의 말을 다시 생각해보자. 앨리스 키가 260센티라고 했을 때, 케이크를 한 번 더 먹어서 20센티가 컸다. 그러면 앨리스의 키는 280센티가 될 것이다. 따라서 앨리스가 한 행동의 결과는 앨리스의 상태에 의존적이다.

✏️ 놀랍게도 되게 복잡해보인다. 그런데 요지는 앨리스의 행동의 결과는 상태에 의존적이라는 것이다. a 사람의 키가 170이라고 가정하고, b 사람의 키가 200 이라고 가정할 때 같은 행동을 해도 (마법의 케이크 먹기) a는 190이 될 것이고 b는 220이 될 것이다. 상태에 따라 행동의 결과가 달라지는 것이다. 

✏️ 프로그래밍에는 변수라는 개념이 있다. 위의 내용을 이해한다면 변수도 이해하게 될 것이다.

 

앞으로 이야기를 위해 앨리스의 특징을 요약해보자.

1. 앨리스는 상태를 가지며 상태는 변경 가능하다.

2. 상태는 앨리스의 행동으로 변경된다.

- 행동의 결과는 상태에 의존적이며 상태를 이용해 서술할 수 있다.

- 행동의 순서가 결과에 영향을 미친다.

3. 앨리스는 어떤 상태여도 식별 가능하다.

 

객체, 그리고 소프트웨어 나라

객체의 특성을 효과적으로 설명하기 위해선 객체를 상태status 행동behavior 식별자identity를 지닌 실체로 보는 게 효과적이다. 

 

해당 책에서는 객체를 다음과 같이 정의한다. ⬇️

객체란 식별 가능한 개체 또는 사물이다. 자동차처럼 만질 수 있는 구체적 사물일 수도 있고, 추상적인 개념일 수도 있다. 객체는 식별자, 행동, 상태를 가진다. 소프트웨어 안에서는 저장된 상태와 실행 가능한 코드를 통해 구현된다.

 

모든 객체의 상태는 단순한 값과 객체의 조합으로 표현할 수 있다. 앨리스가 음료를 먹는 상태에서 앨리스의 키, 위치, 음료(객체)가 앨리스의 프로퍼티가 된다. 프로퍼티는 변경되지 않기 때문에 정적이지만 값은 변경되기때문에 동적이다.

상태, 프로퍼티, 속성들이 무척 헷갈렸다.

✏️객체를 구성하는 단순한 값(키, 위치) = 속성 / 프로퍼티 = 값과 객체(객체의 상태 표현)

 

객체는 자신에게 주어진 책임을 완수하기 위해 다른 객체를 이용하고 서비스를 제공한다.

객체는 협력에 참여하는 과정에서 자기 자신의 상태뿐 아니라 다른 객체의 상태 변경을 유발할 수도 있다. 앨리스가 음료를 마시면 앨리스가 작아지는 동시에 음료의 양이 줄어야 한다. 

그러나 객체는 자신의 상태를 스스로 관리하는 자율적인 존재다. 음료 객체의 양을 줄이는 것은 음료 자신이어야 한다. 앨리스는 음료에게 자신이 음료를 마셨다는 메시지를 전달할 수 있을뿐이다.

💡 자신의 상태는 자신이 관리하는 게 무척 중요한 포인트인 것 같다.

앨리스는 어떤 요청을 보내야할까 갑자기 궁금증이 생겼다. 나 음료 마셨어라는 마셨다의 요청일까 아니면 음료 마셨으니까 음료 양 '줄여줘'라는 요청일까? 옛날부터 고민이 많았던 포인트였다. 책에서는 '앨리스는 자신이 먹은 양만큼 음료 양을 줄여달라고 메시지를 전송한다. 그러나 음료의 양이 줄어들 것인지는 메시지를 수신한 음료가 결정할 사항이다.'라고 적혀있다. 책에서 이해한 건 '줄여줘'라고 요청하는 것은 앨리스의 몫, 수행 할지 말지 판단은 음료의 몫이라고 한다. 그런데 객체지향적으로 봤을때 줄여줘라는 요청을 앨리스가 해야하는 게 맞는가에 대한 의문이 있다.

💡 책에서 drunken(quantily)라는 함수를 호출하는 그림이 있다. 줄여달라는 직접적인 요청은 x, 행위 메시지로 보내는 게 맞는 것 같다.

... 헉 뒤에 바로 설명이 나오네... 

 

drunken(quantity)의 메세지를 보고 음료의 양이 줄어든다는 상태 메세지를 예상할 수 있겠는가? 메시지 송신자는 수신자의 상태 변경에 대해선 전혀 알지 못한다. 이것이 캡슐화가 의미하는 것이다.

객체는 상태를 캡슐 안에 감춰둔 채 외부로 노출하지 않는다. 객체가 외부에 노출하는 것은 행동뿐이며, 외부에서 객체에 접근할 수 있는 유일한 방법 역시 행동뿐이다.

 

메시지를 받고 객체의 상태를 변경할지 여부는 객체 스스로 결정한다.

 

상태를 외부에 노출시키지 않고 행동을 경계로 캡슐화하는 것은 결과적으로 객체의 자율성을 높인다. 자율적인 객체는 스스로 결정해서 지능도 높아진다. 결론적으로 잘정의된 행동 집합 뒤로 캡슐화하는 것은 객체의자율성을 높이고 협력을 단순하고 유연하게 만든다. (상태를 캡슐화 해야하는 이유)  

 

객체를 서로 구별할 수 있는 특정한 프로퍼티를 '식별자'라고 한다. 모든 객체는 식별자를 가지며 식별자를 이용해 객체를 구별할 수 있다. 값과 객체의 가장 큰 차이점은 값은 식별자를 가지지 않지만 객체는 식별자를 가진다는 점이다. 

값은 두 인스턴스의 상태가 같다면 두 인스턴스를 같은 것으로 판단한다. (두 개의 1이면 두 숫자는 같은 것.)(동등성)  객체는 가변 상태를 가진다. 단 두 객체의 상태가 다르더라도 식별자가 같다면 두 객체를 같은 객체로 판단할 수 있다. (동일성) 객체는 시간의 흐름에 따라 상태가 변하기 때문에 독립적인 별도의 식별자를 이용할 수밖에 없다.

 

행동이 상태를 결정한다

일반적으로 객체의 상태를 조회하는 작업을 쿼리라고 하고 상태를 변경하는 작업을 명령command라고 한다.

 

객체 지향에 갓 입문한 사람들이 빠지는 함정은 상태를 중심으로 객체를 바라보는 것이다. 먼저 객체에 필요한 상태가 무엇인지를 결정하고 그 상태에 필요한 행동들을 결정한다. 안타깝게도 상태를 먼저 결정하는 건 설계에 나쁜 영향을 끼친다.

1) 상태를 먼저 결정하면 캡슐화가 저해된다. 

2) 객체를 협력자가 아닌 고립된 섬으로 만든다. 

객체가 필요한 이유는 애플리케이션 문맥 내에서 다른 객체와 협력하기 위해서이다.

3) 객체의 재사용성이 저하된다.

협력이 아닌 상태에 초점을 맞추면 재사용성이 저하된다.

=> 상태가 아니라 행동에 초점을 맞춰야 한다.

 

객체지향 설계는 협력을 생각하고 협력에 필요한 행동을 생각하고 행동을 수행할 객체를 선택하는 식으로 수행된다. 행동을 결정한 후에야 무슨 정보가 필요한지 고려하며 상태가 결정된다. (행동이 상태를 결정한다.)

 

RDD (책임 주도 설계)는 협력이라는 문맥 안에서 행동을 생각하도록 도움으로써 응집도 높고 재사용 가능한 객체를 만들 수 있게 한다.

 

은유와 객체

'객체지향이란 현실 세계의 모방' <- 이것은 도시 전설이다.

객체지향을 현실 세계의 추상화(실제 사물에서 자신이 원하는 특성만 취하고 필요 없는 부분을 추려 핵심 표현)라고 한다. 그러나 객체지향은 현실 세계의 단순한 모방이 아닌다. 소프트웨어 안에 구현된 겍체는 실제 세계와 다른 양상을 띈다.

상품은 실제 상품이 하지 못하는 가격 계산을 할 수 있다. 이는 특성이 전혀 다른 어떤 것임을 나타낸다. 

현실과 소프트웨어 객체의 가장 큰 차이점은 현실 속에서는 수동적인 존재가 소프트웨어 객체로 구현될 때는 능동적으로 변한다는 것이다. (의인화)

 

객체지향 세계는 현실을 모방한 것이 아니라, 조금 참조할 뿐 궁극적인 목적은 현실과 전혀 다른 세계를 창조하는 것이다. 오히려 현실 속의 객체보다 더 많은 특징과 능력을 보유한 객체들로 넘쳐난다.

 

객체지향 설계자로써 우리는 현실을 모방하는 게 아니다. 현실을 닮아야 한다는 어떤 제약이나 구속도 없다.

 


가장 공감되었던 점: 메시지를 받고 객체의 상태를 변경할지 여부는 객체 스스로 결정한다.

현실과 소프트웨어 객체의 가장 큰 차이점은 현실 속에서는 수동적인 존재가 소프트웨어 객체로 구현될 때는 능동적으로 변한다는 것이다.

💡결국 중요한 말, 강조하고 싶은 말은 하나인 것 같다. 객체는 '스스로' 행동한다는 것.