Search
📗

객체지향의 사실과 오해 - 조영호

Chapter 1. 협력하는 객체들의 공동체

1. 객체 지향의 목표

객체지향의 목표는 실세계를 모방하는 것이 아니다. 오히려 새로운 세계를 창조하는 것이다.
실세계를 모방하여 객체를 설계하는 것으로는 한계가 있음
→ 실세계의 연관성을 기반으로 객체를 설계하면 객체 간 연관성에 흠이 생길 여지가 있음
→ 실세계의 방화벽 개념으로 네트워크의 방화벽 객체를 생성할 수 없으며 오직 개념적으로 참고만 될 뿐
실세계를 모방하는 것은 객체지향에 대한 개념을 잡기 위한 교육적 수단임

2. 객체 지향의 본질

객체 지향이란 시스템을 상호작용하는 자율적인 객체들의 공동체로 바라보고 객체를 이용해 시스템을 분할하는 방법이다.
자율적인 객체란 상태와 행위를 함께 지니며 스스로 자기 자신을 책임지는 객체를 의미한다.
객체는 시스템의 행위를 구현하기 위해 다른 객체와 협력한다. 각 객체는 협력 내에서 정해진 역할을 수행하며 역할은 관련된 책임의 집합이다.
객체는 다른 객체와 협력하기 위해 메시지를 전송하고, 메시지를 수신한 객체는 메시지를 처리하는데 적합한 메서드를 자율적으로 선택한다.

3. 객체를 지향하라

가. 객체를 설계 시 유의할 점

클래스에 치우친 사고를 버리고 객체 간 메시지를 주고받는 동적 관계에 집중할 것
→ 클래스는 특정 언어에서 객체를 구현하는 수단일 뿐

나. 객체의 본질

객체의 협력 관계
→ 거대한 시스템은 객체의 협력으로 이루어짐
→ 모든 협력은 메시지를 바탕으로 이루어짐
→ 메시지 송신자 객체와 메시지 수신자 객체 간의 관계에 유의하여 객체를 설계해야 함
객체의 책임
→ 메시지를 수신 받은 객체는 해당 메시지에 대해 처리할 책임 지게 됨
→ 메시지 처리를 위해 특정 행동을 하는데 이것을 메소드로 구현할 수 있음
객체의 역할
→ 객체의 역할은 관련성이 높은 책임을 모아서 생성할 수 있음
역할에 대해 직관적으로 이해가 되지 않는다. 이하 인용구문에 대해 추후 고민해본다
여러 객체가 동일한 역할을 수행할 수 있음
역할은 대체 가능성을 의미함
각 객체는 책임을 수행하는 방법을 자율적으로 선택할 수 있음
하나의 객체가 동시에 여러 역할을 수행할 수 있음

Chapter 2. 이상한 나라의 객체

1. 객체지향 패러다임의 본질

객체지향적 패러다임의 본질은 이 세상의 복잡성을 인간이 이해할 수 있는 수준의 단순한 구조로 변형하여 문제를 해결하는 것
이러한 관점에서 객체란 현실 또는 해결하려는 문제의 물리적이거나 추상적인 개념을 이해할 수 있는 어떤 것이 되어야 함

Chapter 3. 타입과 추상화

1. 추상화를 통한 복잡성 극복

가. 추상화란

특정 목적(이해도 향상, 특정 특징 강조)을 이루기 위해 특정 절차나 특성을 간소화 또는 생략하여 복잡도를 극복하는 것
→ 지하철 노선도를 시민들에게 쉽게 이해시키기 위해(목적) 지하철이 지나는 지역의 지형적 특징을 매우 간략화(특정 절차나 특성 간소화)함

나. 추상화를 구현하기 위한 단계

1단계: 사물들 또는 개념 간 공통점은 드러내고 차이점은 간소화 또는 생략함
2단계: 중요한 부분을 강조하기 위해 불필요한 내용은 삭제함

2. 타입

타입의 핵심은 분류하는 것 추후 내용 보강

