[객체지향의 사실과 오해] 1장

2020. 4. 7. 21:46책/객체지향의 사실과 오해

객체지향적 프로그래밍에 대해 설명해보라

이 질문에 대한 답을 얻기위해, 많은 사람들의 의견을 들어보았고 검색도 해보았다.

그 사전적 의미를 나누어 객체가 무엇이고 지향하는것이 무엇이고 프로그래밍이 무엇인지를 이해했음에도 불구하고,

'객체지향적 프로그래밍'이 무엇인지 명쾌한 해답을 찾는것은 매우 힘들었다.

정답이 없는 질문일까?

누구도 반박할 수 없는 명쾌한 설명을 늘 기대하던 도중, 지인의 추천으로 이 책을 읽어보게 되었다.

챕터별로 감명깊게 읽은 부분과 느낀점을 작성하고, 다시 그 챕터를 읽을때마다 내용을 추가하고 수정해보려고 한다.

그러다 보면 조금이나마 이 질문에 대해 나만의 견해가 생길 수 있다는 기대 때문이다.

1장에 대한 내용을 정리하기 전에,

객체지향에는 많은 사람들이 동의하는 공통적인 특징이 있다.

추상화, 캡슐화, 상속, 다형성은 객체지향을 다른 패러다임과 구분하는 중요한 특징이다.

SOLID로 대표되는 몇가지 원칙들을 사용하면 훌륭한 객체지향 코드를 작성할 수 있다는 사실에 반박하는 개발자들은 그다지 많지 않다.

디자인 패턴 역시 많은 객체지향 프로그래머들이 유용하다고 생각하는 도구 중 하나이다.

그래서 객체지향은 무엇일까? 중요한 것은 이 질문에 대한 자신만의 견해를 가지는 것이다.

1장 협력하는 객체들의 공동체

시너지를 생각하라. 전체는 부분의 합보다 크다. - 스티븐 코비

1장에서는 커피를 주문하는 과정을 통해 객체지향에 대한 이해를 시도하였다.

손님, 캐시어, 바리스타는 각각 역할책임을 가지고 협력관계에 있다.

여기서 협력이란 요청과 응답으로 구성되어 있다.

'손님이 캐시어에게 커피를 주문하는것', '캐시어가 바리스타에게 커피를 제조하라고 시키는것' 은 요청이라고 볼 수 있다.

'바리스타가 캐시어에게 완성된 커피를 주는것', '캐시어가 손님에게 완성된 커피를 전달하는것' 은 응답이라고 볼 수 있다.

여기서 손님 역할을 맡은 사람은 커피를 주문할 책임을 이행한다.

캐시어 역할을 맡은 사람은 주문을 받는 책임과, 바리스타에게 커피제조를 시킬 책임, 완성된 커피를 손님에게 전달할 책임을 이행한다.

바리스타 역할을 맡은 사람은 커피제조의 책임과, 캐시어에게 완성된 커피를 전달할 책임을 이행한다.

*객체도 마찬가지이다. 각 객체는 각각의 역할이 있고 그에 따른 책임을 가지고 있다. *

이렇게, 역할과 그에따른 책임을 가진 여러 객체들은 서로 협력하여 하나의 기능을 만들어낸다.

이때 중요한 4가지 개념이 있다.

1. 여러 객체가 동일한 역할을 수행할 수 있다.

캐시어의 역할을 하는 사람이 누구이건, 주문을 받고 커피제조를 시키고, 완성된 커피를 손님에게 전달하는 책임을 다하면 된다.

객체도 마찬가지이다. 여러 객체가 한 메소드에 대한 자신만의 응답을 가지고 있을 수 있다.

2. 역할은 대체 가능성을 의미한다.

즉, 어떠한 역할을 할 객체는 여러개 일 수 있다.

3. 책임을 수행하는 방법은 자율적으로 선택할 수 있다.

바리스타가 커피를 제조해야하는 책임에 대하여 어떤 방식으로 커피를 제조할지는 본인이 스스로 결정할 수 있다. 이것을 객체지향 프로그래밍에서 생각해보면, 어떠한 메소드를 호출 받았을때 어떤식으로 응답을 할지는 그 객체에서 결정한다.

4. 한 객체가 동시에 여러 역할을 수행할 수 있다.

1번과 헷갈리는 말일 수 있다. 1번이 한 역할을 할 수 있는 객체가 여러개 일 수 있는것이면,

4번은 한 객체가 여러 역할을 할 수 있다는 것이다. 즉, 캐시어가 바리스타의 역할까지 할 수 있다는 것이다.

객체를 지향하라

