▼ What ?
이 "이상한 나라의 객체" 라는 챕터에선 '객체의 특성' 과 '캡슐화' 를 "이상한 나라의 앨리스" 라는 이야기에 빗대어 설명하고, 객체를 생성할 때 어떤 점을 유의해야 하는지, 그리고 객체지향의 세계는 무엇이며 현실 세계와 어떤 관계가 있는지를 다루고 있다.
▼ Summory & Comment
이 챕터를 읽고 나서 기억에 남는 말 !
현실을 모방하는 것이 아니라, 이상한 나라를 창조하기만 하면 된다.
객체지향과 인지 능력
- 어린 아기들이 물체를 인지하는 방법을 연구한 결과로부터, 아기들조차 선천적으로 타고난 인지능력을 통해 본능적으로 세상을 식별 가능한 객체의 집합으로 바라본다는 사실을 알 수 있다.
➜ 직접적으로 보이는 것뿐만 아니라 개념적으로 경계 지을 수 있는 추상적인 사물까지도 객체로 인식 가능하다.
( 동일한 계좌로 동일한 금액을 두 번 이체하더라도 각 계좌이체를 구분 가능한 것처럼 ! ) - 객체지향의 패러다임은 인간이 인지할 수 있는 다양한 객체들이 모여 현실 세계를 이루듯이 소프트웨어의 세계도 인간이 인지할 수 있는 다양한 소프트웨어 객체들이 모여 이뤄져 있다는 것에서 시작 !
➜ 단, 현실 세계와 소프트웨어 세계 사이의 유사성은 여기까지 ! - 객체지향의 패러다임은 "현실 세계를 모방하는 것이 아닌 현실 세계를 기반으로 새로운 세계를 창조하는 것"
➜ 이게 무슨 말이며 왜 작가가 "이상한 나라의 앨리스" 이야기를 가져왔는지 이해했다면, 이 챕터에서 작가가 전달하고자 하는 바를 이해한 것이라 생각한다. - 현실 세계의 객체와 소프트웨어 세계의 객체는 다르다.
➜ 이 내용에 대해서도 이후에 더 자세히 다룬다. - 객체지향 애플리케이션은 겉으로 봤을 땐 현실 세계와 유사하나 내부를 들여다보면 본질적으론 매우 이질적인 모습의 세계가 나타난다는 점에서 마치 앨리스가 경험한 이상한 나라만큼이나 낯설고 기묘할 것이다.
객체, 그리고 이상한 나라
- 앨리스(객체)의 상태는 변경시키는 것은 앨리스의 행동(문을 통과)이다.
➜ 앨리스(객체)가 한 행동의 결과는 앨리스(객체)의 상태(앨리스의 키)에 의존적이며, 행동의 결과는 상태를 이용해 서술도 가능하다.
➜ 행동의 순서도 결과에 영향을 미친다. - 앨리스(객체)가 어떤 상태에 있더라도 유일하게 식별 가능하다.
( 앨리스는 어떤 상태에 있더라도 앨리스 ! )
➜ 왜 앨리스를 객체라 하는지를 이해하는 것이 중요하고, 이 정리를 기반으로 이번 챕터의 흐름이 흘러간다.
객체, 그리고 소프트웨어 나라
- 상태(state), 행동(behavior), 식별자(identity)를 가진다면 어떤 실체도 객체가 될 수 있다.
상태 (state)
- "상태(state)" 라는 것이 왜 필요할까?
➜ 어떤 행동의 결과는 과거에 어떤 행동들이 일어났는지에 의존한다.
하지만, 과거에 발생한 행동들의 이력을 통해 현재 발생한 행동의 결과를 예상하는 것은 너무 어렵다.
( 앨리스가 문을 통과하기 전에 했던 모든 행동들(음료, 케이크, 부채, 버섯 등)을 기억해야 문을 통과한 결과를 도출 가능한 것처럼 ! )
➜ 이를 해결하기 위해 등장한 것이 상태(state)이다. - 상태(앨리스의 키, 문의 높이)를 알면 과거에 얽매이지 않고 현재를 기반으로 (객체의) 행동의 결과 예측 가능하다.
➜ 문의 높이 ?
앨리스가 물을 통과하는 과정 속에 있던 케이크, 음료, 부채, 그리고 토끼, 문까지도 모두 객체이다.
( 식별 가능하며, 상태와 행동 모두 가능하기 때문 ! ) - 그렇다면, 식별 가능하면 객체인가? NO!
➜ 앨리스의 키, 음료와 케이크의 양, 문이 열려있는지의 여부 등과 같은 단순한 "값" 은 객체 자체가 아닌 객체의 상태를 표현하기 위한 수단 - 앨리스의 상태를 구성하는 단순한 값과 객체 모두를 객체의 프로퍼티(property)라 칭한다.
➜ 객체의 프로퍼티(property)는 정적(키, 위치, 음료)이고, 프로퍼티 값(property value)는 동적(키의 값, 위치의 값, 음료의 양)이다.
- 앨리스(객체)가 음료수(객체)를 마시기 위해 들고 있는 모습
➜ 객체의 상태는 앞서 말한 프로퍼티가 아닌 다른 객체를 사용해서도 표현 가능하다는 것을 알 수 있다.
➜ 이때 앨리스와 음료수는 링크(link)되어 있다.
- 앨리스가 음료수를 다 마시면, 앨리스의 키는 줄고 위치는 정원으로 바뀌며 음료는 버릴 것이다.
➜ 그럼, 앨리스라는 객체는 음료수라는 객체를 알지 못하는 상태로 변경되는 것이다 ! ( 캡슐화? )
- 앨리스가 음료수를 다 마시면, 앨리스의 키는 줄고 위치는 정원으로 바뀌며 음료는 버릴 것이다.
- 링크(Link)는 객체가 다른 객체를 참조할 수 있다는 것을 의미하는 동시에, 한 객체(앨리스)가 다른 객체(음료수)의 식별자를 알고 있다는 것을 의미한다 !
➜ 객체의 프로퍼티(property)는 "객체를 구성하는 단순한 값을 의미하는 속성(attribute)" 과 "다른 객체(음료)를 참조하는 링크"로 표현될 수 있다.
( 단순한 값으로 표현될 수 있는 키와 위치는 속성에 해당한다 ! )
- 앨리스(객체)가 음료수(객체)를 마시기 위해 들고 있는 모습
- 객체는 상태를 간접적으로 변경할 수 있는 방법이 필요하다.
➜ 이 방법이 바로 "행동" 이다 !
간접적으로 변경 ?
➜ 외부 객체의 행동이 아닌 스스로의 행동에 의해서만 상태가 변경되도록 하여 객체의 자율성을 유지 !
행동
- 행동은 상태에 의존하는 동시에 상태를 변경할 수 있다.
➜ 행동과 상태는 서로에게 영향을 주는 관계 ! - 상태를 이용해 복잡한 객체의 행동을 아래와 같은 접근 방식에 따라 간단하게 서술할 수 있다.
상호작용이 현재 상태에 어떤 방식으로 의존하며 현재의 상태를 어떻게 변경시키는가?
➜ '앨리스의 키가 40cm 이하라면 문을 통과할 수 있다.' ( '키'와 '위치' 라는 두 가지 상태를 이용 )
만약 상태가 없다면 ?
➜ 앨리스가 과거에 음료수를 마셨는지, 케이크는 얼마나 먹었는지, 부채질은 얼마나 했는지 등의 과거의 행동들을 기억해서 문을 통과한 결과를 복잡하게 서술해야 한다. - 이 책의 1장인 '협력하는 객체들의 공동체' 에서도 객체들이 협력할 수 있는 유일한 방법은 요청 메시지 뿐이라고 했었다.
➜ 2장에선 "행동이란 외부의 요청 또는 수신된 메시지에 응답하기 위해 동작하고 반응하는 활동" 이라 적혀있듯이, 객체들이 협력할 수 있는 유일한 방법은 곧 행동이라 할 수 있다 ! - 행동으로 발생하는 두 가지의 부수 효과(side effect)
- 객체 자신의 상태를 변경.
- 행동을 통해 협력하는 다른 객체에 대한 메시지 전송. (요청)
➜ 이 부분은 다른 객체와의 협력에 참여하므로 외부에 가시적이어야 함
- 객체 자신의 상태를 변경.
- 상태 캡슐화
음료의 양이 줄여 상태를 변경시키는 주체
- 현실 세계 ➜ 음료를 마신 앨리스.
- 객체지향 세계 ➜ 음료 객체. ( 자신의 상태를 변경할 수 있는 것 오직 자신 뿐 )
앨리스 객체는 drinkBeverage() 메시지를 전달받고, 음료를 마신 만큼 음료의 양을 줄여달라고 drunken(quantity) 메시지를 음료 객체에 전송한다.
➜ 앨리스 객체는 요청만 할 뿐 음료 객체가 상태 변경을 할지는 알 수 없다 ! ( 캡슐화 )
➜ 메시지를 받은 음료 객체가 스스로 음료의 양을 줄일 것인지 판단하여 행동한다. ( 객체의 자율성 보장 )
➜ 각각의 객체들은 메시지를 송 · 수신하기만 하면 되기 때문에 협력을 단순하고 유연하게 만든다 !
- 현실 세계 ➜ 음료를 마신 앨리스.
식별자
- 식별자 ?
➜ 어떤 객체를 다른 객체와 구별할 수 있게 해주는 해당 객체의 특정 프로퍼티 - 단순한 "값" 은 불변 상태(immutable state)
➜ 따라서, 상태가 같으면 두 인스턴스는 동일한 것으로 인식 가능하다.
➜ 동등성(equality) 검사
ex) 1은 1, 1만원은 1만원 - "객체" 는 가변 상태(mutable state)
( 객체는 시간에 따라 변할 수도, 행동에 의해 변경될 수도 있는 상태도 가지기 때문에 ! )
➜ 상태를 기준으로 같은 객체라고 판단 X
➜ 상태 변경에 의존성이 없는 식별자를 이용하여 판단
➜ 동일성(identical) 검사
ex) 앨리스와 키가 같고 이름도 같은 사람이 있어도 앨리스와 그 사람은 같은 사람이라 생각 안하는 것처럼, 객체도 마찬가지로 모든 상태가 같아도 같은 객체라 할 수 없다. - 모든 객체는 식별자를 가진다.
➜ 단순한 값은 식별자를 가지지 못한다.
➜ 이것이 객체와 값의 가장 큰 차이점이다 !
상태가 변하지 않기 때문에 식별자가 필요없는 "값", 반대로 상태가 변할 수 있어 식별자가 필요한 "객체", 즉 식별자가 있냐 없냐를 기준으로 "값" 과 "객체" 를 구분할 수 있다.
하지만, 객체지향 프로그래밍에선 "값" 과 "객체" 를 모두 클래스를 이용해 구현하기 때문에 문맥에 따라 의미가 다소 혼란스러울 수 있다.
➜ 이러한 오해의 소지를 줄이기 위한 용어 있다.
- 식별자가 없는 값 객체(value object)
vs 식별자가 있는 객체는 참조 객체(reference object) 또는 엔티티(entity)
➜ 객체지향 프로그래밍을 하는 것에 있어서 위처럼 "값"과 "객체" 를 명확하게 구분하고 명시적으로 표현할 수 있는지는 매우 중요하다 !
( 그 이유는 ▼Study를 참고 )
➜ 따라서 "식별자"라는 개념도 늘 객체지향 하면 언급되던 상속, 캡슐화, 다형성과 같은 개념만큼이나 매우 중요 !
- 식별자가 없는 값 객체(value object)
기계로서의 객체 - 은유
- 앞서 나열한 객체의 모든 특성을 좀더 쉽게 이해할 수 있게 도와주는 개념이 바로 우리가 흔히 아는 "은유" 이다 !
- 마이어가 제시한 기계 은유 ( 앞서 앨리스를 객체로 생각하는 것에 모티브가 되는 방식 )
➜ 객체 기계에 상태를 변경하는 명령에 해당하는 사각형 버튼, 상태를 조회하는 쿼리에 해당하는 둥근 버튼만 존재.
( 동시에 이 버튼들은 객체가 외부에 제공하는 행동이라는 점을 기억하자! )
여기서 중요한 점은 사용자인 우리는 객체 기계가 제공한 버튼 즉, 객체가 제공한 행동을 통해서만 해당 객체에 접근해 상태를 간접접으로 변경시킬 수 있다는 것이다 !
- 우리는 기계가 어떠한 원리와 구조로 작동하는지는 열어보기 전까진 알 수 없다는 점 ➜ 캡슐화
- 디스플레이창에 동일하게 자신의 상태를 표현하는 숫자 130을 출력하고 있는 2개의 기계가 있어도 우린 두 기계가 같다고 생각 X
➜ 식별자 개념도 확인 가능 ! - 두 기계를 연결(link)시킨 후 우리가 한 쪽의 기계의 버튼(음악 재생)을 눌러 메시지를 수신한 기계가 다른 기계에 어떠한 버튼(음악 정지)을 누르라는 요청 메시지를 전송했다.
➜ 메시지 전송을 통해 협력하는 객체들의 관계도 쉽게 이해할 수 있다.
- 우리는 기계가 어떠한 원리와 구조로 작동하는지는 열어보기 전까진 알 수 없다는 점 ➜ 캡슐화
행동이 상태를 결정한다
- Bad choice
: 객체에 필요한 상태를 먼저 생각하고 그 상태를 위한 행동을 결정하는 것
➜ 앨리스 객체에게 필요한 상태(키, 위치)를 먼저 일단 결정하고, 그 상태를 행동(문에 들어가기)에 적합한 상태가 되도록 변경하려는 것과 같다.
이로 인해 발생하는 나쁜 영향 3가지
- 상태를 먼저 결정할 경우엔 객체 내부에 캡슐화되는 것이 아닌 공용 인터페이스에 노출될 확률이 증가한다.
➜ 캡슐화 X - 객체의 상태를 먼저 고려하면 다른 객체와의 협력에 적합하지 못한 객체가 탄생하게 되고, 애플리케이션에서 협력을 위해 존재하는 객체의 용도에 모순된 상황이 발생하는 것이다.
- 상태에 초점을 맞췄기 때문에 다양한 협력에 참여하지 못하는 것은 당연하기에 재사용성도 떨어지게 된다.
- 상태를 먼저 결정할 경우엔 객체 내부에 캡슐화되는 것이 아닌 공용 인터페이스에 노출될 확률이 증가한다.
- 어떠한 상태를 가지는 객체를 탐색하는 것이 아니라, 필요한 행동을 먼저 생각하고 그 행동을 수행해줄 만한 객체를 탐색하거나 생성해주자 !
➜ 그렇게 행동을 먼저 결정짓고 난 이후에서야 그 행동에 적합한 상태를 선택하는 것이다 ! - "협력하는 객체들의 공동체" 에서도 다뤘듯이 행동을 결정한다는 것은 곧 그 객체에게 책임을 부여한다는 것이고, 따라서 어떤 행동이 필요한가라는 고민은 어떤 책임이 필요한가라는 생각으로 자연스레 이어진다.
➜ 이러한 과정을 거친 설계를 "책임-주도 설계(Responsibility-Driven Desing, RDD)" 라고 할 수 있다.
➜ 이러한 설계를 통해 협력에 있어서 적합한 객체, 즉 우리가 객체를 필요로 하는 이유에 걸맞는 객체를 생성해낼 수 있게 되는 것 ! - 앞서 다룬 모든 내용들은 "행동이 상태를 결정한다." 라는 말을 전하기 위한 빌드업이다 !
은유와 객체
- 1장에서 "객체가 아닌 클래스가 객체지향의 핵심"이라는 객체지향의 오래된 도시전설 한 가지를 다뤘듯이, 여기선 "객체지향이란 현실 세계의 모방" 이라는 도시전설을 다루고 있다.
➜ 객체지향을 현실 세계를 추상화(abstraction)한 모습이라 말하며, 현실 세계를 면밀히 관찰해 그 안에 존재하는 실제 객체들의 특징을 잘 파악해 소프트웨어 객체로 추상화할 수 있는 능력이 중요하다는 생각이 뿌리 깊게 박혀있다
( 놀랍게도 객체지향 분석/설계에 대한 전통적인 조언도 이와 같은 말을 해주고 있다는 것이다. ) - 1장에서도 충분히 언급했듯이 객체지향을 설명하기 위한 가장 쉬운 방법이 현실 세계에 빗대어 이야기하는 것일 뿐, 객체지향 세계는 현실 세계의 단순한 모방이 아니다 !
의인화
- 앞서 언급했던 소프트웨어 세계의 음료수 객체와 현실 세계의 실제 음료수를 생각해보자.
- 현실 세계의 실제 음료수 ?
➜ 사람과 같은 생명체의 도움 없이는 바닥에 쏟을수도 마셔질수도 없는 수동적인 존재이다. - 반대로 소프트웨어에서의 음료수 객체 ?
➜ 스스로 음료수의 양, 즉 자신의 상태를 변경할 수 있는 능동적인 존재이다 !
- 현실 세계의 실제 음료수 ?
- 이처럼, 소프트웨어 객체를 창조하면 현실의 객체보다 더 많은 일(수동적 ➜ 능동적)을 할 수 있게 되는데, 이러한 소프트웨어 객체의 특징을 "의인화(anthropomorphism)" 라고 한다.
➜ 쉽게 말해, 소프트웨어 객체의 특징인 "의인화"는 현실 세계에선 존재하지 않는 것들도 사람처럼 생명을 가진 존재로 재탄생시킬 수 있다는 것을 의미한다.
➜ 게다가 눈에 보이지 않는 공기와 바람도 소프트웨어 안에선 가시적으로 나타날 수 있다.
( 흔히, 우리가 아는 의인화는 "사람이 아닌 것을 사람에 빗대어 표현하는 것" 을 의미하는데, 여기서 사람에 빗대어 표현한다는 점으로부터 영감을 받아 앞서 말한 특징을 "의인화 라고 정의해준 것 같다. )
은유
- 객체지향의 세계와 현실 세계가 전혀 관계가 없다는 것은 아니다 !
단지 모방이나 추상화의 수준이 아닌 다른 관점에서 유사성을 갖고 있는 것일 뿐이다.
➜ 이러한 객체지향의 세계와 현실 세계 간의 유사성을 나타내는 관계를 설명해줄 수 있는 단어가 "은유(metaphor)"이다 ! - "은유" 는 실제로는 적용되지 않는 한 가지 개념을 이용해 다른 개념을 서술하는 대화의 한 형태이다.
➜ 은유의 본질은 한 종류의 사물(객체지향의 세계)을 다른 종류의 사물 관점(현실 세계)에서 이해하고 경험하는 데 있다 !
예를 들어, 스스로 전화를 걸 수는 없지만 우리가 익히 알고 있는 현실 세계의 전화기라는 개념을 이용해 소프트웨어 객체를 묘사했을 때, 소프트웨어에서의 전화기 객체는 스스로 전화를 걸 수 있는 능력이 있다고 은유하면 소프트웨어 객체의 개념을 쉽게 이해할 수 있게 되는 것!
➜ 1장에서 현실 세계의 객체의 이름을 소프트웨어 객체에 부여해 설명해준 이유가 바로 이러한 은유의 장점 때문이다 !
저자가 2장에서 "이상한 나라의 앨리스" 라는 이야기를 가져온 이유도, 해당 이야기에서도 현실 세계에서 우리에게 친숙한 트럼프 카드가 움직이고 고양이와 토끼가 사람처럼 두 발로 움직이는 등 "이상한 나라의 앨리스" 자체가 현실 세계의 객체로 "이상한 나라" 라는 새로운 세계의 객체를 은유를 통해 묘사하고 있기 때문이다.
▼ Study
식별자는 엔티티?
- 식별자는 스프링(Spring)에서 다루는 엔티티(Entity) 개념과 유사한 것 같다.
➜ 엔티티들은 'id' 라는 프로퍼티로 구별되고 이 id가 여기서 말하는 식별자라 할 수 있다 !
프로퍼티(property)와 속성(attribute)을 구분하자
- "객체의 프로퍼티(property)는 객체를 구성하는 단순한 값을 의미하는 '속성(attribute)'과 다른 객체를 참조하는 '링크(link)'로 표현될 수 있다." 라는 말에서 속성은 property가 아닌 attribute, 즉 변하지 않는 불변(immutable)을 의미한다는 것을 이해하는 것이 중요한 것 같다.
Java에서의 동등성(equality) vs 동일성(identical)
동일성(identical)
String str1 = "string";
String str2 = "string";
String str3 = new String("string");
System.out.println(str1 == str2); // true
System.out.println(str1 == str3); // false
🔻 "string" 이라는 문자열 리터럴을 사용해서 객체를 생성해주면, 이 "string" 은 객체들이 저장되는 Heap 영역이 아닌 String Constant Pool이라는 메모리 영역에 저장된다.
➜ 따라서, 위처럼 생성된 객체인 str1과 str2는 String Constant Pool에 저장된 객체의 메모리 주소가 저장된 것이기 때문에, 사실 둘 다 같은 객체를 가리키고 있는 것이고 간단하게 말하면 엘리스가 이름으로 바꾼 것이나 다름 없다.
➜ 자연스럽게 메모리 주소값을 비교하는 연산자 '==' 는 true를 반환하게 된다 !
( 사실, 쉽게 말해서 객체라고 하는 것이지 str1, st2, str3는 모두 객체의 주소가 저장된 참조 변수, 즉 인스턴스라 하는 것이이 정확한 말이긴 하다. )
➜ 이로써 이 책에서 말하는 "동일성(identical)" 을 Java에서 검사하는 방법은 연산자 "==" 를 이용것이다.
➜ 연산자 "==" 을 이용하여 비교했을 때 'true' 가 반환된다면, 두 객체는 같은 객체이며 동일성(indentical) 관계를 이루고 있다고 할 수 있다.
➜ Java에서의 식별자는 "메모리 주소" 라고 할 수 있을 것 같다 !
동등성(equality)
String str3 = new String("string");
String str4 = new String("string");
System.out.println(str3 == str4); // false
System.out.println(str3.equals(str4)); // true
🔻 new 생성자를 이용해 생성한 객체의 주소를 담고 있는 str2와 str3는 서로 다른 객체의 주소를 저장하고 있다 !
➜ Java에서 식별자라고 할 수 있는 메모리 주소가 다른 객체는 동일성(identical)에 어긋난다고 할 수 있다.
➜ 그래서 두 인스턴스에 저장된 단순한 불변 상태의 "값" 으로 같은지 비교하고 싶다면 동일성(indentical)이 아닌 "동등성(equality)" 검사를 해야 한다.
➜ 따라서, 'str3 == str3' 는 식별자를 이용해 비교하기 때문에 당연히 false를 반환하게 되는데, 'str2.eqauls(str3)' 는 true를 반환하고 있는 것을 확인할 수 있다 !
➜ 이로써 Java의 메서드 'equals()' 는 이 책에서 말하는 "동등성(equality)" 을 체크하는 역할임을 알 수 있다 !
➜ equals 메서드는 객체의 주소(식별자)가 아닌 해당 객체의 상태, 즉 단순한 "값" 을 비교하기 때문에 동등한 인스턴스으로 인식하고 있는 것이다.
Issue_1
앨리스가 문을 통과할 수 있는지는 앨리스의 키가 현재 몇 센티미터인지에 달려 있다. 앨리스의 키가 문보다 크다면 문을 통과할 수 없을 것이다.
이 부분이 객체의 행동은 상태에 영향을 받는것과 관계가 있는 것 같은데, 문을 통과한다는 행동의 실현 가능 여부가 상태에 영향을 받는다고 생각하면 되는 걸까요?
- 과거의 모든 행동들을 설명하지 않고도 현재의 상태만으로 행동의 결과를 예측할 수 있다고 했듯이, 앨리스 객체의 상태인 키가 문을 통과한다는 행동의 결과, 즉 행동의 실현 가능 여부에 영향을 미친다고 볼 수 있을 것 같습니다.
Issue_2
상호작용이 현재의 상태에 어떤 방식으로 의존하는가
상호작용이 어떻게 현재의 상태를 변경시키는가
상태라는 개념을 이용해 행동을 간단하게 서술하기 하기 위한 두 가지 관점을 다룬 내용인데, 이 부분에서 말하는 상호작용이 앨리스가 문을 통과하는 행동이 할 때 이 행동으로 인해 발생하는 '앨리스'라는 객체와 '문'이라는 객체 사이의 상호작용을 말하는 것일까요?
- 앨리스가 문을 통과하는 행동을 상호작용으로 치환해서 단순하게 생각하면 될 것 같습니다.
Issue_3
실제 프로그래밍에서 값과 객체 두 개념 모두 클래스를 이용해 구현된다. 문맥에 따라 그 의미가 혼란스러울 수 있다. 객체지향 프로그래밍 언어를 이용하면 숫자는 Integer라는 클래스로, 사람은 Person이라는 클래스로 정의될 수 밖에 없다. 따라서 프로그래밍 언어의 관점에서 숫자는 Integer 클래스로부터 생성된 객체이며, 사람은 Person 클래스로부터 생성된 객체다.
여기서 숫자는 값, 사람은 객체 아닌가요? 왜 둘 다 객체라고 하나요? 값은 객체인데 식별자가 없는 객체라고 이해하면 되는걸까요?
- int, float, double 과 같은 기본형(Primitive) 타입에 해당하는 값은 이때는 객체가 아니라 이 책에서 언급했던 "불변 상태"에 있는 단순한 "값"에 해당하는 것이 맞습니다. 하지만 저 글에서 말하는 것처럼 객체지향 언어에선 '숫자'도 일반 객체처럼 "가변 상태"에 있는 객체로 사용되는 경우도 있기 때문에 혼란스러울 수 있는 점을 완화하기 위해, "객체"를 식별자를 지닌 객체(참조 객체), "값"을 식별자를 가지지 않는 객체(값 객체)라 추가적으로 별도의 용어를 지정해줬다고 합니다. 그래서 저기서 말하는 값은 식별자가 없는 객체라고 이해하면 될 것 같다고 생각합니다.
Issue_4
모든 객체의 상태는 단순한 값과 객체의 조합으로 표현할 수 있다. 이때 객체의 상태를 구성하는 모든 특징을 통틀어 객체의 프로퍼티(property)라고 한다. 앨리스의 경우 키, 위치, 음료가 앨리스의 프로퍼티가 된다. 일반적으로 프로퍼티는 변경되지 않고 고정되기 때문에 '정적'이다. 반면 프로퍼티 값(property value)은 시간이 흐름에 따라 변경되기 때문에 '동적'이다.
프로퍼티가 정적이라고 말하는데, 프로퍼티에 해당하는 키, 위치, 음료는 변할 수 있는 값이 아닌가요? 그리고 키나 위치의 값과 같은 것이 프로퍼티 값이라고 생각했는데, 프로퍼티 값이 '동적'이라면 불변(immutable)이라 했던 "값"이 프로퍼티 값에 해당되지 못하는 것인가요?
- 키, 위치, 음료가 앨리스의 프로퍼티가 되며 '정적'이라는 것은 이것들 자체가 앨리스가 갖고 있는 항목이기 때문에 잘 변경되지 않고 고정된다고 말하는 것 같습니다. 키나 위치에 해당하는 값은 ;프로퍼티 값(property value);이 맞다고 생각합니다. 키의 값이나 위치의 값이 이 책에서 말하는 불변(immutable)의 특징이 있는 "값"에 해당하는 것이 맞습니다. 하지만, 이 부분에서 다루는 '동적'이라는 개념은 "키가 1.5m에서 40cm로 바뀔 수 있다."는 것을 말하는 것 같고, "단순한 값"이 갖고 있는 '불변(immutable)'이라는 개념은 "40cm는 40cm이고 1L는 1L이다."는 것을 말하는 것이라 생각합니다.
따라서, 프로퍼티 값이 '동적'이라고 해서 '불변'이라고 하는 "단순한 값(키 값, 위치 값)"이 '프로퍼티 값(property value)'이 되지 못할 이유는 없다고 생각합니다.
Issue_5
객체지향프로그래밍 언어에서 숫자는 Integer라는 클래스로 정의하고 이를 "값 객체"라는 용어라고 정의했는데, 이는 참조 객체 또는 엔티티와는 다른 어떤 역할을 하게 되는지 궁금합니다 !
- "값 객체(Value Obejct)"와 대조되는 "엔티티(Entity)" 를 먼저 생각해보면, "엔티티" 는 언제나 상태(property)가 변할 수 있는 가변(mutable) 객체이기 때문에 기본적으로 'id' 라는 식별자로 동일성(identical)을 판단할 수 있습니다. 하지만, "값 객체" 는 한 번 생성되면 다신 바뀌지 않는 불변(immutable) 객체이기 때문에, 객체이긴 하지만 식별자로 동일성(identical)을 판단할 수 없습니다. 그리고 값을 변경하고 싶다면 다른 값 객체로 대체되어야 한다는 점 덕분에, 엔티티와 달리 값 객체는 상태가 같은 값 객체라면 무엇이든 교체 가능해 자유롭다는 장점이 있습니다. 반대로, 엔티티는 상태가 바뀌어도 여전히 같은 엔티티라는 장점도 있습니다.
이러한 특징들로 인해 "값 객체" 와 "엔티티" 를 구분하는 것이 객체지향 프로그래밍에서 큰 영향을 미치기 때문에 매우 중요하고, 애플리케이션을 어떻게 사용할 것인가에 따라 "값 객체" 또는 "엔티티" 중 무엇을 생성할지가 결정된다고 합니다!
두 가지 예를 들면, GPS 기능을 하는 애플리케이션이라면 위치 객체가 어떤 값을 담고 있는지만 중요하기 때문에, 이때는 위치 객체를 "값 객체" 로 생성해줍니다. 근데 위험 구역에 쳐진 철책에서 누군가 들어오는지 감시하는 애플리케이션이라면, 앞선 예시와 달리 특정 범위 내에서 사람이 들어오는지만 확인하면 되기 때문에 철책 주변의 위치 객체는 "엔티티" 로 생성해줘야 합니다 . 그리고 흔히 "엔티티" 라고 생각하는 사람 객체는, 어떤 사람인지 상관없이 누군가 감시중인 구역에 들어오는지만 궁금하기 때문에 "값 객체" 로 생성해주는 것이 적합합니다.