Chapter 4. 역할, 책임, 협력

1. 협력

가. 협력의 구성요소, 요청

요청을 받는다는 것은 해당 요청을 수신한 객체가 요청에 대한 책임을 질 의무와 능력 있음을 의미함

나. 협력의 구성요소, 응답

요청을 수신한 객체는 적절한 지식과 행동으로 요청에 대한 결과를 응답할 수 있음

다. 객체의 책임은 협력의 요청과 응답을 통해 정의됨

2. 책임

가. 객체의 책임

책임은 메세지의 요청에 대해 적절히 응답할 수 있는 것이나 의무를 말함
책임이란 구체적으로 어떻게 하겠다는 것이 아님. 이는 구현에 해당하는 것으로 객체와 책임이 모두 설계 된 후에 진행함
책임은 공용 인터페이스를 구성하며, 외부에 제공할 수 있는 정보가 됨
→ 객체의 외부에 공개할 수 있는 정보 또는 외부에 제공하는 서비스가 이에 해당함

3. 역할

가. 역할이란 책임의 집합

관련된 책임이 모이면 역할이 될 수 있음
ex) 증인(역할): 증인석에 설 것(책임) + 증언할 것(책임) + 선서를 할 것(책임) 등등

나. 역할은 인지의 과부하를 줄임

다. 역할의 가장 큰 가치: 협력의 추상화

보수적인 재판관(역할: 판사) - 악독한 고리대금업자(역할: 증인) - 국선변호사(역할: 변호인)
진보적인 재판관(역할: 판사) - 착하고 똑똑한 배만진(역할: 증인) - 엘리트 로펌 변호사(역할: 변호인)
→ 위와 같이 객체가 바뀌더라도 역할은 고정되므로 전체적인 시스템의 협력을 추상적으로 설계할 수 있음

4. 객체지향 설계 기법

가. 책임-주도 설계

시스템이 서용자에게 제공해야 하는 기능인 시스템 책임을 파악
시스템 책임을 더 작은 책임으로 분할
분할된 책임을 수행할 수 있는 적절한 객체 또는 역할을 찾아 책임을 할당
객체가 책임을 수행하는 중 다른 객체의 도움이 필요한 경우 이를 책임질 적잘한 객체 도는 역할을 탐색
해당 객체 또는 역할에게 책임을 할당함으로써 두 객체가 협력하게 됨

나. 디자인 패턴

다. TDD

TDD는 책임-주도 설계의 기본 개념을 따르며, 협력, 책임, 역할에 대한 이해가 선행되어야 효과적으로 TDD를 활용할 수 있음

Chapter 5. 책임과 메시지

1. 자율적인 책임

가. 자율성

객체의 책임은 메세지의 요청에 반응하지만 요청에 대해 구체적으로 책임지는 것은 객체에게 맡겨야 함
메세지가 일일이 객체의 책임을 구체화하여 요청하는 것은 객체의 자율성을 침해하는 것

나. '어떻게'가 아니라 '무엇'을

자율적인 책임이란 '무엇'을 하는지에 대한 설명임
어떻게 책임을 질지에 대해서는 외부에 드러낼 필요 없으며, 객체가 자율적으로 알아서 수행하 영역임

2. 메시지를 따르라

가. 책임 - 주도 설계 다시 살펴보기

첫번째, 어플리케이션 전체의 기능을 시스템의 책임으로 인식
두번째, 시스템의 책임을 나누기 위해 협력 관계를 시작할 객체 찾기
세번째, 협력 관계를 시작할 객체에게 시스템의 책임을 객체의 책임으로 할당
네번째, 시작 객체의 책임을 완수하기 위해 도움을 요청하기 위한 메세지를 결정
다섯번째, 해당 메세지를 수신하기 적절한 객체 선택
→ 메시지가 수신 객체의 책임을 결정함

나. What/Who 사이클

객체 사이의 협력 관계는 What(메세지, 어떤 행위)를 수행할 것인지를 우선 결정
What이 결정되면 이것을 Who(수신 객체)가 수행할 것인지 결정

