Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions 이현희/Chapter0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# 오브젝트 vs 객사오
객사오
- 첫번째 걸음<br>
클래스가 아니라 객체를 바라보기
- 두번째 걸음<br>
객체를 독립적인 존재가 아니라 기능을 구현하기 위해 협력하는 공동체 속의 존재로 바라보기

오브젝트
- 세번째 걸음<br>
협력에 참여하는 객체들에게 적절한 역할과 책임을 부여하기
- 네번째 걸음<br>
프로그래밍 언어라는 틀에 위의 걸음들을 잘 담아낼 수 있는가

생각을 많이 해보게 하던 객사오와 다르게, 오브젝트는 정답을 직접적으로 제시함.

이책에서 말하는 것들이 전부 정답은 아님. 이런식으로 하는 거다라는 시작점을 제시할 뿐.

실무에 반영하려면 설계를 약간 비트는 등의 테크닉이 필요할 수도 있음

# 추천사
메타프로그래밍, 함수형 프로그래밍, 자동구성 등에 현혹되지 말고 객체지향에 집중해라

스프링의 시작은 객체지향이었다.

# 대상 독자
객체지향 언어를 할 줄 알고, 객체지향의 기본 개념을 알고(=객사오 읽은 사람), 실무에서 객체지향 프로그래밍을 하면 설계에 대한 고민을 해본 사람

# 패러다임
과학사를 연구하던 토마스 쿤에 의해 지금의 의미를 가지게 된 "패러다임"

패러다임 : 한 시대의 사회 전체가 공유하는 이론이나 방법, 문제의식 등의 체계

프로그래밍에서의 패러다임 : 성숙한 개발자 사회에 의해 수용된 프로그래밍 방법, 문제해결 방법, 프로그래밍 스타일

패러다임은 동일한 기초를 공유하도록 하여, 기초적인 내용에 대한 불필요한 논쟁을 막는다.

프로그래밍 언어와 패러다임은 떼어놓을 수 없는 관계. 프로그래밍 언어에는 패러다임이 녹아있거나 근본에 존재하기 때문.

일반적인 패러다임과 프로그래밍에서의 패러다임의 차이점
1. 프로그래밍 패러다임은 두 개의 패러다임이 공존 가능
2. 프로그래밍 패러다임은 혁명적이라기보단 발전적. 기존의 패러다임을 부수는 게 아니라 그 위에 쌓임
66 changes: 66 additions & 0 deletions 이현희/Chapter1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# 실무는 이론에 앞선다
이론은 실무를 가지고 만든 귀납적 결과물

특히 소프트웨어 설계, 유지보수 분야에서는 실무가 이론보다 다섯 수는 앞서있음.

따라서, 설계와 유지보수에 대해서 논할 때는 이론보다는 실무(=코드)를 가지고 논하는 게 좋음

# 작은 소극장 예제
막간 자바 문법 - ellipsis => 인자가 "Ticket ... tickets"면, Ticket[] 타입

## 소프트웨어 모듈의 3가지 목적
1. 실행 중 제대로 동작하는 것
2. 변경에 용이한 것
3. 의사소통에 용이한 것

위의 소극장 예제는 1번만 달성함

2번 => Audience나 TicketSeller 변경 시 Theater 수정 필요. Bag이나 TicketOffice 수정 시에도 Teather 수정 필요.
3번 => 직관과 위배됨. Theater가 Audience의 가방을 맘대로 열어보고 돈을 차감함.

Theater가 모든 객체들에게 관여함 => Theater의 의존성이 과하다 = 결합도가 높다

# 개선하기
## 1차 개선
Theater가 모든 객체들에게 접근하고 관여하는 것이 문제 => 다른 객체들의 자율성을 보장해야 함.

Audience가 알아서 Bag을 처리하도록 하고, TicketSeller가 알아서 TicketOffice와 Ticket을 처리하도록 함.

자율적인 객체만 보장해주면 응집도는 올라가고, 결합도는 낮아짐.

## 절차지향 vs 객체지향
프로세스와 데이터를 어디에 담냐에 대한 관점으로 비교 가능

절차지향에서 객체는 그냥 데이터를 담을 뿐. 프로세스는 하나의 객체가 통솔함.

객체지향은 객체가 알아서 자신의 데이터를 처리함. 즉, 객체가 데이터와 프로세스를 다 같이 가지고 있음.

## 2차 개선
Audience가 Bag의 자율성을 보장하도록 변경 + TicketSeller가 TicketOffice의 자율성을 보장하도록 변경

Audience가 Bag에게 자율성을 준 건 좋은데, TicketSeller가 TicketOffice에게 자율성을 주니 결합도가 증가함

TicketOffice가 Audience에 대한 의존성을 가짐.

trade off라 선택해야 함.

