추상화, 캡슐화, 상속, 다형성 등 이 요소들은 객체지향을 다른 패러다임과 구분하는 중요한 특징입니다.
SOLID 원칙으로 훌륭한 객체지향 코드를 작성할 수 있다는 사실에 반박하는 개발자는 많지 않습니다.
반복적으로 발생하는 문제와 해법의 쌍을 일컫는 디자인 패턴 역시 유용하게 생각합니다.
그래서 객체지향이란 무엇일까요?
이 질문에 정답은 존재하지 않지만, 중요한 사실은 우리는 객체지향에 대해 자신있게 대답하지 못한다는 점에 있는 것 같다. 실제로 상속이 무엇인지는 대답을 할 수 있지만 “일반화”가 무엇인지는 대답하지 못하는 개발자가 은근 있다. 말 그대로 객체를 지향한다는 사실을 잘 알고 있으면서도 여전히 클래스나 상속을 중심으로 객체지향을 바라보고 있다.
객체지향 관점을 보는 방법
객체지향으로 향하는 첫 걸음은 클래스가 아니라 객체를 바라보는 것에서 부터 시작합니다. 객체지향으로 향하는 두 번째 걸음은 객체를 독립적인 존재가 아니라 기능을 구현하기 위해 협력하는 공동체의 존재로 바라보는 것이다. 객체지향으로 향하는 세 번째 걸음은 협력에 참여하는 객체들에게 얼마나 적절한 역할과 책임을 부여할 수 있느냐에 달려있습니다. 객체지향으로 향하는 마지막 걸음은 앞에서 설명한 개념들을 프로그래밍이라는 언어의 틀에 흐트러짐 없이 담아낼 수 있는 기술을 익히는 것입니다.
이 책을 읽는방법
이 책의 집필 의도는 객체지향 프로그래밍에 대한 구체적이고 상세한 지식을 “전달”하는 목적이 아니라는 것을 알고 있자. 이 책은 객체지향을 다루는 다른 책이나 자료들을 읽을 때 미리 알고 있으면 도움이 될만한 기본 배경과 지식을 다루는 책이다. 이 책을 읽고 나면 객체지향을 바라보는 우리의 시야가 깊어지는 동시에 넓어질 것은 확신한다 !
페이지를 한장 한장 읽을 때 마다 지금까지 프로그래밍을 했던 기억을 떠올리며 “그게 이런 의미였구나”, “그래서 이 언어가 그런 방식으로 설계가 되었구나”라는 생각을 하도록 만드는 것이다.
내가 지금까지 해왔던 기억을 떠올리면서 읽자!
1장 - 협력하는 객체들의 공동체
1장의 주제는 객체지향 패러다임의 핵심이 자율적인 객체들의 협력이라는 사실을 강조합니다. 지금까지 객체지향의 중심이 클래스나 상속이라고 생각했던 사람들은 1장을 읽고 약간의 당혹감을 느낄 수 있는 챕터이다.
객체지향이라고 불리는 새로운 세상의 문을 연 대부분의 사람들은 “객체지향이란 실세계를 직접적이고 직관적으로 모델링 할 수 있는 패러다임” 이라는 설명과 마주하게 된다.
패러다임 : 한 시대 사람들의 견해나 사고를 근본적으로 규정하고 있는 테두리로서의 인식의 체계, 사물에 대한 이론적인 틀이나 체계를 의미하는 개념
이런식의 설명이 전달하고자 하는 핵심은 객체지향 프로그래밍이란 현실 속에 존재하는 사물을 최대한 유사하게 모방해 소프트웨어 내부로 옮겨오는 작업이기 때문에 그 결과물인 객체지향 소프트웨어는 실세계의 투영이며, 객체란 현실 세계에 존재하는 사물에 대한 추상화 라는 것이다.
역할과 책임
사람들은 다른 사람과 협력하는 과정에서 특정한 역할을 부여받는다.
커피를 제조하기 위해 캐시어와 바리스타가 협력하는 과정에서 손님, 캐시어, 바리스타라는 역할이 존재한다.
역할이란?
어떤 협력에 참여하는 특정한 사람이 협력 안에서 차지하는 책임이나 임무를 의미한다.
손님 : 커피를 주문하자 !
캐시어 : 주문을 받자 !
바리스타 : 커피를 제조하자 !
책임이란?
역할이라는 단어는 의미적으로 책임이라는 개념을 내포하고 있다.
선생님은 학생을 가르칠 책임이 있다.
특정한 역할은 특정한 책임을 암시한다.
협력에 참여하며 특정한 역할을 수행하는 사람들은 역할에 적합한 책임을 수행하게 된다.
손님 : 커피를 주문할 책임이 있다.
캐시어 : 주문 내용을 바리스타에게 전달하고 커피가 준비되었다는 사실을 손님에게 알릴 책임이 있다.
바리스타 : 커피를 제조할 책임이 있다.
사람들이 협력을 위해 특정한 역할을 맡고 역할에 적합한 책임을 수행한다는 사실은 몇가지 중요한 개념을 제시한다.
여러 사람이 동일한 역할을 수행할 수 있다.
손님 입장에서 자신이 주문한 커피를 마실 수만 있다면 어떤 캐시어가 주문을 받는지는 상관이 없다.
캐시어의 입장에서 자신이 전달한 주문 내역에 맞게 커피를 제조할 수 있다면 어떤 바리스타가 커피를 제조하더라도 크게 상관이 없다.
만약 캐시어가 카페를 그만둔다면 캐시어라는 역할에 따르는 책임을 수행할 수 있는 다른 사람을 고용하면 되는 것이다.
손님은 오늘의 캐시어가 어제의 그 캐시어가 아니더라도 크게 개의치 않을 것이다.
결국 손님 입장에서는 캐시어가 주문을 받고 커피가 완성됐다는 사실을 통보하는 책임을 성실히 수행할 수 만 있다면 그만이다.
역할은 대체 가능성을 의미한다.
손님 입장에서 캐시어는 대체가능 하다. 좀 더 정확하게 말하면 두명이 동일한 역할을 수행할 수 있다면 요청자 입장에서 둘 중 어떤 사람이 역할을 수행하더라도 크게 문제되지 않는다.
책임을 수행하는 방법은 자율적으로 선택할 수 있다.
요청을 받은 사람들은 요청을 처리하는 방법을 자유롭게 선택할 수 있다.
커피 제조를 요청받은 바리스타는 자신만의 독특한 방법으로 커피를 제조할 수 있다.
어떤 바리스타는 카푸치노의 거품을 이용해 아름다운 무늬를 만들기도 하고 어떤 바리스타는 커피 향을 더 향기롭게 만드는 방법을 알지도 모른다.
중요한 것은 커피를 제조하라는 동일한 요청을 받더라도 바리스타의 역할을 수행하는 사람들마다 서로 다른 방식으로 요청을 처리할 수 있다는 것이다.
이러한 동일한 요청에 대해 서로 다른 방식으로 응답할 수 있는 능력을 다형성이라고 한다.
한 사람이 동시에 여러 역할을 수행할 수 있다.
캐시어와 바리스타라는 개별적인 역할을 이용해 협력 관계를 묘사했지만 한 사람이 캐시어와 바리스타의 역할을 동시에 수행하는 것도 가능하다.
따라서 한 사람이 동시에 둘 이상의 역할을 수행하느 것도 가능하다.
현실 속에 살아가는 우리는 모두 둘 이상의 역할을 수행한다. 회사에 출근하면 회사원이라는 역할을 수행하지만 집에 돌아와서는 누군가의 부모로서의 역할과 남편과 아내라는 역할을 수행하게 된다.
역할 책임 협력
기능을 구현하기 위해 협력하는 객체들
역할과 책임을 수행하며 협력하는 객체들 * 역할은 관련성 높은 책임의 집합이다. * 역할은 유연하고 재사용 가능한 협력 관계를 구축하는 데 중요한 설계 요소다.
협력속에 사는 객체
객체지향 애플리케이션의 윤곽을 결정하는 것은 역할, 책임, 협력이지만 실제로 협력에 참여하는 주체는 객체다.
만약 실행중인 애플리케이션의 내부를 눈으로 직접 볼 수 있다면 그 안에는 쉴새없이 메시지를 주고받으며 협력하는 객체가 존재한다는 것을 확인할 수 있을 것이다.
인간의 세계에서 사람이 없으면 역할, 책임, 협력이 아무런 의미가 없는 것처럼 객체자 존재하지 않는 객체지향 세계 역시 아무런 의미가 없다.
객체는 애플리케이션의 기능을 구현하기 위해 존재한다. 아주 작은 기능조차 객체 혼자 감당하기에는 버거울 정도로 복잡하고 거대하기 때문에 일반적으로는 객체는 다른 객체와 협력을 통해 기능을 구현하게 된다.
객체지향 애플리케이션의 아룸다움을 결정하는 것이 협력이라면 협력이 얼마나 조화를 이루는지 결정하는 것은 객체다. 결국 협력의 품질을 결정하는 것은 객체의 품질이다.
객체가 가져야할 두가지 덕목
객체는 충분히 “협력적”이어야 한다. > 객체는 다른 객체의 요청에 충실히 귀 기울이고 다른 객체에게 적극적으로 도움을 요청할 정도로 열린 마음을 지녀야 합니다. > 외부의 도움을 무시한 채 모든 것을 스스로 처리하려고 하는 전지전능한 객체는 내부적인 복잡도에 의해 자멸하고 만다. > 여기서 충분히 협력적이라는 말은 다른 객체의 명령에 따라 행동하는 수동적인 존재를 의미하는 것은 아니라는 사실에 주의하라. > 객체는 다른 객체의 명령에 복종하는 것이 아니라 요청에 응답할 분이다. > 어떤 방식으로 응답할지는 객체 스스로 판단하고 결정한다. 심지어 요청에 응할지 여부도 객체 스스로 결정할 수 있다.
객체는 충분히 “자율적”이어야 한다. > “자율적”이라는 단어의 뜻은 자기 스스로의 원칙에 따라 어떤 일을 하거나 자기 스스로를 통제하여 절제하는 것을 의미한다. > 어떤 사물이 자신의 행동을 스스로 결정하고 책임진다면 우리는 그 사물을 자율적인 존재라고 말한다. > 인간사회는 자율적인 존재로 구성된 협력 공동체이다. 사람들은 다른 사람의 요청에 따라 행동하지만 최대한 스스로의 판단에 따라 결정하고 행동한다. > 캐시어는 손님이 주문하면 행동을 시작하지만 손님에게 음료를 주문하는 절차나 바리스타에게 접수내역을 전달하는 방법은 스스로 결정한다. > 손님이 캐시어에게 어떤 질문을 해야하고 어떤 방식으로 바리스타에게 주문 내역을 전달하라고 지시하지 않는다. 캐시어는 요청에 대해 스스로 판단하고 행동하는 자율적인 존재다.
객체지향 설계의 묘미는 다른 객체와 조화롭게 협력할 수 있을 만큼 충분히 개방적인 동시에 협력에 참여하는 방법을 스스로 결정할 수 있을 만큼 충분히 자율적인 객체들의 공동체를 설계하는 데 있다.
객체지향의 본질
객체지향이란 시스템을 상호작용하는 자율적인 객체들의 공동체로 바라보고 객체를 이용해 시스템을 분할하는 방법이다.
자율적인 객체란 상태화 행위를 함께 지니며 스스로 자기 자신을 책임지는 객체를 의미한다.
객체는 시스템의 행위를 구현하기 위해 다른 객체와 협력한다. 각 객체는 협력 내에서 정해진 역할을 수행하며 역할은 관련된 책임의 집합이다.
객체는 다른 객체와 협력하기 위해 메시지를 전송하고 메시지를 수신한 객체는 메시지를 처리하는 데 적합한 메서드를 자율적으로 선택한다.
저는 1장을 읽고 손님, 캐시어, 바리스타의 예처럼 비슷한 예제가 어떤게 있을지 생각을 해보면서 읽었습니다.
서문에 나오는 것처럼 객체지향 관점을 보는 방법에서 “클래스가 아닌 객체를 바라보는것”, “독립적인 존재가 아니라 어떠한 기능을 구현하기 위해 협력하는 공동체의 존재로 바라보는것”
“협력에 참여하는 이 객체들이 얼마나 적절한 역할을 수행하고 책임을 가지고 있는지” 를 생각하며 생각을 해 보았을때
배달이라는 예제를 한번 생각해 보았습니다. 제가 배달의 민족 어플에서(전화로) 교촌치킨 레드콤보 + 배달기사님 문앞에 놔주세요를 작성해서 주문을 한다면
가장 먼저 해당 가게에게 교촌치킨 레드콤보 요청이 들어가게 됩니다. 저는 가게 점주님이 어떤 분인지 알지도 못합니다. 하지만 가게 점주님은 레드콤보 레시피에 맞게 맛있게 치킨을 튀겨 치킨을 만들어 줍니다.
그리고 제가 배달할 때 요청했던 기사님에게 고객님이 문앞에 두고 가달라고 하셨습니다 하고 제 요청을 기사님에게 연쇄적으로 발생하게 됩니다.
저는 마찬가지로 기사님이 어떤분인지 모르지만 결국 문앞에 맛있는 레드콤보가 놓여져 있는 것을 받을 수 있게 됩니다.
이렇게 각자의 역할과 협력을 통해 배달이라는 기능이 완성될 수 있는 것이죠 :) 이 과정에서도 요청 연쇄가 일어나며 각각의 루트로 배달하고 각각의 방법으로 치킨을 만들어서 주는 부분이 이번 1장과 비슷하다고 생각했습니다.
객체지향 관점을 보는 방법
객체지향으로 향하는 첫 걸음은 클래스가 아니라 객체를 바라보는 것에서 부터 시작합니다. 객체지향으로 향하는 두 번째 걸음은 객체를 독립적인 존재가 아니라 기능을 구현하기 위해 협력하는 공동체의 존재로 바라보는 것이다. 객체지향으로 향하는 세 번째 걸음은 협력에 참여하는 객체들에게 얼마나 적절한 역할과 책임을 부여할 수 있느냐에 달려있습니다. 객체지향으로 향하는 마지막 걸음은 앞에서 설명한 개념들을 프로그래밍이라는 언어의 틀에 흐트러짐 없이 담아낼 수 있는 기술을 익히는 것입니다.
1장이 무엇을 말하고 싶었던 걸까?
용훈 :
진형 : 클래스는 수단에 불과하고 객체 적으로 관점을 바라보거라.
연우 : 객체 = 클래스 잘못된 오해를 하는 부분 객체는 클래스 중심이 아닌다. 객체들은 자율적인 객체가 무엇인가? 자율적인 객체는 결국 자기 자신의 책임을 다하면서
스스로 요청이 들어왓을때 응답할지를 결정하는것 조차도 자기의 기준을 가지고 내부적인 구현은 내부에서 모두 결정하고 처리를해서 객체들로 이루어지도록 생각을 해야한다 생각을 했다.
객체지향 바라보는 시선
멘토님 : 내가 바랍뢋을때 녹여낼 수 있지만 동등하지는 않다.
이퀄스 해쉬코드는 다르다 / 리얼 월드랑은 해시코드가 다르다.
객체지향 속에 사람은 사람이다.
사물끼리 왜 멀까? 현실세계에 객체로 표현하지 못하는게 많다.
감각적인것도 현실세계에 있는데 이런건 객체로 표현할 수 없다. 모든걸 객체로 녹여낼수 없다.