3. 객체 인터페이스

가. 공용 인터페이스의 구성요소

객체의 공용 인터페이스는 객체가 수신하는 메시지의 목록임

나. 책임, 메시지, 그리고 인터페이스

메서드란 객체가 메시지를 수신했을 때 책임을 구체적으로 수행하는 방법

다. 인터페이스가 필요한 이유

'변경'이라는 거대한 적을 상대하기 위한 유일한 무기
인간의 두뇌의 한계를 고려하여 '변경'에 대응하기 위해 안전지대와 위험지대를 구분해서 대응해야 함
안전지대: 구현부분을 변경해도 외부에 영향을 주지 않음
위험지대: 구현부분을 변경하면 외부에 영향을 줄 수 있음

3. 인터페이스와 구현의 분리

가. 인터페이스와 구현의 분리 원칙

훌륭한 객체지향적 설계에서는 인터페이스만으로도 전체적인 시스템의 흐름을 알 수 있음
객체 외부에 영향을 미치는 변경은 오직 인터페이스에 명시된 메세지를 변경할 때 뿐임
→ 인터페이스에는 서로 다른 객체에게 영향을 주는 모든 메세지가 포함되어 있음
→ 위험지대를 다루는 것이 인터페이스의 영역
외부로 드러나는 인터페이스 부분과 외부로 드러나지 않는 구현 부분은 구분되어야 함
→ 변경에 대응하기 위함

나. 캡슐화(=정보은닉)

데이터 캡슐화: 외부에서 반드시 접근해야만하는 상태와 행위에 대해서만 공용 인터페이스를 통해 노출하고 나머지는 감추는 것

Chapter 6. 객체 지도

1. 구조 설계

가. 설계 철학

미래를 대비하는 가장 좋은 방법은 추후 변경될 여지를 설계에 남겨두는 것
→ 아무리 미래의 변화를 예측한다고 해도 사람인 이상 모두 예측하는 것은 불가능
여지를 남겨둔다는 것은 자주 변경되지 않는 핵심 또는 근간을 바탕을 중심으로 안정적인 구조로 설계하는 것

2. 기능과 구조

가. 구조

구조는 사용자나 이해관계자들이 도메인에 관해 생각하는 개념과 개념들 간의 관계로 표현함
도메인이란 사용자가 프로그램을 사용하는 대상 분야
모델이란 대상을 단순화하고 구조적으로 표현하는 것
도메인 모델: 사용자가 프로그램을 사용하는 대상 분야에 대해 단순화하여 구조적으로 표현한 것
→ 도메인 모델을 설계할 때, 시스템 이미지에 대해 개발자의 입장과 사용자의 입장을 고려해야 함

나. 기능

기능은 사용자의 목표를 만족시키기 위해 책임을 수행하는 시스템의 행위로 표현함
프로그램 사용에 대한 사용자의 목표를 만족시키기 위해 프로그램의 기능의 목록을 정리하여 기능적 요구사항을 작성함
유스케이스(Use Case): 사용자의 목표를 달성하기 위해 사용자와 시스템 간의 상호작용을 텍스트로 정리한 것

3. 재료 합치기: 기능과 구조의 통합

가. 도메인 모델, 유스케이스, 책임-주도 설계

이러한 시도는 '변경'에 대한 파급효과를 최소화하기 위한 설계를 하는 것이 목표
유스케이스에서 최초의 책임(거대한 책임, 시스템 책임)을 뽑아냄
도메인 모델에서 안정적인 구조를 만들어 냄
책임-주도 설계에서 최초의 책임을 작은 책임으로 나누고, 도메인 모델에서 잡은 구조 속의 객체에게 적절한 책임을 할당함

나. 책임-주도 설계를 기반으로 통합

객체의 이름은 도메인 모델에 포함된 개념을 차용
책임 할당의 기본 원칙: 해당 책임과 관련된 정보나 행위 등과 가장 관련성이 있는 객체에 할당함