## 의인화
의사소통을 위해서는 코드가 직관적이어야 하긴 함.

그런데 스스로 짐을 빼고 넣는 가방같이 객체가 의인화 되는 것은 감당할 필요가 있음.

# 설계
무슨 고차원적인 일이 아니라, 코드를 어디에 위치시킬 지 결정하는 것.

따라서 코드가 없이는 논의가 불가능함.

## 좋은 설계
소프트웨어의 요구사항은 매번 변함 = 쉽게 변경할 수 있어야 함 = 쉽게 이해되어야 함

데이터와 프로세스를 합친 객체의 형태로 작성하면 이해하기 쉬워짐
1. 데이터와 프로세스를 객체로 모으기

그러나 객체로 모았다고 다 끝난 것은 아니고, 객체 간의 상호작용 즉, 의존성을 관리해야 함
2. 객체 간 의존성 관리

+ 어떻게 보면 1번은 응집도고 2번은 결합도인듯??
146 changes: 146 additions & 0 deletions 이현희/Chapter2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# 영화 예매 시스템 요구사항
영화 : 영화에 대한 기본정보를 의미

상영 : 실제로 관객들이 영화를 관람하는 사건을 의미<br>
=> 관객들은 영화가 아니라 상영을 위해 돈을 지불하는 것

특정 조건을 만족하면 할인 가능
1. 할인 조건 : 할인 여부 결정
1. 순서 조건 : 입장 순번에 따라 할인 여부 결정 eg. 10번째 손님 할인
2. 기간 조건 : 요일, 시작시간, 종료시간으로 구성. 그 기간에 포함되면 할인 대상
2. 할인 정책 : 할인 액수 결정
1. 금액 할인 정책 : 특정 값 만큼 할인
2. 비율 할인 정책 : 특정 비율 만큼 할인

영화 별로 0 또는 1개의 할인 정책 지정 가능<br>
할인 조건은 할인 정책이 있다면, 몇 개든 상관 없음(0개?)

할인 적용을 위해서는
1. 할인 조건을 만족하는가 확인
2. 할인 정책을 통한 요금 계산

사용자가 예매를 완료하면, 시스템은 예매 정보를 생성

# 협력, 객체, 클래스, 도메인
객체지향은 클래스가 아니고 객체를 지향

협력 속에 1. 어떤 객체가 필요하고 2. 그 객체들에게 어떤 책임을 할당할 것인지에 집중<br>
객체 식별 -> 타입 식별 -> 클래스 설계

## 도메인 구조 -> 클래스 구조
도메인 = 문제를 해결하기 위해 소프트웨어를 사용하는 분야

객체지향의 장점 : 도메인 분석 ~ 코드 구현까지 객체라는 추상화 기법을 동일하게 이용가능

## 클래스 생성
공용 인터페이스는 public으로, 구현은 private으로 => 객체의 자율성, 프로그래머의 자유 보장 가능
1. 객체의 자율성
객체 = 상태 + 행동
캡슐화 => 인터페이스와 구현의 분리
2. 프로그래머의 자유
프로그래머를 2가지로 분리
1. 클래스 작성자(=API 작성자)
2. 클라이언트 프로그래머(=API 이용자)

이때 인터페이스와 구현의 분리는 둘 모두에게 이롭다

설계라는 건 변경이 쉽도록 하는 것

## 협력 속의 객체 공동체
영화 예매 가격 계산을 Screening이 Movie에게 요청

협력 속에서, 객체는 자신이 할 수 없는 일을 요청하고 그걸 받은 객체는 응답함.

메시지와 메서드

Money라는 멤버 변수가 하나 뿐인 클래스 => 도메인의 의미를 풍부하게 표현<br>
특정 제약이나 규칙 반영 가능(like 일급 컬렉션)

## 할인 요금 계산을 위한 협력
Movie 클래스 내에서는 할인 정책에 따라 할인 가격을 계산하는 것을 요청함.

그런데 어떤 할인 정책을 사용할 지는 명시되어 있지 않음 => 상속을 통한 다형성 이용

할인 정책 클래스(DiscountPolicy)는 큰 흐름만 구성되어 있는 abstract class이고,<br>
구체적인 할인 가격 계산은 자식에게 맡기고 있음(Template Method 패턴)

# 기타 사항
## 생성자를 통한 객체의 상태 보장
도메인의 규약사항을 생성자로 표현 가능

Movie의 생성자 => DiscountPolicy 1개만을 인자로 받음
DiscountPolicy의 생성자 => DiscountCondition 여러 개를 인자로 받음

## 컴파일 시간 의존성과 런타임 의존성
어떤 클래스가 다른 클래스에 접근할 수 있는 경로가 있거나(=참조 변수?),<br>
해당 클래스의 메서드를 호출할 경우, 둘 사이에 의존성이 있다고 말함.

