diff --git "a/\354\235\264\355\230\204\355\235\254/Chapter0.md" "b/\354\235\264\355\230\204\355\235\254/Chapter0.md" new file mode 100644 index 0000000..f46bc30 --- /dev/null +++ "b/\354\235\264\355\230\204\355\235\254/Chapter0.md" @@ -0,0 +1,41 @@ +# 오브젝트 vs 객사오 +객사오 +- 첫번째 걸음
+클래스가 아니라 객체를 바라보기 +- 두번째 걸음
+객체를 독립적인 존재가 아니라 기능을 구현하기 위해 협력하는 공동체 속의 존재로 바라보기 + +오브젝트 +- 세번째 걸음
+협력에 참여하는 객체들에게 적절한 역할과 책임을 부여하기 +- 네번째 걸음
+프로그래밍 언어라는 틀에 위의 걸음들을 잘 담아낼 수 있는가 + +생각을 많이 해보게 하던 객사오와 다르게, 오브젝트는 정답을 직접적으로 제시함. + +이책에서 말하는 것들이 전부 정답은 아님. 이런식으로 하는 거다라는 시작점을 제시할 뿐. + +실무에 반영하려면 설계를 약간 비트는 등의 테크닉이 필요할 수도 있음 + +# 추천사 +메타프로그래밍, 함수형 프로그래밍, 자동구성 등에 현혹되지 말고 객체지향에 집중해라 + +스프링의 시작은 객체지향이었다. + +# 대상 독자 +객체지향 언어를 할 줄 알고, 객체지향의 기본 개념을 알고(=객사오 읽은 사람), 실무에서 객체지향 프로그래밍을 하면 설계에 대한 고민을 해본 사람 + +# 패러다임 +과학사를 연구하던 토마스 쿤에 의해 지금의 의미를 가지게 된 "패러다임" + +패러다임 : 한 시대의 사회 전체가 공유하는 이론이나 방법, 문제의식 등의 체계 + +프로그래밍에서의 패러다임 : 성숙한 개발자 사회에 의해 수용된 프로그래밍 방법, 문제해결 방법, 프로그래밍 스타일 + +패러다임은 동일한 기초를 공유하도록 하여, 기초적인 내용에 대한 불필요한 논쟁을 막는다. + +프로그래밍 언어와 패러다임은 떼어놓을 수 없는 관계. 프로그래밍 언어에는 패러다임이 녹아있거나 근본에 존재하기 때문. + +일반적인 패러다임과 프로그래밍에서의 패러다임의 차이점 +1. 프로그래밍 패러다임은 두 개의 패러다임이 공존 가능 +2. 프로그래밍 패러다임은 혁명적이라기보단 발전적. 기존의 패러다임을 부수는 게 아니라 그 위에 쌓임 \ No newline at end of file diff --git "a/\354\235\264\355\230\204\355\235\254/Chapter1.md" "b/\354\235\264\355\230\204\355\235\254/Chapter1.md" new file mode 100644 index 0000000..896ff47 --- /dev/null +++ "b/\354\235\264\355\230\204\355\235\254/Chapter1.md" @@ -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번은 결합도인듯?? \ No newline at end of file diff --git "a/\354\235\264\355\230\204\355\235\254/Chapter2.md" "b/\354\235\264\355\230\204\355\235\254/Chapter2.md" new file mode 100644 index 0000000..8fa292e --- /dev/null +++ "b/\354\235\264\355\230\204\355\235\254/Chapter2.md" @@ -0,0 +1,146 @@ +# 영화 예매 시스템 요구사항 +영화 : 영화에 대한 기본정보를 의미 + +상영 : 실제로 관객들이 영화를 관람하는 사건을 의미
+=> 관객들은 영화가 아니라 상영을 위해 돈을 지불하는 것 + +특정 조건을 만족하면 할인 가능 +1. 할인 조건 : 할인 여부 결정 + 1. 순서 조건 : 입장 순번에 따라 할인 여부 결정 eg. 10번째 손님 할인 + 2. 기간 조건 : 요일, 시작시간, 종료시간으로 구성. 그 기간에 포함되면 할인 대상 +2. 할인 정책 : 할인 액수 결정 + 1. 금액 할인 정책 : 특정 값 만큼 할인 + 2. 비율 할인 정책 : 특정 비율 만큼 할인 + +영화 별로 0 또는 1개의 할인 정책 지정 가능
+할인 조건은 할인 정책이 있다면, 몇 개든 상관 없음(0개?) + +할인 적용을 위해서는 +1. 할인 조건을 만족하는가 확인 +2. 할인 정책을 통한 요금 계산 + +사용자가 예매를 완료하면, 시스템은 예매 정보를 생성 + +# 협력, 객체, 클래스, 도메인 +객체지향은 클래스가 아니고 객체를 지향 + +협력 속에 1. 어떤 객체가 필요하고 2. 그 객체들에게 어떤 책임을 할당할 것인지에 집중
+객체 식별 -> 타입 식별 -> 클래스 설계 + +## 도메인 구조 -> 클래스 구조 +도메인 = 문제를 해결하기 위해 소프트웨어를 사용하는 분야 + +객체지향의 장점 : 도메인 분석 ~ 코드 구현까지 객체라는 추상화 기법을 동일하게 이용가능 + +## 클래스 생성 +공용 인터페이스는 public으로, 구현은 private으로 => 객체의 자율성, 프로그래머의 자유 보장 가능 +1. 객체의 자율성 + 객체 = 상태 + 행동 + 캡슐화 => 인터페이스와 구현의 분리 +2. 프로그래머의 자유 + 프로그래머를 2가지로 분리 + 1. 클래스 작성자(=API 작성자) + 2. 클라이언트 프로그래머(=API 이용자) + + 이때 인터페이스와 구현의 분리는 둘 모두에게 이롭다 + + 설계라는 건 변경이 쉽도록 하는 것 + +## 협력 속의 객체 공동체 +영화 예매 가격 계산을 Screening이 Movie에게 요청 + +협력 속에서, 객체는 자신이 할 수 없는 일을 요청하고 그걸 받은 객체는 응답함. + +메시지와 메서드 + +Money라는 멤버 변수가 하나 뿐인 클래스 => 도메인의 의미를 풍부하게 표현
+특정 제약이나 규칙 반영 가능(like 일급 컬렉션) + +## 할인 요금 계산을 위한 협력 +Movie 클래스 내에서는 할인 정책에 따라 할인 가격을 계산하는 것을 요청함. + +그런데 어떤 할인 정책을 사용할 지는 명시되어 있지 않음 => 상속을 통한 다형성 이용 + +할인 정책 클래스(DiscountPolicy)는 큰 흐름만 구성되어 있는 abstract class이고,
+구체적인 할인 가격 계산은 자식에게 맡기고 있음(Template Method 패턴) + +# 기타 사항 +## 생성자를 통한 객체의 상태 보장 +도메인의 규약사항을 생성자로 표현 가능 + +Movie의 생성자 => DiscountPolicy 1개만을 인자로 받음 +DiscountPolicy의 생성자 => DiscountCondition 여러 개를 인자로 받음 + +## 컴파일 시간 의존성과 런타임 의존성 +어떤 클래스가 다른 클래스에 접근할 수 있는 경로가 있거나(=참조 변수?),
+해당 클래스의 메서드를 호출할 경우, 둘 사이에 의존성이 있다고 말함. + +Movie 클래스의 경우, DiscountPolicy에 의존함.
+얘는 구체적인 구현이 아니고 추상적인 개념임 + +그런데 실제 생성자를 호출할 때 구체적인 구현체를 넣어줌 + +즉, 코드에서의 의존성 실제 실행 시의 의존성은 다를 수 있다.
+다른 말로, 컴파일 시간의 의존성과 런타임의 의존성을 다를 수 있다. + +이것이 바로 유연성, 재사용성의 근원. + +그러나 설계가 유연해질 수록, 코드를 이해하긴 어렵다.
+실제로는 누구와 의존하는 지 가봐야 아니까;; + +## 의존성이 어떻게 바뀔 수 있는건데? +상속을 통해 다형성을 구현했기 때문 + +상속은 코드 재사용의 의미도 있지만, 인터페이스의 승계라는 의미도 있음.
+인터페이스란 객체가 이해할 수 있는 메시지의 모음이고, 타입의 근원이다. + +자식 객체는 부모와 이해할 수 있는 인터페이스가 같거나 더 많기 때문에,
+자식 클래스는 부모 클래스와 같은 타입으로 불 수 있음.(=업캐스팅) + +Movie 입장에서는 누가 대답하던 알바 아님. 그냥 이 메시지를 이해하고 응답할 대상이 필요할 뿐 + +다형성 = 하나의 메시지에 대해 다르게 대답할 수 있는 능력 + +컴파일 시간이 아닌 런타임에 "메시지에 대한 응답 메서드"를 결정함으로써 가능(=동적 바인딩) + +다형성 구현을 위해서는 상속 뿐 아니라 인터페이스도 있음.
+인터페이스는 공유할 구현이 하나도 없을 때 쓰는 것 + +## 추상화와 유연성 +추상화의 장점 +1. 요구사항은 높은 수준에서 서술 가능(=인지 과부하 줄임) +2. 설계가 유연해짐 + +추상화를 이용해 요구사항을 기술한다는 것 = 애플리케이션의 협력흐름을 기술한다는 것
+이 협력 흐름을 재사용될 수 있다. 그 예시가 바로 디자인 패턴이나 프레임워크 + +추상화를 중심으로 설계하면, 유연하고 확장 가능해짐. 잘 변하는, 구체적인 것에 의존하지 않기 때문 + +협력 흐름을 추상화한다는 관점에서, 예외 상황을 만드는 것은 좋은 방식이 아님. 협력 흐름이 깨지는 상황이 생기는 거니까~ + +컨텍스트 독립성 <- 이게 먼 뜻임? + +## NoneDiscountPolicy에서 추상클래스 방식 vs 인터페이스 방식 +할인 정책이 존재할 때의 흐름과 없을 때의 흐름이 아예 다름 + +이걸 기존의 추상 클래스 방식으로 다룰 거냐, 아니면 인터페이스를 위에 하나 더 둘 거냐의 차이 + +이처럼 설계에는 여러 방법이 있고, 트레이드 오프가 있다.
+이 트레이드 오프를 고려한다는 것은 곧 모든 코드에는 이유가 있다는 것(거기에 있는) + +## 상속 vs 합성 +상속은 +1. 캡슐화를 위반 + 부모의 구현을 다 알아야 함. + 부모가 바뀌면 자식도 다 바뀌어야 함. +2. 설계의 유연성을 떨어뜨림 + 컴파일 타임에 부모-자식 관계를 지정함. + 자식 A와 자식 B를 서로 갈아끼기 힘듦. + +합성은 이 두 가지 문제를 해결함. + +뭐 상속을 아예 쓰지 말라는 건 아니긴 함 -> 상속은 다형성 구현할 때도 쓰이기 때문 -> 근데 꼭 상속만 다형성 구현에 쓰이는 건 또 아님
+??? 어쩌래는겨 + + + diff --git "a/\354\235\264\355\230\204\355\235\254/Chapter3.md" "b/\354\235\264\355\230\204\355\235\254/Chapter3.md" new file mode 100644 index 0000000..783fae3 --- /dev/null +++ "b/\354\235\264\355\230\204\355\235\254/Chapter3.md" @@ -0,0 +1,89 @@ +# 객체지향의 본질 +2장 내용은 구현에 치우친 설명이었음 + +객체지향의 본질은 책임, 협력, 역할임. + +객체지향 애플리케이션의 제어 흐름은 어느 한 객체에 의해 통제되는 것이 아니고
+여러 객체에 균형있게 나눠져 있음.
+객체들은 자신에게 배정된 로직을 실행함. + +책임 : 객체가 협력에 참여하기 위해 실행하는 로직 +협력 : 객체들이 기능 구현을 위해 상호작용 하는 것 +역할 : 객체가 수행하는 책임이 모인 것 + +# 협력 +협력(=객체 간의 상호작용)은 메시지를 통해서만 일어남
+수신 받은 메시지에 대한 처리 방법(=메서드)는 수신받은 객체가 자율적으로 결정함. + +내부 구현을 캡슐화(=자율적인 객체) 해 놓아야 일부 책임(=로직)을 위임할 수 있음. + +객체의 존재 이유 = 협력에 참여하기 때문
+객체가 협력에 참여 가능한 이유 = 협력에 적절한 행동을 보유하고 있기 때문 + +협력이 객체의 행동을 결정한다
+협력이 바뀌면 객체의 행동도 변해야 한다. + +eg. Movie라는 객체는 어떤 행동을 해야할까?
+일반적인 생각으로는 play 같은 행동이 있겠지만, 티켓 예매라는 협력 속에서는, 가격 계산이라는 행동이 있음. + +협력은 행동을 정하고, 행동과 상태는 서로를 정한다(협력이 상태를 바꾸고 상태에 기반해 행동하고 반복) + +# 책임 +객체가 협력을 위해 수행하는 행동임 + +책임은 하는 것과 아는 것으로 구분됨. + +책임이 메시지와 내부 속성(=상태)을 정함. + +책임이 메시지보다 크므로, 여러 개의 메시지로 쪼개지게 됨. + +아는 것과 하는 것은 밀접하게 관련되어 있음
+이것은 객체에게 책임을 할당하는 가장 기본적인 힌트를 제공함
+뒤에 나오지만, 이 장에서 간략하게 언급하는 건 Information Expert 패턴 + +시스템의 기능을 시스템의 책임으로 보고,
+이 책임을 수행하기 위해 작은 책임들로 쪼개고, 객체들에게 할당.
+다시 또 그 책임을 쪼갠 뒤 객체들에게 할당하는 것을 반복 + +메시지가 객체를 선택하는 것.
+물론 객체도 이미 어느정도 개념은 있음(도메인 모델에서 가져온다던가)
+여기서 말하는 건 객체를 보고 어떤 메시지가 어울릴까 고민하는 게 아니고,
+협력을 위한 책임을 통해 메시지를 만들고, 이 메시지를 어느 객체에 할당할 지 선택하는 게 좋다는 것.
+=> 이러면 메시지부터 떠올리기 때문에 "무엇을"에 집중할 수 있고, 협력에 필요한 메시지만 생각하기 떄문 "최소개수"도 만족 가능 + +객체는 자신이 수행할 수 있는 행동을 통해 자신의 존재 의미를 가짐
+객체의 쓸모, 존재 이유, 품질 모두 그 행동(=책임)을 얼마나 잘 정의헀냐로 결정됨 + +# 역할 +간단하게 말하자면 책임의 집함. + +협력을 모델링하는 책임주도설계 과정에서 특정 책임을 어떤 객체에게 맡긴다고 생각하는 게 아니라
+어떤 역할에 맡긴다고 생각하는 것이 더 좋다.
+나중에 그 역할에 해당하는 객체가 하나인 걸로 결정되면, 그때 객체라고 해도 됨. + +역할은 "재사용 가능한" 협력을 만들 수 있게 해준다.
+역할은 책임의 집합이고, 어떠한 객체든지 그 책임의 집합을 감당할 수 있다면 그 역할을 수행할 수 있다.
+역할을 구현하는 방법 = 상속, 인터페이스 + +협력은 역할의 상호작용이라고도 볼 수 있음
+협력 -> 역할 -> 객체 -> 클래스 + +도메인 모델은 사람이 세상을 바라보는 모델임
+그래서 근본적으로 불안함.
+그래서 협력 속에서 상호작용하는 그 대상들이 객체인지, 클래스인지, 역할인지 초기엔 분간하기 어렵고 나중에 바뀔 수도 있음
+따라서 그냥 그 대상을 "후보(Candidate)"라는 개념으로 바라보는 것이 좋음. + +특정 시나리오에 대한 협력을 구성할 때
+보통 도메인 모델의 개념들을 "후보"로 선택해 책임을 할당하게 되는데
+이때 비슷한 구조의 협력이 보일 수 있음.
+그럼 이제 역할을 통한 협력의 추상화 삽가능 + +다양한 객체가 협력할 게 확실하다면 역할로 딱 정하고 시작해도 되고
+그게 어려우면 후보라고 뭉뚱그려 표현해도 되고
+협력 자체가 어떤 상호작용인지 판단하기 어렵다면 구체적인 객체(일종의 예시로서)를 통해서 생각해도 됨 + +역할은 객체의 추상화라고 볼 수 있고,
+그래서 2장에 나온 추상화의 장점 2가지가 적용됨
+1. 추상적인 수준에서의 기술 가능(협력을) +2. 유연함(다양한 객체가 참여할 수 있으므로, 협력이 유연해짐) +역할은 협력 내에서만 임시적으로 존재하며, 배우와 배역의 예제를 봤을 때 페르소나라고도 볼 수 있다. \ No newline at end of file