서문
객체지향을 흔히 실세계를 직접적이고 직관적으로 모델링 할 수 있는 패러다임으로 알고 있는 사람들이 많으나, 실세계의 모방이라는 개념은 객체지향의 기반을 이루는 철학적인 개념을 설명하는 데는 적합하지만 실용적인 관점에서 객체지향 분석, 설계를 설명하기에는 적합하지 않다.
방화벽을 예시로 들어보면, 소프트웨어 세상에서의 방화벽은 실제 방화벽과 다르게 불을 막는 것이 아니라 네트워크의 침입을 막는다. 이처럼 객체지향의 목표는 실세계를 모방하는 것이 아니라, 새로운 세계를 창조하는 것이다.
그럼에도 객체지향을 이런 방식으로 알고 있는 이유는 실세계에 대한 비유가 객체지향의 다양한 측면을 이해하고 학습하는 데 효과적이기 때문이다.
협력하는 사람들
커피 공화국에서의 예시: 커피 주문이라는 협력을 달성하기 위해 손님, 캐시어, 바리스타라는 역할이 존재한다.
손님
커피를 주문할 책임을 수행한다.
캐시어
손님의 주문을 받는 책임을 수행한다.
바리스타
주문된 커피를 제조하는 책임을 수행한다.
커피 주문이라는 과정조차도 이렇게 분리된 과정들을 거쳐 진행된다. 이보다 더 복잡한 애플리케이션에서는 동작하는 과정들이 더 많을 것이다.
따라서 객체는 스스로 해결하지 못하는 문제와 마주치면 그것을 해결해 줄 수 있는 다른 객체에게 도움을 요청한다. 그런데, 일반적으로는 하나의 문제를 해결하기 위해 다수의 객체 혹은 역할이 필요하기 때문에 한 객체에 대한 요청이 또 다른 객체에 대한 요청을 유발하는 것이 일반적이다. → 요청은 연쇄적으로 발생한다.
커피 공화국 예시: 손님은 캐시어에게 주문을 하고, 캐시어는 바리스타에게 커피를 제조해달라고 요청한다.
요청을 받은 객체는 수행한 뒤 결과를 응답해준다. 응답 과정 또한 연쇄적으로 발생한다.
커피 공화국 예시: 바리스타는 만든 커피를 캐시어에게 전달하고, 캐시어는 손님에게 커피를 제공한다.
요청과 응답을 통해 다른 객체와 협력할 수 있는 능력은 거대하고 복잡한 문제를 해결할 수 있는 공동체 (애플리케이션)을 형성할 수 있게 해 준다. 협력의 성공은 특정한 역할을 맡은 각 객체가 얼마나 요청을 성실히 이행하느냐에 달려 있다.
커피 공화국 예시: 손님 역할을 맡은 객체는 커피를 주문할 책임이 있다. 캐시어 역할을 맡은 객체는 주문을 받아야 할 책임이 있다. 바리스타 역할을 맡은 객체는 커피를 제조할 책임이 있다.
역할은 다음과 같은 특징을 가진다.
- 여러 객체가 동일한 역할을 수행할 수 있다. → 손님 입장에서는 어떤 객체가 캐시어를 맡을 지에는 아무 상관도 없다. 그저 임의의 캐시어로부터 커피를 받기만 하면 될 뿐이다.
- 역할은 대체 가능성을 의미한다. → 두 객체가 캐시어 역할을 수행할 수 있다면 손님 입장에서는 어떤 것을 해도 상관 없다.
- 책임을 수행하는 방법은 자율적으로 선택할 수 있다. → 손님이 현금으로 주문하든, 카드로 주문하든 손님이 주문할 수 있는 방법은 캐시어 객체에게 아무 상관 없다.
- 동일한 요청에 대해 서로 다른 방식으로 응답할 수 있는 능력을 다형성이라고 한다.
- 한 객체가 동시에 여러 역할을 수행할 수 있다. → 캐시어가 바리스타의 역할까지 수행해도 무방하다.
역할, 책임, 협력
어떤 객체도 섬이 아니다. - 워드 커닝험 (Ward Cunningham)과 켄트 벡 (Kent Beck)
사용자가 최종적으로 인식하게 되는 시스템의 기능은 객체들이 성실히 협력해서 일궈낸 결실이다.
애플리케이션의 기능은 더 작은 책임으로 분할되고 책임은 적절한 역할을 수행할 수 있는 객체에 의해 수행된다.
객체지향 설계라는 예술은 적절한 객체에게 적절한 책임을 할당하는 것에서 시작되며, 책임은 객체지향 설계의 품질을 결정하는 가장 중요한 요소다.
역할은 협력에 참여하는 객체에 대한 일종의 페르소나이다.
역할은 유연하고 재사용 가능한 협력 관계를 구축하는 데 중요한 요소다.
협력 속에 사는 객체
결국 역할, 책임, 협력을 구현하는 것은 객체다. 객체 지향 프로그래밍이라고 부르는 이유는 객체가 핵심적이기 때문이다.
객체지향 애플리케이션의 아름다움을 결정하는 것이 협력이면, 협력이 얼마나 조화를 이루는지는 객체가 결정한다.
- 애플리케이션의 아름다움 결정: 협력
- 협력의 품질 결정: 객체의 품질
객체는 다음과 같은 덕목을 갖춰야 한다.
- 객체는 충분히 협력적이어야 한다.
- 객체가 충분히 자율적이어야 한다.
객체가 협력에 참여하기 위해 어떤 행동을 할 경우, 그 행동을 하는 데 필요한 상태도 함께 지니고 있어야 한다.
바리스타가 커피 제조법을 모른다는 것은 말이 안 된다.
또한 객체의 자율성은 객체의 외부와 내부를 명확히 구분하는 것으로부터 나온다.
- 외부: 접근이 허락된 수단 (ex: 주문된 커피를 얻기)
- 내부: 사적으로 취급할 정보 (ex: 바리스타가 제조할 커피 제조의 상세한 방식)
객체지향은 데이터 (상태)와 프로세스 (협력에 참여하는 메서드)를 하나의 틀 안에 묶어놓음으로써 객체의 자율성을 보장한다.
객체지향에서의 유일한 의사소통 수단은 메시지이다. 메시지를 전달하는 송신자, 메시지를 수신하는 수신자로 구분된다.
- 수신자는 수신한 메시지를 실행 시점에 자신만의 방법으로 처리하여 응답한다. 이때 자신만의 방법을 메서드라고 한다.
- 기본적인 절차적 프로그래밍은 컴파일 시점에 메시지를 처리한다.
- 메시지: 커피를 주문하는 요청 / 메서드: 커피를 제조하는 방법
- 메시지와 메서드를 명확히 구분하는 것은 객체의 자율성을 높인다. → 캡슐화와 관련된다.
객체지향의 본질
초기 객체지향 프로그래밍 언어의 초점은 새로운 개념의 데이터 추상화를 제공하는 클래스에 맞춰져 있었다. 때문에 대부분의 사람들은 객체지향을 클래스를 지향하는 것으로 생각했다.
클래스가 객체지향 프로그래밍 언어의 관점에서 매우 중요한 구성요소인 것은 맞으나, 객체지향의 핵심을 이루는 중심 개념이라고 말하는 것은 무리가 있다.
클래스가 중요한 개념이긴 하지만 객체들의 역할, 책임, 협력에 비해서는 덜 중요하다.
지나치게 클래스를 강조하는 프로그래밍 언어적인 관점은 객체의 캡슐화를 저해하고 클래스를 서로 강하게 결합시킨다. 애플리케이션을 협력하는 객체들의 공동체가 아닌 클래스로 구성된 설계도로 보는 관점은 유연하고 확장 가능한 애플리케이션의 구축을 방해한다.
훌륭한 객체지향 설계자가 되기 위해서는 코드를 담는 클래스의 관점에서 메시지를 주고받는 객체의 관점으로 사고를 전환하는 것이다. 중요한 것은 정적인 클래스의 관계가 아니라 동적인 객체들의 역할, 책임, 협력이기 때문이다.
요약
- 객체지향 세계는 실생활을 모방하는 것이 아니라 완전히 새로운 세계를 창조하는 것이다.
- 객체는 역할과 책임, 요청과 응답을 통해 협력이라는 것을 이끌어내고 이는 애플리케이션의 실행 목적을 뜻한다.
- 애플리케이션을 정적인 클래스들의 관계로 바라보지 말고 동적인 객체들의 역할, 책임, 협력 과정으로 바라보라.
- 역할은 그 객체가 수행해야 할 책임을 내포한다. (ex: 바리스타 → 커피 제조)
- 메시지는 다른 객체에게 의사소통하는 유일한 수단이며, 메서드는 받은 메시지를 처리하는 객체만의 자율적인 방법을 뜻한다. 이 둘을 명확히 구분해야 객체의 자율성이 나온다.
- 협력은 애플리케이션의 품질을 결정하며 협력의 품질은 객체의 품질로부터 나온다.
- 적절한 객체에게 적절한 책임을 할당하는 것이 애플리케이션 설계의 중요한 요소이다.
'도서 📚 > 📗 객체지향의 사실과 오해' 카테고리의 다른 글
6장: 객체 지도 (0) | 2023.11.08 |
---|---|
5장: 책임과 메시지 (0) | 2023.11.07 |
4장: 역할, 책임, 협력 (0) | 2023.11.05 |
3장: 타입과 추상화 (1) | 2023.11.02 |
2장: 이상한 나라의 객체 (1) | 2023.11.01 |