KoreanFoodie's Study
[책 리뷰] 객체 지향의 사실과 오해 리뷰 본문
객체지향의 본질
사실 대부분의 사람들이 객체지향이라는 말을 들었을 때 떠올리는 문장은 다음과 같을 것이다.
- 객체지향이란 시스템을 상호작용하는 자율적인 객체들의 공동체로 바라본다
- 자율적인 객체는 상태와 행위를 함께 지니며, 스스로 자기 자신을 책임진다
- 객체는 시스템의 행위를 구현하기 위해 다른 객체와 협력한다. 각 객체는 협력 내에서 정해진 역할을 수행하며 역할은 관련된 책임의 집합이다.
- 객체는 다른 객체와 협력하기 위해 메시지를 전송하고, 메시지를 수신한 객체는 메시지를 처리하는 데 적합한 메서드를 자율적으로 선택한다 (캡슐화라는 것은, 메시지를 전송한 객체는 수신한 객체가 어떻게 동작할지를 모르고, 수신한 객체가 요청 사항을 메시지로 받은 후 알아서 처리한다는 것을 의미한다. 따라서 메시지를 전송하는 객체는 수신한 객체의 동작을 알 수도, 알 필요도 없다!)
사실 책은 위의 내용들을 풀어 설명하는데 대부분의 지면을 할애하고 있다.
의인화
우리는 현실 세계를 모방하여 추상화한 것이 클래스 내지는 객체라고 이해하고 있다. 하지만 책에서는 소프트웨어에서의 추상화는 '모방' 이 아니라고 역설한다. 즉, 현실 세계에서 커피는 '마셔지는' 객체이지만, 소프트웨어에서는 '스스로 마신 정도를 관리하는 자율적인' 객체인 것이다!
협력 안에서 객체의 행동은 결국 객체가 협력에 참여하면서 완수해야 하는 책임을 의미한다. 따라서 어떤 책임이 필요한가를 결정하는 과정이 전체 설계를 주도해야 한다. 그 중 행동이 중요한 것이다! (cf. 책임-주도 설계(Responsibility-Driven Design, RDD : '데이터보다 행동을 먼저 결정하라' 는 원칙과도 부합)
추상화
추상화를 통해 복잡성을 극복한다. 추상화는 대상의 핵심을 드러낸다는 점에서, 복잡성을 극복하는 방법이라고 볼 수 있다!
추상화는 두 차원에서 이뤄진다.
- 구체적인 사물들 간의 공통점은 취하고 차이점은 버리는 일반화를 통해 단순화한다
- 중요한 부분을 강조하기 위해 불필요한 세부 사항은 제거한다
또한, 소프트웨어 객체는 현실 객체를 모방한 것이 아니라 은유를 기반으로 재창조한 것이다. 따라서 소프트웨어 객체는 현실 객체가 갖지 못하는 특성을 가질 수도 있고 현실 객체가 하지 못하는 행동을 할 수도 있다.
타입은 추상화다
타입을 이용하면 객체의 동적인 특성을 추상화할 수 있다. 결국 타입은 시간에 따른 객체의 상태 변경이라는 복잡성을 단순화할 수 있는 효과적인 방법이다!
객체를 분류하는 기준은 타입이며, 타입을 나누는 기준은 객체가 수행하는 행동이다.
역할, 책임, 협력
역할은 책임의 집합이며, 동시에 협력 안에서 구체적인 객체로 대체될 수 있는 추상적인 협력자다. 따라서 본질적으로 역할은 다른 객체에 의해 대체 가능함을 의미한다. 단, 객체가 역할을 대체하기 위해서는 행동이 호환되어야 한다.
협력은 객체의 모양을 결정한다. 즉, 책임은 객체가 외부에 제공하게 될 행동이며, 협력이라는 문맥에서 행동을 수행하는 데 필요한 데이터를 고민해야 한다.
책임과 메시지
객체가 다른 객체에게 접근할 수 있는 유일한 방법은 요청을 전송하는 것뿐이다. 그리고 이 요청을 메시지라고 부른다. 메시지는 다른 객체에게 '무엇' 을 하라고 주문하지만, '어떻게' 하라고 명시하지는 않는다. 메시지를 수신하는 객체는 '자율성' 을 가지기 때문이다.
다형성
위의 관점에서 보면 다형성이란 서로 다른 유형의 객체가 동일한 메시지에 대해 서로 다르게 반응하는 것을 의미한다. 또한, 다형성을 사용하면 송신자가 수신자의 종류를 모르더라도 메시지를 전송할 수 있다. 즉, 다형성은 수신자의 종류를 캡슐화한다!
What / Who 사이클
책임-주도 설계의 핵심은 어떤 행위가 필요한지를 먼저 결정한 후에 이 행위를 수행할 객체를 결정하는 것이다. 이 과정을 흔히 What/Who 사이클이라고 한다.
묻지 말고 시켜라(Tell, Don't Ask)
메시지를 먼저 결정하고 객체가 메시지를 따르게 하는 설계 방식은 객체가 외부에 제공하는 인터페이스가 독특한 스타일을 따르게 한다. 이 스타일을 묻지 말고 시켜라(Tell, Don't Ask) 스타일 또는 데메테르 법칙(Law of Demeter) 이라고 한다.
객체 지도
객체지향 세계를 구축하기 위해서는 사용자에게 제공할 '기능' 과 기능을 담을 안정적인 '구조'라는 재료가 준비돼 있어야 한다. 기능은 시스템의 서비스이며, 구조는 시스템의 기반으로, 기능 변경을 수용할 수 있을 정도로 안정적이어야 한다.
일반적으로 기능을 수집하고 표현하기 위한 기법을 유스케이스 모델링이라고 하고, 구조를 수집하고 표현하기 위한 기법을 도메인 모델링이라고 한다.
도메인 모델은 사용자가 생각하는 멘탈 모델을 포괄하며, 이를 추상화한 소프트웨어 모델이다. 즉, 이용자가 해당 모델을 이용해서 하려는 것들을 구현할 수 있는 기반이 되도록 만들어야 한다는 뜻이다.
사람들이 동일한 용어와 동일한 개념을 이용해 의사소통하고 코드로부터 도메인 모델을 유추할 수 있게 하는 것이 도메인 모델의 진정한 목표다. 안정적인 도메인 모델을 기반으로 시스템을 구현하라. 도메인 모델과 코드를 밀접하게 연관시키기 위해 노력하라.
함께 모으기
객체지향 설계 안에 존재하는 세 가지 상호 연관된 관점인 개념 관점, 명세 관점, 구현 관점을 알아보자.
개념 관점(Conceptual Perspective) 에서 설계는 도메인 안에 존재하는 개념과 개념들 사이의 관계를 표현한다. 이 관점은 사용자가 도메인을 바라보는 관점을 반영한다. 따라서 실제 도메인의 규칙과 제약을 최대한 유사하게 반영하는 것이 핵심이다.
명세 관점(Specification Perspective) 은 객체의 인터페이스를 바라보게 된다. 명세 관점에서 프로그래머는 객체가 협력을 위해 '무엇'을 할 수 있는가에 초점을 맞춘다. 인터레이스와 구현을 분리하는 것은 훌륭한 객체지향 설계를 낳는 가장 기본적인 원칙이라는 점을 기억하라.
구현 관점(Implementation Perspective) 은 객체들이 책임을 수행하는 데 필요한 동작 코드를 작성하는 것에 초점이 맞춰져 있다. 따라서 프로그래머는 객체의 책임을 '어떻게' 수행할 것인가에 초점을 맞추며 인터페이스를 구현하는 데 필요한 속성과 메서드를 클래스에 추가한다.
'R & D > Software Engineering' 카테고리의 다른 글
[C++ 함수형 프로그래밍] 함수로 설계하기 (feat. 틱택토와 STL) (0) | 2023.09.28 |
---|---|
[C++ 함수형 프로그래밍] 파셜 애플리케이션과 커링 (0) | 2023.09.28 |
[C++ 함수형 프로그래밍] 함수형 합성 (C++ 에서 함수 합성하기) (0) | 2023.09.28 |
[C++ 함수형 프로그래밍] 순수 함수와 람다 (0) | 2023.09.27 |
UML (클래스 다이어그램, 시퀀스 다이어그램) 간단 정리 (0) | 2022.10.14 |