훌륭한 객체지향 설계자가 되기 위해 거쳐야 할 첫 도전은 코드를 담는 클래스의 관점에서 메시지를 주고받는 객체의 관ㅂ점으로 사고의 중심을 전환하는 것이다.

중요한 것은 어떤 클래스가 필요한가가 아니라 어떤 객체들이 어떤 메시지를 주고받으며 협력하는가이다.

클래스는 객체들의 협력 관계를 코드로 옮기는 도구에 불과하다.

클래스의 구조와 메서드가 아니라 객체의 역할, 책임, 협력에 집중하자.

객체 지향은 객체를 지향하는 것이지 클래스를 지향하는 것이 아니다.

느낀점

간단한 애플리케이션을 구현할 때에도, 가장 먼저 어떠한 클래스를 만들지 고민하였다.

클래스는 객체를 코드로 옮기는 도구에 불과하다. 즉, 클래스가 붕어빵을 만드는 틀이라면 객체는 그곳에서 나오는 붕어빵이다.

커피제조 과정을 코드로 옮긴다고 가정했을때 나는,

손님 클래스, 캐시어 클래스, 바리스타 클래스를 만들고 그 안에 각각 필요한 필드와 메소드를 선언하고 정의할 것이다.

만든 클래스를 통해 손님 객체, 캐시어 객체, 바리스타 객체를 만들고 서로간의 메소드 호출을 통해 하나의 애플리케이션을 완성할 것이다.

어떠한 역할을 가지고, 어떠한 책임을 수행하는 객체를 만들것인가? 라는 생각과

어떠한 필드를 가지고, 어떠한 메소드를 수행하는 클래스를 만들것인가? 라는 생각의 차이는 종이 한장보다 얇아서 거의 동시에 생각이 이루어 지는 것 같다. 특히, 개발을 해야하는 입장에서는 오히려 후자가 더 먼저 떠오를지도 모른다.

위에 언급한 것처럼, 나 또한 자연스럽게 클래스를 먼저 생각하고 거기에서 객체를 뽑아 사용한다고 말하고 있다.

글을 적는 이 순간에도 헷갈린다...

붕어빵틀과 붕어빵의 관계임을 알면서도

'어떤 붕어빵이 필요한가?'를 생각하는 것과 '그 붕어빵을 만들어내는 틀을 어떻게 만들것인가'의 차이가 확실하게 와닿지 않는다.

클래스가 존재하는 자바라는 언어에 익숙해져서 일까?

자바스크립트 같은 프로토타입 기반의 객체지향 언어에서는 클래스가 존재하지 않으며 오직 객체만이 존재한다.

이러한 프로토타입 언어를 써보면 클래스를 지향하는것과 객체를 지향하는것의 차이를 더 잘 이해 할 수 있을까?

책을 더 읽고 그 답을 찾을 수 있으면 좋겠다.

1장 끝

.

.

.

.

.

.

책을 더 읽어보고 그 답을 찾을까 하다가, 도저히 궁금해서 책을 추천해준 분에게 여쭈어보고 답을 얻어냈다.

결론적으로 말하자면 bottom-up방식의 프로그래밍과 top-down방식의 프로그래밍의 차이와 비슷했다.

커피 제조로 예를들면 클래스 지향적인 개발은 우선 필요한 클래스를 모두 만든 후, 필요한 메소드와 필드를 그때그때 만들어가며 개발한다.

하지만 객체 지향적인 개발은, 우선 이 애플리케이션이 시작되는 객체 클래스만을 만든 후, 그 클래스 안에 필요한 작업들에 대해 코드를 적는다. 필요한 클래스를 그때그때 생성하는 것이 아니고 우선 시작되는 객체에 필요한 내용들을 모두 명시한 후, 그 내용들을 구현하기 위해 필요한 클래스를 생성해 나가는 방식이다.

말로는 참 모호했지만, 지인분이 친절하게도 직접 코드를 작성해 나가며 설명해주셨더니 이해가 한번에 갔다. 

이 개념이 헷갈릴땐, 뉴렉처님의 '자바 구조적인 프로그래밍' 에서 bottom-up 프로그래밍과 top-down 프로그래밍에 대한 강좌를 보면 좀더 이해하는데에 도움이 될 것같다.

이 과정에서, 상태보다 행동을 먼저 구현하라는 의미도 알게 되었다.

필드를 먼저 정의하지말고, 메소드를 먼저 설계한 후 이에 필요한 필드를 정의한다는 의미였다. 

사람마다 개발방식이 모두 다르겠지만, 직접 구현되는 코드들을 보며 확실히 위의 방식들은 설계를 함에 있어서 더 부드럽게 진행이 된다고 느꼈다.