Chapter 7. 함께 모으기

1. 객체지향적으로 커피 전문점 이해하기

도메인: 커피를 주문하는 과정을 객체 간 협력관계로 구현하는 것
도메인이란 해결 할 문제 정의 또는 관심 주제

가. 커피 전문점의 객체화

손님(Object 이하 O)는 메뉴판(O)의 여러 항목(O) 중 하나 또는 다수를 선택하여 바리스타(O)에게 주문함
바리스타(O)는 주문을 받은 항목(O)에 맞는 커피(O)를 제조함

나. 객체 간 관계

손님은 메뉴판에서 하나 또는 다수의 항목을 선택함
손님은 바리스타에게 선택한 항목에 맞는 커피를 주문함
바리스타는 커피를 제조함 등등

다. 객체 분류

객체의 클래스: 객체의 구현에 대한 정의, 객체 내부의 상태와 상태를 구현하기 위한 연산이 포함됨
객체의 타입: 객체의 인터페이스, 상태와 행동이 동일한 객체의 묶음
4가지 종류의 커피 객체는 모두 '커피 타입'으로 묶을 수 있음
반대로 '커피 타입'에는 4가지의 '커피 항목 타입'의 인스턴스 존재

라. 타입 간 관계

핵심요소 1) 도메인을 구성하는 타입
핵심요소 2) 타입 간 관계를 파악하여 도메인을 이해
메뉴판 타입과 메뉴 항목 타입 간 관계: 포함(containment) or 합성(composition) 관계, 메뉴 항목 타입 4가지는 메뉴판 타입에 일부로 포함됨.
손님과 메뉴판 간 관계: 연관(association) 관계, 각 타입 간 포함되지 않는 상태가 아니고 연관성만 있음. ex) 손님과 바리스타의 관계

2. 객체지향적으로 설계하기

객체지향적 설계 목표: 협력하는 자율적인 객체들의 공동체 창조

가. 협력 설계

객체지향 설계의 첫번째 목표: 훌륭한 협력을 설계하는 것
협력 설계 포인트 1) 객체 보다 도메인의 주요 메세지 선택
협력 설계 포인트 2) 메세지를 수신하는 객체 선택
협력 설계 포인트 3) 메세지 수신 객체의 메세지 처리 책임 명시, 필요 시 다른 객체에 도움 요청 등

가-1) 첫번째 메세지: 커피 주문

메세지 수신 객체: 손님
손님 객체의 메세지 처리 책임: 특정 메뉴의 이름을 선택
손님 객체 스스로 메뉴의 옵션을 알 수 없으므로 메뉴 객체에 특정 메뉴 항목을 요청

가-2) 두번째 메세지: 특정 메뉴 항목 요청

메세지 수신 객체: 메뉴판
메뉴판 객체의 책임: 손님 객체로부터 전달 받은 특정 메뉴의 이름에 맞는 메뉴 항목 객체를 손님에게 전달

가-3) 세번째 메세지: 커피 제조

메세지 수신 객체: 바리스타
바리스타 객체의 책임: 손님 객체로부터 전달 받은 메뉴 항목 객체에 맞는 커피 객체를 생성하여 손님에게 전달
바리스타 객체의 고유 상태와 로직으로 커피 객체 생성 가능(자율적인 객체)

나. 인터페이스 정리

메세지를 수신한 객체 내 메세지와 연관된 operation 정의 ex) 손님 객체 내 커피 주문 operation 정의해야 함
협력 설계 과정에서 정의된 operation은 외부에서 접근 가능한 공용 인터페이스임(public 선언)
인터페이스와 구현의 분리: 인터페이스를 먼저 정의한 후, 구현 시도

3. 구현하기

객체의 내부로직을 구현하면서 인터페이스와 상이한 부분이 있다면 인터페이스도 함께 수정
구현코드는 다음의 레포에 정리, https://github.com/MJbae/OOP_JAVA

Reference

조영호, 객체지향의 사실과 오해