<객체지향의 사실과 오해>를 읽고 알게된 충격적 사실들

포키·2022년 3월 4일
1

Books

목록 보기
1/1
post-thumbnail

(충격의 기준은 사람마다 다를 수 있습니다)

이 책, 속된 말로 ‘닉값 한다’. 읽는 내내 ‘내가 객체 지향에 대해 단단히 오해하고 있었군...’이라는 생각을 하게 했다. 깨진 나의 오해들, 다른 말로는 충격적인 사실들을 정리해봤다.

충격적인 사실 1. 객체는 현실의 모방이 아닌 은유다

처음 객체지향이라는 단어에 대해 배울 때, ‘현실을 프로그램 안으로 옮겨오는 개념’이라고 배웠고 나는 그 말을 곧이 곧대로 받아들였다. 그래서 우테코의 첫 미션인 자동차 경주 게임을 구현 할 때에도 ‘자동차는 움직이라면 움직일 뿐인데 Car.move()가 움직일 지 말지 판단하는게 어색하지 않나?’라는 생각을 했었다.

그러나 현실의 자동차와 다르게, 프로그램 안에서 Car 객체는 얼마든지 자율적일 수 있다. 그것은 내 손 끝에 달렸다. 현실을 모방해야 한다는 내 생각이 내가 만든 객체의 자율성을 제한하고 있었다.

객체는 현실의 모방이 아닌 은유다. 이 책에서는 ‘의인화’라고 표현한다. 무생물을 생물처럼 생각하고 설계하면 객체는 자율적이게 되고, 책임은 더욱 응집되고, 협력의 퀄리티는 좋아진다.

충격적인 사실 2. 구현과 인터페이스는 분리되어야 한다

나는 어떤 일을 시작할 때(개발 뿐 아니라 다른 일이라도) 처음부터 멀리까지 상상하는 버릇이 있다. 이 버릇이 좋은 것만은 아니라는 사실은 인식하고 있었지만, ‘처음부터 머리 속에서 다 돌려보면 금방 지치고 피곤해지니까’라는, 나의 체력 보전에 관한 아주 단순한 이유에서였다.

프로그래밍에서는 이러한 습관이 변화에 취약한 설계를 만든다. 협력하는 객체들은 서로에게 어떤 메세지를 던질지만 생각할 뿐, 그 내부에는 관심을 두지 않아야 한다. 그를 위해서는 각 객체가 스스로의 내부를 캡슐화 해야한다. 여기서 메세지는 인터페이스, 내부는 구현과 연결된다. 메세지에만 신경써도 되는 설계를 위해서 우리는 구현과 인터페이스를 분리해야 한다.

처음부터 구현을 상상하며 설계를 하면 구현이 인터페이스 내부로 쏙 들어가는 것이 아니라, 인터페이스가 구현에 영향을 받게 된다. 구현에 의존한 인터페이스 설계는 결국 메세지를 사용하는 곳에서 내부에 신경을 써야하는 상황을 만든다. 이 사실을 알고 나니, TDD Cycle이 가지는 이점이 더욱 와닿았다. TDD Cycle을 지키다 보면 자연스레 ‘무엇을’ 해야할 지를 먼저 생각한 후 ‘어떻게’ 구현해야 할 지는 그 후의 일이 된다. 객체를 사용하는 외부의 입장에서는 ‘무엇을’은 곧 메세지, ‘어떻게’는 곧 내부이며 객체 스스로에게 ‘무엇을’은 인터페이스, ‘어떻게’는 구현을 의미한다. 이 둘을 잘 분리한 설계는 변화에 빠르게 대응할 수 있는 구조를 만들어준다.

충격적인 사실 3. 상속이 꼭 대체가능성을 의미하지 않는다

이 책의 부록에서는 상속의 두 가지 용도를 소개하고 있다.

  • subtyping : subclass가 superclass를 대체할 수 있을 때
  • subclassing : subclass가 superclass를 대체할 수 없을 때

나는 Java에서 Class의 상속 관계가 무엇인지 개념만 알았지, 내 손으로 직접 설계하고 구현해본 경험이 많지 않다. 그래서 superclass를 대체하지 못할 가능성에 대해 고려해 본 적이 없다.

subclass가 superclass를 대체하려면, subclass가 superclass에 대해 행위적, 구조적으로 순응해야 한다. 구조적 순응이란 속성 및 다른 Class들과의 연관관계를, 행위적 순응이란 행위가 동일한 계약(행위의 결과가 동일한 기대값을 반환)을 기반으로 하는 것을 의미한다. 이는 설계를 유연하게 해준다.

그러나 단순히 코드의 중복 제거와 재사용만을 목표로 한다면 단지 코드만 공유하고 superclass는 대체할 수 없는 subclass를 구현할 수도 있다. 이 경우가 subclassing이다. subclassing보다는 subtyping의 목적으로 상속 관계를 만들 때 더 유연한 프로그램이 된다. 그러니 가능한 subtyping을 염두에 두는 것이 좋겠다.

사실 아직 경험이 없어서 완전히 와닿지는 않는다. 실제로 행위적, 구조적 순응을 만족하는 상속 관계를 구현해봐야 더 확실히 알 수 있을 것 같다.

충격적인 사실 4. 캡슐화는 Class 밖에서도 일어난다

부끄럽지만, 내가 생각한 캡슐화는 단순히 ‘접근 제한자로 외부의 접근을 막는 것’이었다. 그러나 이 책에서는 집합 간의 계층 관계를 통해 부분 집합 내의 요소들을 캡슐화할 수 있다고 말한다.

이 부분을 읽으며 내가 두 번째 미션인 로또 미션에서 구현한 일급 컬렉션을 떠올렸다. 내 프로그램에서 로또에 사용되는 번호는 LottoNumber라는 type을 가지고, 이를 6개 단위로 묶는 LottoNumbers라는 일급 컬렉션으로 결합되어 사용된다. LottoLottoNumber를 6개 가지는 것이 아니라 LottoNumbers를 하나 가지고 있다. 로또의 당첨 결과를 알고 싶거나, 특정한 번호가 포함되어 있는지 알고 싶으면 LottoNumbers에게 물어보면 된다. 외부에서는 각 LottoNumber에게 직접적으로 접근하지 않는다.

이 것 역시 LottoNumber 객체 자체에 대한 일종의 캡슐화임을, 이 책을 읽고서야 깨달았다. 내가 구현해 본 내용을 대입해서 이해하니 더 와닿았다.

객체 지향은 알면 알 수록 어렵다는 말의 뜻을 이제야 조금 알 것 같다. 이 말을 뒤집어보면, ‘아득해지기 시작했다는 것은 조금 더 알게 되었다는 것’이라 할 수 있겠다. 나의 깨달음이 깨달음에서 그치지 않고 코드의 변화로 이어지길 스스로에게 바라본다.

profile
항상 이유를 찾고 싶은 포키

4개의 댓글

comment-user-thumbnail
2022년 3월 4일

정말 기가막히고 코가 막히는 독후감이네요! 잘 읽고 갑니다.

1개의 답글
comment-user-thumbnail
2022년 3월 4일

정말 충격적인 사실이네요!! 큰 충격 받고 갑니다.

1개의 답글