-
OOP 객체지향처럼 생각해보기책/객체지향의 사실과 오해 2020. 12. 21. 20:42
시작
- 이 글은 객체지향의 사실과 오해라는 책의 07장 함께 모으기 중 커피 전문점 도메인 설계 및 구현 예제에 대한 내용입니다.
- 객체지향의 사실과 오해라는 책과, 우형의 기술 블로그를 보고 한번 더 정리해보면 기억에 오래 남지 않을까 해서 정리하려고 합니다.
- 객체 지향의 사실과 오해를 읽으면서 메시지, 책임, 협력, 역할이라는 용어에 대해 배웠고 신선했습니다!
- 이 책을 보면 객체 지향이라는 것은 협력 관계 속에서 책임을 할당하고 그에 가장 알맞은 역할, 객체를 찾습니다.
- 해당 객체는 스스로 자율적인 객체로서 수신한 메시지를 책임지기 위해 동작하고 그 책임 안에서 다른 객체에게 책임을 할당하기도 하며 협력 공동체를 만들어 갑니다.
- 이러한 하나의 책임 주도의 설계는 캡슐화, 높은 응집도와 낮은 결합도로 바뀌었고 이는 제가 개발을 하고 변경이 잦아지면서 생기는 두려움 등을 해소시켜 주지 않을까 생각했습니다!
- 하지만 아직도 객체지향 설계를 하려고 하면 어려운 건 사실입니다. 하루 빨리 더 많은 경험을 해서 이 책을 100% 이해하는 날이 왔으면 좋겠습니다.
커피 전문점을 객체지향적으로 바라보고 설계하고 구현해보자.
- 커피 전문점 도메인 예제를 통해 도메인 모델에서 시작하여 최종 코드까지의 구현 과정을 살펴보겠습니다.
커피 전문점 도메인
도메인 이란?
- 사용자들이 관심을 가지고 있는 특정 분야나 주제를 말하며 소프트웨어는 도메인에 존재하는 문제를 해결하기 위해 개발됩니다.
- 객체 지향 설계를 하다 보면 도메인 모델의 구조와 유사한 구조를 띄우게 됩니다.
- 도메인 모델이 단순히 설계에 필요한 용어를 제공하는 것을 넘어서 코드의 구조에도 영향을 미친다는 것입니다.
- 따라서 구현을 가이드할 수 있는 도메인 모델을 선택해야 합니다.
- 객체지향은 도메인의 개념과 구조를 반영한 코드를 만들기 때문입니다. 도메인의 구조가 코드의 구조를 이끌어 내는 것은 자연스러울 뿐만 아니라 바람직한 것입니다.
커피 주문
다음 예제의 목적은 커피 전문점에서 커피를 주문하는 과정을 객체들의 협력 관계로 구현하는 것입니다.
커피 전문점이라는 세상
1. 객체들로 구성된 작은 세상으로 바라보자
객체지향 패러다임에서 가장 중요한 것은 책임입니다. 그렇기 때문에 커피전문점을 구성하는 요소들(손님, 바리스타)을 객체로 보고 커피 전문점은 그 객체들로 이루어진 작은 세상으로 보겠습니다.
손님이 커피를 주문하는 예제를 요약하자면 다음과 같습니다.
손님이 메뉴판에서 4가지 메뉴 항목들 중 하나를 선택해서 바리스타에게 선택한 메뉴(커피)를 주문하고, 바리스타는 커피를 제조해서 손님에게 건네줍니다.- 4가지 메뉴 항목들, 바리스타, 커피 등은 각각 하나의 객체가 될 수 있습니다.
- 모델링에 대해서는 익숙하지 않지만 먼저 생각해볼 것은 주문한다 라는 하나의 책임입니다.
- 주문한다를 생각해 보았을때 손님 객체와 바리스타 객체를 먼저 생각해 볼만 합니다.
- 손님 객체가 주문을 하기 위해 메뉴가 필요할 것이고, 그럼 메뉴 객체들이 있는 메뉴판 객체가 있어야 합니다!
- 또한 바리스타 객체가 손님 객체의 주문에 따라 만들어서 제공해야 할 커피 객체들이 필요할 것입니다.
- 즉 객체지향의 관점에서 커피 전문점이라는 도메인은 손님 객체, 메뉴 항목 객체, 메뉴판 객체, 바리스타 객체, 커피 객체로 구성된 작은 세상인 것입니다.
- 커피를 주문하는 과정을 객체지향의 관점에서 다시 설명해봅시다.
손님 객체는 메뉴판 객체 안에 적힌 메뉴 항목 객체들 중에서 하나를 선택해서 바리스타 객체에게 전달(주문)하는 것입니다. 그리고 바리스타 객체는 주문을 받은 메뉴에 해당하는 커피 객체를 제조하는 것이죠.- 이와 같이 객체지향의 관점에서 객체들로 이루어진 커피 전문점 작은 세상을 그림으로 정리하면 아래와 같이 표현된다고 합니다.
2. 객체들 간의 관계
- 다음으로는 각 객체들 사이의 관계에 대해서 살펴보겠습니다. 사실 그림 7.2에서도 각 객체들 사이의 관계는 쉽게 알 수 있습니다.
- 손님은 메뉴판에서 커피를 선택할 수 있습니다. 이런 관계가 있는 것이죠. 손님과 바리스타, 바리스타와 커피도 마찬가지입니다. 메뉴판과 커피와는 직접적으로 관계가 없는 것도 알 수 있습니다.
3. 객체들의 분류
- 이제는 동적인 객체들을 정적인 타입으로 간단하게 추상화해보겠습니다.
- 이를 위해 객체들을 분류할 건데, 분류를 위해서는 타입(type)을 사용합니다.
- 4가지 커피 객체들을 모두 같은 ‘커피 타입’으로 분류할 수 있는 것입니다.
- 동일한 상태와 동일한 행동을 가질 수 있는 객체는 같은 타입의 인스턴스로 분류할 수 있습니다.
클래스와 타입 사이의 차이는 꼭 이해해 두어야 합니다. 객체의 클래스는 그 객체가 어떻게 구현되느냐를 정의합니다. 클래스는 객체의 내부 상태와 그 객체의 연산에 대한 구현 방법을 정의합니다. 반면, 객체의 타입은 그 객체의 인터페이스, 즉 그 객체가 응답할 수 있는 요청의 집합을 정의합니다. 하나의 객체가 여러 타입을 가질 수 있고 서로 다른 클래스의 객체들이 동일한 타입을 가질 수 있습니다. 즉, 객체의 구현은 다를지라도 인터페이스는 같을 수 있다는 의미입니다.
-Gof 디자인 패턴. p. 46
각 객체들은 아래와 같이 모델링할 수 있습니다.
- 손님 객체는 ‘손님 타입’의 인스턴스
- 바리스타 객체는 ‘바리스타 타입’의 인스턴스
- 4가지 커피 모두 ‘커피 타입’의 인스턴스
- 메뉴판 객체는 ‘메뉴판 타입’의 인스턴스
- 4가지 메뉴 항목 객체들 모두 동일한 ‘메뉴 항목 타입’의 인스턴스
- 메뉴판 객체는 4개의 메뉴 항목 객체를 포함
4. 타입 간의 관계
- 각 객체들을 타입별로 분류 했으니 이제는 그 타입들 간의 관계를 살펴봅시다.
도메인 모델을 작성하는 단계에서는 다음과 같이 두 가지에 초점을 맞추는 것에 충분하다고 합니다.
- 어떤 타입이 도메인을 구성하는지
- 타입들 사이에 어떤 관계가 존재하는지 파악함으로써 도메인을 이해하는 것
4-1. 메뉴판 타입과 메뉴 항목 타입 간의 관계
- 메뉴 항목 객체가 메뉴판 객체에 포함(has a)되어 있으므로, 메뉴판 타입과 메뉴 항목 타입은 합성(composition) 관계로 단순화할 수 있습니다.
4-2. 손님과 메뉴판 사이의 관계
- 손님 타입은 주문을 하려면 메뉴판 타입을 알아야 하지만, 메뉴판 타입은 손님의 일부가 아닙니다.
- 이 관계는 합성 관계는 아닌 연관(association) 관계라고 하며 단순한 선으로 연결합니다.
- 위와 마찬가지로 손님 타입과 바리스타 타입의 관계나 바리스타 타입과 커피 타입의 관계도 동일한 연관 관계입니다.
- 이렇게 해서 그림 7.5와 같이 커피 전문점 도메인을 구성하는 타입들의 종류와 관계를 표현하게 되었습니다.
- 이처럼 소프트웨어가 대상으로 하는 영역인 도메인을 단순화해서 표현한 모델을 도메인 모델이라고 합니다.
5. 객체지향 설계
- 지금까지 커피 전문점이라는 도메인을 단순화해서 이해해봤습니다.
- 객체지향의 세계는 협력하는 자율적인 객체들의 공동체라는 얘기가 이 책의 초반부터 여러번 나옵니다.
- 다음 단계는 각 객체들의 협력을 설계하는 것입니다. 즉, 적절한 객체에게 적절한 책임을 할당하는 것입니다
설계하고 구현하기
커피를 주문하기 위한 협력 찾기
- 객체지향 설계의 첫 번째 목표는 훌륭한 객체를 설계하는 것이 아니라 훌륭한 협력을 설계하는 것 입니다!
- 훌륭한 객체는 훌륭한 협력을 설계할 때만 얻을 수 있습니다.
- 협력을 설계할 때는 객체보다는 메시지를 먼저 선택하고
- 그 후에 메시지를 수신하기에 적절한 객체를 선택해야 합니다.
- 즉 메시지가 객체를 선택하게 하게 해야 합니다. 그 후 메시지를 수신할 객체는 메시지를 처리할 책임을 맡게 되고
- 객체가 수신하는 메시지는 객체가 외부에 제공하는 퍼블릭 인터페이스에 포함됩니다.
커피를 주문하는 협력 설계하기
1. 첫 번째 메시지는 ‘커피를 주문하라’ 일 것입니다.
- 메시지 위에 붙은 화살표는 메시지에 담아 전달될 부가 정보인 인자를 의미합니다.
- 나중에 ‘메뉴를 주문하라(아메리카노)’와 같이 인자를 포함하는 형식으로 구현될 것입니다.
- 메시지를 찾았으니 이제 메시지를 수신하기에 적절한 객체를 선택해야 합니다.
- 어떤 객체를 선택해야 할까요? 어떤 객체가 커피를 주문할 책임을 져야 할까요?
- 커피를 주문할 책임을 잘 아는 객체는 무엇일까요? 그것은 손님입니다.
- 따라서 메시지를 처리할 객체는 손님 타입의 인스턴스입니다.
- 이제 손님 객체는 커피를 주문할 책임을 할당받았습니다.
- 손님은 ‘커피를 주문하라’는 메시지를 받자마자 스스로 할 수 있는 것이 없습니다.
- 메뉴 항목에 대해서 모르기 때문에 스스로 바로 주문할 수 없는 상황인 것입니다.
- 스스로 할 수 없는 일이 있다면 다른 객체에게 이를 요청해야 합니다.
- 객체는 협력을 통해 공동체를 이루기에 적절한 책임을 수행할 다른 객체를 선택해야 합니다.
- 해당하는 책임에 대한 요청은 손님 객체에서 외부로 전송되는 메시지를 정의할 것입니다.
- 여기서 ‘메뉴 항목을 찾아라’라는 새로운 메시지가 등장하는 것입니다.
- 화살표 위에 있는 ‘메뉴 이름’이라는 인자를 포함해 함께 전송하고,
- 화살표 아래에 붙은 ‘메뉴 항목’은 손님에게 응답해야 하는 것을 의미합니다.
- 즉, ‘메뉴 항목을 찾아라’라는 메시지를 수신한 객체는 ‘메뉴 이름에 대응되는 ‘메뉴 항목’을 반환해야 하는 것입니다.
- 그럼 새로운 메시지인 ‘메뉴 항목을 찾아라’를 수신해서 메뉴 항목을 찾을 책임을 어떤 객체에게 할당하는 것이 적절할까요?
- 메뉴판 객체가 메뉴 항목 객체를 포함하고 있으므로 가장 적절해 보입니다.
- 이제 손님은 자신이 주문한 커피에 대한 메뉴 항목을 얻었으니
- 이제 메뉴 항목에 맞는 커피를 제조해달라고 요청할 수 있습니다.
- 새로운 요청은 새로운 메시지가 필요하다는 신호이므로, 메시지를 먼저 정의합니다.
- 손님은 ‘커피를 제조하라’는 메시지의 인자로 ‘메뉴 항목’을 전달하고 반환 값으로 제조된 커피를 받아야 합니다.
- 커피에 대해 잘 아는 전문가 객체는 무엇일까? 그것은바리스타입니다.
- 위에서 보면 알 수 있듯이 ‘커피를 제조하라(메뉴 항목)’는 메시지를 먼저 정의하고, 그 메시지로 객체를 선택했다는 것을 잊지 말아야 합니다.
- 지금까지 계속해서 메시지를 먼저 정의하고 그 메시지를 수신할 객체를 선택해왔습니다.
- 즉 책임이 주도가 되는 설계를 기반으로 진행하고 있습니다.
- 또 해당 객체의 메시지를 수신하기 위해 해당 책임을 가장 잘 알고 있는 정보 전문가 객체를 선택했습니다.
- 바리스타는 아메리카노를 만드는 데 필요한 정보와 기술을 함께 구비하고 있는 전문가입니다
- . 아메리카노를 만들기 위한 지식은 바리스타의 상태로, 기술은 바리스타의 행동으로 간주할 수 있습니다.
- 이런 관점에서 바리스타는 스스로의 판단과 지식에 따라 행동하는 자율적인 존재라고 할 수 있습니다.
- 커피 주문을 위한 협력은 이제 바리스타가 새로운 커피를 만드는 것으로 끝납니다.
- 이로써 협력에 필요한 객체의 종류와 책임, 주고받아야 하는 메시지에 대한 대략적인 윤곽이 잡혔습니다.
- 이제 남은 일은 각 객체의 인터페이스를 구현 가능할 정도로 메시지들을 상세하게 정제하는 것입니다
다음으로
참조
'책 > 객체지향의 사실과 오해' 카테고리의 다른 글
OOP 객체지향처럼 생각해보기 2 (0) 2020.12.21