Skip to content

Commit

Permalink
Create 07_함께_모으기.md
Browse files Browse the repository at this point in the history
  • Loading branch information
ttaehee authored Jan 6, 2023
1 parent deda690 commit e6132c7
Showing 1 changed file with 200 additions and 0 deletions.
200 changes: 200 additions & 0 deletions 객체지향의_사실과_오해/07_함께_모으기.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
# Chapter 7 : 함께 모으기

<br/>

- [객체지향 설계의 세 가지 관점](#객체지향-설계의-세-가지-관점)
- [개념관점(Conceptual Perspective)](#개념관점-Conceptual-Perspective-)
- [명세관점(Specification Perspective)](#명세관점-Specification-Perspective-)
- [구현관점(Implementation Perspective)](#구현관점-Implementation-Perspective-)
- [코드와 세 가지 관점](#코드와-세-가지-관점)
- [인터페이스와 구현을 분리하라](#인터페이스와-구현을-분리하라)
- [총 과정](#총-과정)
- [1. 객체들간의 관계 파악](#1-객체들간의-관계-파악)
- [2. 협력 설계하기](#2-협력-설계하기)
- [3. 인터페이스로 정리하기 ](#3-인터페이스로-정리하기)
- [4. 구현하기](#4-구현하기)
- [💡 생각해볼 점](#-생각해볼-점)

<br/>

## 객체지향 설계의 세 가지 관점
마틴 파울러가 설명한 객체지향 설계 안에 존재하는 세가지 관점
이것은 곧, 개발자가 소프트웨어를 개발하는데 있어서 클래스를 어떻게 설계해야 하느냐에 대한 힌트가 될 수 있음

<br/>

### 개념관점(Conceptual Perspective)
- 설계는 `도메인` 안에 존재하는 `개념과 개념 사이의 관계` 표현이라는 관점
- 사용자가 도메인을 바라보는 관점 반영
- 도메인 개념을 참조하는 이유(도메인 개념 안에서 메시지에 대한 적절한 객체를 선택하는 것)
- 도메인에 대한 지식만으로도 -> 코드의 구조와 의미 쉽게 유추 -> 유지보수성 향상(변화에 쉽게 대응)

<br/>

### 명세관점(Specification Perspective)
- 도메인을 벗어나 개발자의 영역인 소프트웨어로 초점
- 소프트웨어 안의 `객체들의 책임`에 초점 = 객체가 협력을 위해 `무엇을` 할 수 있는가에 초점
- 구현이 아니라 `인터페이스`에 대해 프로그래밍하라

<br/>

### 구현관점(Implementation Perspective)
- 코드(객체들이 책임을 수행하는 데 필요한 동작)를 작성하는 것에 초점
- 객체의 책임을 `어떻게 수행`할 것인가에 초점

<br/><br/>


## 코드와 세 가지 관점

- 도메인 관점 반영 : 도메인을 구성하는 중요한 개념 간 관계를 클래스에 반영해야 함
- 명세 관점 반영 : 클래스의 공용 인터페이스를 만들어야 함
- 구현 관점 반영 : 클래스의 속성과 메서드는 캡슐화 되어야 함

<br/>

=> 클래스는 세가지 관점을 모두 수용할 수 있도록 `개념, 인터페이스, 구현``함께 드러내야`
동시에 코드 안에서 세 가지 관점을 쉽게 `식별`할 수 있도록 깔끔하게 `분리`해야 함
그러려면 훌륭한 설계 필요

<br/><br/>

## 인터페이스와 구현을 분리하라
- 저자는 인터페이스와 구현을 분리할 것을 다시한번 강조
= 명세관점과 구현관점이 뒤섞이는 것을 막자는 것

- 인터페이스가 구현 세부사항 노출 -> 취약한 설계(아주 작은 변동에도 전체 협력이 요동치게 됨)

<br/>

=> 분리하자
명세 관점, 즉 `인터페이스로 설계를 주도`하고 `구현을 통해 세부사항을 구성`하면 `설계의 품질`이 향상된다

<br/><br/>

## 총 과정

### 1. 객체들간의 관계 파악

`예시) 커피 전문점 도메인`
객체지향의 관점에서 커피 전문점이라는 도메인은 손님, 메뉴 항목, 메뉴판, 바리스타, 커피 객체로 구성된 작은 세상

<br/>

- 각 객체들의 관계
- 메뉴 항목은 메뉴판에 포함 -> 합성(포함)관계
- 손님은 메뉴판을 알아야함(메뉴판은 손님의 일부가 아님) -> 연관 관계
- 손님은 바리스타에게 주문을 해야함
- 바리스타와 커피 -> 연관 관계

<br/>

- `동적인 객체``정적인 타입으로 추상화`하여 복잡성을 낮춰야함 (타입)
- 타입은 분류를 위해 사용
- 상태와 무관하게 동일하게 행동할 수 있는 객체들을 `동일한 타입으로 분류`해 복잡성을 낮춤
- ex) 손님 타입, 메뉴판 타입 등
- 객체는 특정 타입의 인스턴스로 볼 수 있음

=> 다음 단계는 적절한 객체에게 적절한 책임 할당하기

<br/>

### 2. 협력 설계하기
- 훌륭한 객체를 설계하는 것이 아닌 훌륭한 협력을 설계하는 것이 중요
- 그러려면, 객체가 메시지를 선택하는 것이 아닌 `메시지가 객체를 선택`하게 해야

<br/>

- `메시지 -> 수신하기에 적합한 객체 선택 -> 선택된 객체는 메시지 처리할 책임을 부여받음 -> 메시지는 공용 인터페이스에 포함됨`
- 어떤 책임을 `수행하기 위한 정보`를 가장 많이 가지고 있는 객체에게 책임 할당할 것

- 객체 지향 세계에서는 무생물도 능동적이고 자율적(ex) 메뉴판)
- 객체지향은 현실세계를 모방,추상화가 아닌 `은유`할 뿐

<br/><br/>

- 예시) `협력을 시작하는 메시지` : 커피를 주문하라
- 메시지 처리하기에 `적합한 객체` : 손님 타입의 인스턴스
- 손님이 주문 중 스스로 할 수 없는 일 : 메뉴가 무엇인지 알아야함 -> 다른 객체에게 `요청`해야함

- 메시지 : 메뉴를 찾아라(메뉴를 `반환`받아야함) => 메뉴판

- 메시지 : 커피를 제조하라 -> 제조에 `필요한 정보(상태, 행위)를 알고` 있어야함 => 바리스타
- 커피 만드는 지식 : 상태
- 커피 만드는 기술 : 행동

<br>

### 3. 인터페이스로 정리하기
- `수신 가능한 메시지`만 추려해면 인터페이스가 됨
- 실제 소프트웨어 `구현`은 동적인 객체가 아닌 `정적인 타입을 통해` 이루어짐
-> 객체들을 분류하는 타입을 정의하고 `타입의 인터페이스`를 정의해야 함

- `클래스를 이용`해 타입 구현 (클래스와 타입은 다름, 클래스는 타입의 구현방법 중 하나)

<br/>

- interface를 통해 실제로 상호작용을 해보기 전, interface의 모습을 정확하게 예측하는 것은 힘듬

-> `interface를 결정`할 때,
가급적 객체 `내부의 구현`(객체가 어떤 속성을 가지는지, 그 속성이 어떤 자료 구조로 구현되었는지)에 대한 `어떤 가정도 하지 말것`

- 객체의 책임을 결정한 후 책임을 수행하는데 필요한 객체의 속성을 결정할 것

- 이는 구현 세부 사항을 객체의 공용 인터페이스에 노출시키지 않고,
인터페이스와 구현을 깔끔하게 분리할 수 있는 기본적인 방법

<br>

### 4. 구현하기

- 객체에게 메시지를 전송하기 위해서는 참조를 얻어야함
- 저자는 `메서드의 인자로 전달 받아` 참조 문제 해결 후
- 메서드의 구현을 채우기

= `구현 도중 인터페이스가 변경`될 수 있음
=> 설계를 간단히 끝내고 최대한 빨리 구현에 돌입하라

<br/><br/>

## 💡 생각해볼 점

- 책을 간략하게 총 정리 해보자면,
- 관계를 파악하고 메시지를 정해서, 메시지가 객체를 선택하게 하기
선택할 때는 수행할 때 필요한 정보를 많이 가지고 있는 아이를 선택하기
혼자 할 수 없는 일이라면 다른 객체에게 요청메시지 보내기
이 과정에서 동일한 책임을 가지고 있다면 같은 타입으로 분류하고
타입은 클래스를 통해 구현하기
이 때, 인터페이스와 구현 분리에 신경쓰기

<br/>

- 로또와 다리게임 과제를 할 때,
이 기능은 어떤 도메인에 넣어야할까 고민하면서
구현 중에도 위치가 여러번 바뀐적이 있었다
솔직히 구현보다 설계가 훨씬 어려웠다 당연한건가
- 툭정한 기준으로 설계를 하게된다면
갈팡질팡 하는 시간도 줄고,
나의 설계와 코드에 조금 더 확신을 가질 수 있을 것이다
- 혹시나 스스로의 경험치가 쌓여 저자와 다른 기준이 생길 수도 있을까
훗날의 이야기이고, 현재는 저자의 과정을 따라보려고 한다

<br/>

- 객체지향의 본질은 무엇일까
- 본질을 생각하기 전 일단, 객체지향을 왜 쓰는가부터 생각해보자면 효율적으로 코드를 짜기 위해서라고 생각한다
개발에서 뿐 아니라 평소에도 효율은 중요하다고 생각한다 특히 시간과 관련하여서는 더더욱!
효율적이기 위해서는 시간과 비용을 아낄 수 있는 코드를 짜야 한다
그래서 나는 유지 보수가 쉬운, 변경에 대응하기 쉬운 코드가 좋은 코드라고 생각한다
물론, 그러한 생각 없이 처음에 빨리 짜면 이것도 시간을 아끼는거 아니야?! 라고 할 수도 있지만
처음 한번보다는 유지보수와 확장이 필요한 시점들이 훨씬 많을거라 생각하기에 타협할 수 없다
이러한 객체지향을 쓰는 이유와 저자의 말을 참고해서 본질을 생각해보면
객체간의 메시징을 통해 유기적으로 구성이 되는것, 이는 시스템을 변경에 대응하기 쉽게 유연하게 만들어준다
메시지에 초점을 맞추면, 하나의 메시지를 통해 여러 객체들이 추상화, 캡슐화되므로,
결합도가 낮아지고 응집도가 높아지기 때문이다
이는 연결 고리들이 적으니 유지보수와 확장 시, 변경의 범위와 전파를 줄일 수 있다
따라서 시간과 다른 비용들을 모두 아껴 효율적이라고 말할 수 있다
그래서 나는 객체지향의 본질은, 결합도를 낮추고 응집도를 높이는 것이라고 생각한다
이러한 내 생각은 대화나 책들을 통해 언제든 변할 수 있다고 생각하며, 그러한 경험은 언제나 좋다

<br/>

0 comments on commit e6132c7

Please sign in to comment.