"객체지향
이란 실세계를 직접적이고 직관적으로 모델링할 수 있는 패러다임이다”.
객체지향을 한줄로 설명할 수는 없겠지만 가장 적합한 설명일 것이다.
객체지향의 핵심은 현실 속에 존재하는 사물을 객체 단위로 모방하여 소프트웨어 내부로 옮겨오는 작업이다.
즉, 실제 세계에 대한 추상화의 결과는 객체이다.
하지만 이는 어디까지나 철학적이고 이론적인 부분에 한하여 객체지향을 명명하는 단계에서의 설명이다.
실용적인 관점에서는 실세계의 모방이란 힘든작업이며, 실제 세계의 사물과 우리가 이루고자 하는 객체(Object)
의 거리는 유사성을 찾기 어렵다.
그렇기 때문에 객체지향의 목표는 실세계를 모방하는 것이 아닌, 오히려 새로운 세계를 창조하는 것이다.
그대로 옮기는 것이 아닌, 해당 지점에서 만족할 지점을 찾는 서비스를 창출할 수 있도록 새로운 세계를 창조하는 것이 소프트웨어 개발자의 역량이다.
그럼에도 객체지향 프로그래밍을 실세계 객체와 소프트웨어 객체 간의 대응이라는 비유를 이어나가는 이유는 뭘까?
객체지향이라는 측면을 이해하고 학습하는데 매우 효과적이기 때문이다.
객체를 현실 세계의 생명체에 비유하는 것은 상태와 행위를 캡슐화하는 소프트웨어 객체의 자율성을 설명하는데 효과적이다.
이는 나아가 객체간의 메시지를 주고받으며 공동의 목표를 달성하기 위한 협력이라는 키워드까지 설명하는데 적합하다.
이렇듯 실세계의 사물을 기반으로 객체지향의 구현까지 이어진다는 것은 객체지향 설계의 핵심 사상인 연결완전성을 설명하는데 적합하다.
즉, 해당 챕터의 핵심은 객체지향이라는 개념을 실무적 관점에서 실세계의 모방
이라는 개념에 적용시키기에는 부적합한것은 사실이나, 객체지향이라는 기본 사상을 이해하고 학습하는데에는 매우 효과적이기에 잠깐만 얽매여 생각해 보자는 것이다.
협력하는 사람들
우리가 흔히 일상속에서 커피를 시킨다는 행위, 그리고 바리스타가 이를 접수받고 커피를 만들어 사용자에게 전달한다.
이 과정에서 역할과 책임,협력이라는 키워드가 적용된다.
우리가 커피를 시키는 일상의 경우 주문하는 손님과 이를 받는 캐시어, 커피를 제조하는 바리스타라는 역할을 수행하는 각각의 객체가 자신의 책임을 수행한다.
커피 주문이라는 행위에 협력하는 참여자들은 커피가 정확하게 주문되고 전달될 수 있도록 역할과 책임을 다하기에 손님이 성공적으로 커피를 전달 받을 수 있다.
이러한 역할,책임,협력의 개념은 카페에서 커피를 시킬 때 뿐만아닌 실생활과 객체지향에도 적용되는 개념일 것이다.
요청과 응답으로 구성된 협력
우리는 문제를 해결하기 위해 기본적으로 요청(Request)
이라는 행위를 통해 도움을 얻는다.
이는 이전의 커피 예시에서 또한 마찬가지이다. 커피를 주문하고 , 주문을 전달하는 행위 또한 이에 속한다.
요청이 발생하면 그에 연이어 반드시 응답(Response)
이 발생한다.
바리스타가 캐시어에게 커피를 전달하고, 캐시어가 이어 손님에게 커피를 전달하는 것이 그 예시에 적합할 것이다.
요청과 응답을 통해 다른 객체와의 협력(Collaboration)
을 통해 문제를 해결 할 수 있으며, 이는 각 역할의 수행 척도에 따라 달라지게 된다.
역할과 책임
기본적으로 각 객체들은 자신만의 고유한 역할(Role)
을 부여받는다.
역할은 어떤 협력에 참여하는 특정한 사람이 협력안에서 차지하는 책임이나 임무를 의미한다.
누군가는 손님이었다가, 누군가는 캐시어였다가, 누구는 바리스타로서의 책임을 다해야한다.
즉, 역할이라는 단어는 기본적으로 책임(Responsebility)
이라는 개념을 내포한다.
그렇기에 역할과 책임은 협력이 원활하게 진행되게하는 핵심적인 구성요소이다.
협력을 위해 특정한 역할을 맡고 역할에 적합한 책임을 수행한다는 사실은 몇가지 중요개념을 상기 시킬 수 있다.
- 여러 사람이 동일한 역할을 수행할 수 있다. = 여러 객체가 동일한 역할을 수행할 수 있다.
- 손님의 입장에서 캐시어는 누구던지 상관이 없고, 바리스타도 상관이없다.
- 이를 객체지향이나 스프링 개념에 비교하자면 같은 결과값을 반환하고 작업을 수행한다면 어느 클래스이던, 어느 서비스이던 상관이 없다는 것이다.
- 예를 들어, 컨트롤러에서 비즈니스 로직을 수행하던, 서비스레이어에서 처리하던 상관이 없다는 것이다. 하지만 여러 구조상 물론 분리되는 것이 옳은방향이다.
- 역할은 대체 가능성을 의미한다.
- 위의 예시와 비슷하게 누구든 같은 결과값을 반환하여 준다면 손님 입장에서 캐시어는 대체가능한 존재이다.
- 책임을 수행하는 방법은 자율적이다. = 각 객체는 책임을 수행하는 방법을 자율적으로 선택 할 수 있다.
- 손님은 결제를 현금으로 할수도 카드로 할 수도, 바리스타 마다 커피의 제조 능력에 차이가 존재할 수도 있다.
- 이처럼 동일한 요청에 대해 서로 다른 방식으로 응답할 수 있는 능력 즉,
다형성(Polymorphism)
을 가진다.
- 한 사람이 동시에 여러 역할을 수행할 수 있다. = 하나의 객체가 동시에 여러 역할을 수행할 수 있다.
- 캐시어가 바리스타의 역할까지 수행할 수도 있듯이, 하나의 서비스 레이어에서 여러 요청에 대한 처리를 할 수도 있고 분리하여 처리 할 수도 있는 책임의 차이이다.
역할, 책임, 협력
기능을 구현하기 위해 협력하는 객체들
앞의 예시에서 사람은 객체로, 요청은 메시지로, 요청을 처리하는 방법을 메서드로 변경한다면 객체지향의 개념에 부합한 예시가 될것이다.
"즉, 객체간의 상호작용은 메시지로 이루어지고 해당 메시지는 메서드를 통해 수행된다."
역할과 책임을 수행하며 협력하는 객체들
객체 지향에서 반복되는 개념 중 하나가 객체들은 단독으로 책임을 다할 수도 있겠지만 서로간의 상호작용을 통해, 최종적으로는 협력을 통해 목표를 달성하는 것을 추구한다.
즉, 각 객체들은 협력을 통해 책임을 수행하고 이를 객체지향스럽게 구성하기 위해 더 작은 책임으로 분할하여 역할을 구성하고 공동의 목표를 이루기 위해 동작한다.
협력 속에 사는 객체
역할, 책임 ,협력이 객체지향에서 큰 비중을 차지하는 것은 맞지만 결국은 객체(Object)
가 주된 주체이다.
결국 객체지향 프로그래밍은 객체의 성질과 품질에 가장 큰 중점을 두게된다.
그 중점을 책에서는 두가지 덕목으로 정정한다.
첫 번째는 충분히 객체는 “협력적”이어야한다. 즉, 다른 객체에게 요청을 보내고 응답을 줄만큼 협력적이어야 하다는 뜻이다.
하지만 여기서 주의해야할 점은 다른 객체에 종속적인 것이아닌 그저 요청에 응답할 정도의 스스로 판단하고 결정하는 하나의 객체여야 한다는 것이다.
두 번째는 객체가 충분히 “자율적”이어야 한다는 것이다. 스스로 판단하고 행동한다는 점에서 객체는 자율적이어야한다는 점도 포함된다.
상태와 행동을 함께 지닌 자율적인 객체
흔히 객체는 상태(State)
와 행동(Behavior)
을 함께 지닌 실체라고 정의한다.
즉, 객체가 협력에 참여하기 위해 어떤 행동을 취할지가 정의되어 있어야하고 그 행동을 취할 때 필요한 상태도 함께 정의되어 있어야 한다는 것을 의미한다.
이를 간략하게 코드로 나타내본다면, 이런 느낌이지 않을까 싶다.
public class Object{
private State state;
private Behavior behavior;
}
한마디로 객체가 자율적인 존재로 남기 위해서는 행동과 상태를 함께 지니고 있어야한다는 것이다.
또한 자율의 구분은 객체의 내부와 외부를 명확하게 구분하는 것으로 부터 나온다.
객체 외부에서는 객체의 내부에 대해서 일절 몰라야 하며, 외부에서의 접근 또한 정해진 수단을 통해서만 발생해야한다. 객체가 무엇을 수행하는지는 알지만 어떻게 수행하는지에 대해서는 몰라야한다.
이러한 개념은 캡슐화(encapsulation)
와 밀접한 개념이다.
바리스타가 커피 제조방법을 기억하고 있고(행동을 위해 필요한 상태를 포함한 동시에) 자신이 알고 있는 방법으로 커피를 제조한다.(특정 행동을 스스로 수행할 수 있어야한다)
따라서 객체는 상태와 행위를 하나의 단위로 묶는 자율적 존재다.
협력과 메시지
객체지향에서는 메시지(Message)
를 단위로 협력이 발생하고 객체가 협력을 위해 요청을 보내는 즉, 메시지를 전송하는 객체를 송신자(Sender),응답을 보내는 즉,메시지를 수신하는 객체를 수신자(Reciver)라고 정의한다.
메서드와 자율성
메서드는 한마디로 메시지를 처리하는 방법이라고 정의할 수 있다.
이러한 메서드는 객체에서 수신된 메시지를 미리 처리하기 위해 작성되어있다.
메시지를 수신한 객체가 실행시간에 메서드를 선택하여 수행할 수 있다는 점은 다른 프로그래밍언어에 비해 객체지향 프로그래밍이 갖는 장점으로 볼 수 있다.
메시지와 메서드의 분리는 객체의 협력에 참여하는 객체들간의 자율성을 증진시킨다.
그렇기에 객체지향스럽게 설계를 하기 위해선, 외부의 요청이 무엇인지 표현하는 메시지와 요청을 처리하기 위한 구체적인 방법인 메서드를 분리하는 것이 중요하고, 이는 객체의 자율성을 높이는 핵심적인 매커니즘으로 이어진다.
객체지향의 본질
여태까지의 내용들을 종합하는 단계이다. 객체지향이란 과연무엇인가
- 객체지향이란 시스템을 상호작용하는 자율적인 객체들의 공동체로 바라보고 객체를 이용해 시스템을 분할하는 방법
- 자율적인 객체란 상태와 행위가 반드시 동반되어야 하며, 책임을 가진다.
- 객체는 목표의 달성을 위해, 다른 객체와 협력하고 정해진 역할을 수행하며, 책임을 진다.
- 객체는 다른 객체와의 협력을 위해 메시지를 전송하고, 메시지를 수신하는 객체는 메서드를 자율적으로 선택한다.
객체를 지향하라
객체지향 세계에서 우리는 클래스(Class)
라는 단어와 친숙할 수 밖에 없을 것이다.
자바에서 하나의 객체 단위를 나타낼때 대표적으로 사용되는 용어로서 사용되어 왔기 때문이다.
하지만, 우리는 이 개념을 한번쯤은 탈피 해볼 필요가 있다. 클래스라는 관점에 사로잡혀 추상화와 상속이라는 키워드에 사로잡힌다면 오히려 캡슐화를 저해하고, 결합도를 높이는 구조가 되지않겠는가?
‘객체지향의 사실과 오해’ 지금 우리가 읽고 있는 이 책에서 강조하는 부분은 앞에서 부터 반복되어 왔다.
객체지향 관점에서, 정확히 말하자면 객체의 관점에서 어떤 메시지를 주고 받고 어떻게 협력 관계를 맺을 것인지에 대해 고민하는 것이 진정한 객체지향 개발자로서의 자세라고 말하고 있다. 말 그대로 객체를 지향하는 습관을 들여야한다.
Opinion
객체지향의 사실과 오해 라는 이 책을 접하기 전부터 객체에 대한 개념은 알고있었어도, 마인드까지 과연 객체지향적인 사고를 촉구했는지 다시 한번 생각하게 해주는 책인것 같다.
객체지향에서 가장 중요한 것은 객체를 지향하는 것이다. 클래스 단위의 구조가아니라.
또한 각 객체의 역할,책임,협력에 집중하도록하자.