Movie 클래스의 경우, DiscountPolicy에 의존함.<br>
얘는 구체적인 구현이 아니고 추상적인 개념임

그런데 실제 생성자를 호출할 때 구체적인 구현체를 넣어줌

즉, 코드에서의 의존성 실제 실행 시의 의존성은 다를 수 있다.<br>
다른 말로, 컴파일 시간의 의존성과 런타임의 의존성을 다를 수 있다.

이것이 바로 유연성, 재사용성의 근원.

그러나 설계가 유연해질 수록, 코드를 이해하긴 어렵다.<br>
실제로는 누구와 의존하는 지 가봐야 아니까;;

## 의존성이 어떻게 바뀔 수 있는건데?
상속을 통해 다형성을 구현했기 때문

상속은 코드 재사용의 의미도 있지만, 인터페이스의 승계라는 의미도 있음.<br>
인터페이스란 객체가 이해할 수 있는 메시지의 모음이고, 타입의 근원이다.

자식 객체는 부모와 이해할 수 있는 인터페이스가 같거나 더 많기 때문에,<br>
자식 클래스는 부모 클래스와 같은 타입으로 불 수 있음.(=업캐스팅)

Movie 입장에서는 누가 대답하던 알바 아님. 그냥 이 메시지를 이해하고 응답할 대상이 필요할 뿐

다형성 = 하나의 메시지에 대해 다르게 대답할 수 있는 능력

컴파일 시간이 아닌 런타임에 "메시지에 대한 응답 메서드"를 결정함으로써 가능(=동적 바인딩)

다형성 구현을 위해서는 상속 뿐 아니라 인터페이스도 있음.<br>
인터페이스는 공유할 구현이 하나도 없을 때 쓰는 것

## 추상화와 유연성
추상화의 장점
1. 요구사항은 높은 수준에서 서술 가능(=인지 과부하 줄임)
2. 설계가 유연해짐

추상화를 이용해 요구사항을 기술한다는 것 = 애플리케이션의 협력흐름을 기술한다는 것<br>
이 협력 흐름을 재사용될 수 있다. 그 예시가 바로 디자인 패턴이나 프레임워크

추상화를 중심으로 설계하면, 유연하고 확장 가능해짐. 잘 변하는, 구체적인 것에 의존하지 않기 때문

협력 흐름을 추상화한다는 관점에서, 예외 상황을 만드는 것은 좋은 방식이 아님. 협력 흐름이 깨지는 상황이 생기는 거니까~

컨텍스트 독립성 <- 이게 먼 뜻임?

## NoneDiscountPolicy에서 추상클래스 방식 vs 인터페이스 방식
할인 정책이 존재할 때의 흐름과 없을 때의 흐름이 아예 다름

이걸 기존의 추상 클래스 방식으로 다룰 거냐, 아니면 인터페이스를 위에 하나 더 둘 거냐의 차이

이처럼 설계에는 여러 방법이 있고, 트레이드 오프가 있다.<br>
이 트레이드 오프를 고려한다는 것은 곧 모든 코드에는 이유가 있다는 것(거기에 있는)

## 상속 vs 합성
상속은
1. 캡슐화를 위반
부모의 구현을 다 알아야 함.
부모가 바뀌면 자식도 다 바뀌어야 함.
2. 설계의 유연성을 떨어뜨림
컴파일 타임에 부모-자식 관계를 지정함.
자식 A와 자식 B를 서로 갈아끼기 힘듦.

합성은 이 두 가지 문제를 해결함.

뭐 상속을 아예 쓰지 말라는 건 아니긴 함 -> 상속은 다형성 구현할 때도 쓰이기 때문 -> 근데 꼭 상속만 다형성 구현에 쓰이는 건 또 아님<br>
??? 어쩌래는겨



89 changes: 89 additions & 0 deletions 이현희/Chapter3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# 객체지향의 본질
2장 내용은 구현에 치우친 설명이었음

객체지향의 본질은 책임, 협력, 역할임.

객체지향 애플리케이션의 제어 흐름은 어느 한 객체에 의해 통제되는 것이 아니고<br>
여러 객체에 균형있게 나눠져 있음.<br>
객체들은 자신에게 배정된 로직을 실행함.

책임 : 객체가 협력에 참여하기 위해 실행하는 로직
협력 : 객체들이 기능 구현을 위해 상호작용 하는 것
역할 : 객체가 수행하는 책임이 모인 것

# 협력
협력(=객체 간의 상호작용)은 메시지를 통해서만 일어남<br>
수신 받은 메시지에 대한 처리 방법(=메서드)는 수신받은 객체가 자율적으로 결정함.

내부 구현을 캡슐화(=자율적인 객체) 해 놓아야 일부 책임(=로직)을 위임할 수 있음.

객체의 존재 이유 = 협력에 참여하기 때문<br>
객체가 협력에 참여 가능한 이유 = 협력에 적절한 행동을 보유하고 있기 때문

협력이 객체의 행동을 결정한다<br>
협력이 바뀌면 객체의 행동도 변해야 한다.

eg. Movie라는 객체는 어떤 행동을 해야할까?<br>
일반적인 생각으로는 play 같은 행동이 있겠지만, 티켓 예매라는 협력 속에서는, 가격 계산이라는 행동이 있음.

협력은 행동을 정하고, 행동과 상태는 서로를 정한다(협력이 상태를 바꾸고 상태에 기반해 행동하고 반복)

# 책임
객체가 협력을 위해 수행하는 행동임

책임은 하는 것과 아는 것으로 구분됨.

책임이 메시지와 내부 속성(=상태)을 정함.

책임이 메시지보다 크므로, 여러 개의 메시지로 쪼개지게 됨.

아는 것과 하는 것은 밀접하게 관련되어 있음<br>
이것은 객체에게 책임을 할당하는 가장 기본적인 힌트를 제공함<br>
뒤에 나오지만, 이 장에서 간략하게 언급하는 건 Information Expert 패턴

시스템의 기능을 시스템의 책임으로 보고,<br>
이 책임을 수행하기 위해 작은 책임들로 쪼개고, 객체들에게 할당.<br>
다시 또 그 책임을 쪼갠 뒤 객체들에게 할당하는 것을 반복

메시지가 객체를 선택하는 것.<br>
물론 객체도 이미 어느정도 개념은 있음(도메인 모델에서 가져온다던가)<br>
여기서 말하는 건 객체를 보고 어떤 메시지가 어울릴까 고민하는 게 아니고,<br>
협력을 위한 책임을 통해 메시지를 만들고, 이 메시지를 어느 객체에 할당할 지 선택하는 게 좋다는 것.<br>
=> 이러면 메시지부터 떠올리기 때문에 "무엇을"에 집중할 수 있고, 협력에 필요한 메시지만 생각하기 떄문 "최소개수"도 만족 가능

객체는 자신이 수행할 수 있는 행동을 통해 자신의 존재 의미를 가짐<br>
객체의 쓸모, 존재 이유, 품질 모두 그 행동(=책임)을 얼마나 잘 정의헀냐로 결정됨

# 역할
간단하게 말하자면 책임의 집함.

협력을 모델링하는 책임주도설계 과정에서 특정 책임을 어떤 객체에게 맡긴다고 생각하는 게 아니라<br>
어떤 역할에 맡긴다고 생각하는 것이 더 좋다.<br>
나중에 그 역할에 해당하는 객체가 하나인 걸로 결정되면, 그때 객체라고 해도 됨.

역할은 "재사용 가능한" 협력을 만들 수 있게 해준다.<br>
역할은 책임의 집합이고, 어떠한 객체든지 그 책임의 집합을 감당할 수 있다면 그 역할을 수행할 수 있다.<br>
역할을 구현하는 방법 = 상속, 인터페이스

협력은 역할의 상호작용이라고도 볼 수 있음<br>
협력 -> 역할 -> 객체 -> 클래스

도메인 모델은 사람이 세상을 바라보는 모델임<br>
그래서 근본적으로 불안함.<br>
그래서 협력 속에서 상호작용하는 그 대상들이 객체인지, 클래스인지, 역할인지 초기엔 분간하기 어렵고 나중에 바뀔 수도 있음<br>
따라서 그냥 그 대상을 "후보(Candidate)"라는 개념으로 바라보는 것이 좋음.

특정 시나리오에 대한 협력을 구성할 때<br>
보통 도메인 모델의 개념들을 "후보"로 선택해 책임을 할당하게 되는데<br>
이때 비슷한 구조의 협력이 보일 수 있음.<br>
그럼 이제 역할을 통한 협력의 추상화 삽가능

다양한 객체가 협력할 게 확실하다면 역할로 딱 정하고 시작해도 되고<br>
그게 어려우면 후보라고 뭉뚱그려 표현해도 되고<br>
협력 자체가 어떤 상호작용인지 판단하기 어렵다면 구체적인 객체(일종의 예시로서)를 통해서 생각해도 됨

역할은 객체의 추상화라고 볼 수 있고,<br>
그래서 2장에 나온 추상화의 장점 2가지가 적용됨<br>
1. 추상적인 수준에서의 기술 가능(협력을)
2. 유연함(다양한 객체가 참여할 수 있으므로, 협력이 유연해짐)
역할은 협력 내에서만 임시적으로 존재하며, 배우와 배역의 예제를 봤을 때 페르소나라고도 볼 수 있다.