-
[책너두 4기] 개발 서적 스터디 - 오브젝트 chapter 3 ~ 5장 요약독서/오브젝트 2023. 7. 10. 10:35
[7일차]
Chapter 3. 역할, 책임, 협력 (1)
- 객체지향 핵심은 역할, 책임, 협력이다.
- 클래스도 상속도 구현하는 방식일 뿐 더 중요한 것은 협력, 책임, 역할이다.
협력
- 어떤 객체가 다른 객체에게 무엇인가 요청하는 것
- 협력은 객체를 설계하는데 문맥을 제공한다.
- ex) Movie를 일반적으로 생각했을때 영화 play, 극장안에 사람들을 상상한다. 하지만 예제에서는 Movie가 입장시 가격 계산을 수행한다 왜 일까?
- “영화 예매하기 위한 협력”하기 위해 생성한 객체이기 때문이다.
- 협력이 객체의 행동을 결정한다.
- 행동에 필요한 값이 객체의 상태를 결정한다.
- 객체란? 상태와 행동을 캡슐화 한 실행 단위
Chapter 3. 역할, 책임, 협력(2)
책임
- 객체지향에서 가장 중요한 것은 책임.
- 협력이 중요한 이유도 책임을 결정한 맥락을 제공하기 때문.
- 책임이란? 객체가 유지해야하는 정보(아는 것), 수행할 수 있는 행동(하는 것)을 개략적으로 서술한 문장
[예제 - 아는 것 , 하는 것]
- Screening
- 상여 정보 안다.
- 예매 정보 생성한다.
- Movie
- 영화 정보 안다.
- 가격을 계산한다.
- DiscountPolicy
- 할인 정책을 안다.
- 할인된 가격을 계산
- DiscountCondition
- 할인 조건을 알고 있다.
- 할인 여부를 판단한다.
책임 할당
- 정보 전문가에게 책임을 할당한다.
- 사용자에게 제공하는 기능을 하나의 책임으로 인식 → 더 작은 책임 인식 → 객체에 할당으로 책임 할당이 이루어진다.
- ex) 이렇게 책임 할당 (설계)가 이뤄진다.
- 예매하는 기능 (예매는 상영시간, 요금을 알아야한다.)
- 예매해라 → Screening → 계산해라 → Movie
- 예매하는 기능 (예매는 상영시간, 요금을 알아야한다.)
- 메시지가 퍼블릭 인터페이스를 결정한다.
책임 주도 설계
- 위 처럼 책임을 찾고, 책임 수행 객체를 찾아가는 방식을 책임 주도 설계 (RDD)라 한다.
메시지가 객체를 결정한다.
- 메시지가 책임 할당할 객체를 선택해야한다.
- 객체가 최소한의 인터페이스를 가질 수 있게 된다.
- 추상적인 인터페이스를 가질 수 있다.
행동이 상태를 결정한다.
- 객체의 상태 보다 행동이 더 중요하다.
- 객체의 존재 이유 == 협력에 참여이다. 객체에 협력에 필요한 행동을 정의해야한다.
- 상태 위주로 설계하면 내부구현이 인터페이스에 노출해 캡슐화가 깨진다.
- 객체에 의존하는 클라이언트 변경이 발생한다.
- 이렇게 내부 구현에 초점을 맞춘 설계 방식을 DDD라 한다.
역할
- 객체가 어떤 목적을 수행하는 책임의 집합
- 협력 모델링 시 책임은 개체가 아니라 역할에 할당한다.
- 역할이 없어도 협력을 설계할 수 있는데 왜 필요할까?
유연하고 재사용 가능한 협력
- 역할을 통해 유연한고, 재사용 가능한 협력을 얻을 수 있다.
- 역할은 다른 것으로 교체할 수 있는 책임의 집합
- 계산하라 메시지를 수행하는 AmountDiscountPolicy, PercentDiscountPolicy 두개 객체에 각각 책임을 할당 하는게 아니라 두개를 슬록처럼 교체할 수 있는 역할에 할당한다.
- 동일한 책임을 추상화 한 것을 역할
- 역할을 구현하는 가장 일반적인 방법 == 추상 클래스, 인터페이스 집합
객체 대 역할
- 책임의 대상이 하나면 역할이 필요할까? 복잡도를 늘리는 것은 아닐까?
- (저자 견해) 역할과 객체를 명확히 구분하는 일은 설계 초반에 중요하지 않다.
- 단순하게 객체로 시작해서 역할, 책임을 정제하면서 설계를 진행하자.
- 결국 중요한 것은 책임이다.
[8일차]
Chapter 3. 역할, 책임, 협력 (3)
역할과 추상화
- 역할을 객체의 추상화로 볼 수 있다.
- 추상화의 2가지 장점을 가진다.
- 세부사항을 무시하고 상위 수준으로 추상화 == 큰 그림 파악에 용이
- 설계를 유연하게 만들 수 있다.
배우와 배역
- 역할은 객체의 페르소나이다.
- 하나의 객체가 시스템 문맥안에서 다양한 역할을 가질 수 있다.
- 어떤 협력에 참여하는지에 따라 다른 역할을 가진다.
- 다시 강조. 중요한 것은 책임이다.
Chapter 4. 설계 품질과 트레이드 오프 (1)
- 객체지향 설계란 올바른 객체에게 올바른 책임을 할당하면서 낮은 결합도, 높은 응집도를 가진 구조를 창조하는 활동이다.
- 이번 장에서는 나쁜 설계를 예로 통찰을 얻어본다.
데이터 중심의 영화 예매 시스템 (나쁜 예)
- 내부 저장해야하는 데이터부터 설계한다.
- 객체의 종류를 구분하는 type 변수를 Enum으로 변수로 저장한다.
- 인스턴스 종류에 따라 상용될 인스턴스 변수를 저장한다.
- 수정자, 접근자 추가
- 예매 구현할때의 복잡도를 확인 (switch문, if 문 분기처리가 증가)
[9일차]
chapter.4 설계 품질과 트레이드 오프 (2)
설계 트레이드 오프
- 데이터 중심 설계와 책임 중심 설계의 장단점
- 설계 품질의 척도
- 캡슐화
- 응집도
- 결합도
- 캡슐화
- 캡슐화란 변경 가능성이 높은 부분을 객체 내부로 숨기는 추상화 기법
- 변경의 관점에서 설계 품질 판단의 기준이 된다.
- 응집도
- 응집도란 모듈에 내부 요소들이 연관돼 있는 정도
- 설계의 변경을 쉽게 만든다.
- 하나의 목적을 위해 요소들이 긴밀히 협력하면 응집도가 높은 것
- 변경의 관점에서 변경이 발생했을때 모듈 내부 변경이 발생하는 변경 정도를 판단 할 수 있다.
- 결합도
- 한 모듈이 변경되기 위해서 다른 모듈의 변경을 요구해야하는 정도
- 캡슐화와 응집도 결합도는 서로 연관있다.
- 캡슐화를 잘하면 응집도는 올라가고 결합도는 낮아진다.
데이터 중심의 영화 예매 시스탬의 문제점
- 3가지 설계 척도로 설계 평가
- 문제점
- 캡슐화 위반 → Getter, Setter에 과도하게 의존한 설계
- 높은 결합도 → getFree의 리턴 타입 하나면 변경해도 3곳을 변경. 추가 기능르로 제어 로직이 추가라도 된다면 변경하기 힘든 구조로 발전
- 낮은 응집도 → 할인정책이나 할인조건을 조금만 변경하려해도 관계 없는 함수들에 코드가 추가된다.
- 응집도를 높이기 위해서는 단일 책임 원칙을 따라야한다.
[10일차]
chapter.4 설계 품질과 트레이드 오프 (3)
스스로 자신의 데이터를 책임지는 객체
- 데이터 중심 예제를 캡슐화 진행
- 상태와 행동을 하나의 단위로 묶는다.
- 이 객체가 어떤 데이터를 포함해야하는가? 질문을 2개로 나눈다.
- 어떤 데이터를 포함?
- 데이터가 수행해야하는 오퍼레이션은?
- 실습 코드 https://github.com/sendkite/oop
- 설계가 개선되었다. 결합도가 낮아졌다.
개선해도 여전한 문제
- 캡슐화 위반
- 데이터와 행동으로 객체를 정의했다 한들, 메서드 이름, 파라미터 타입이 외부에 노출되고 있다.
- 외부 노출로 인해서 파급효과가 발생한다.
- 결합도가 높다고 표현할 수 있다.
- 응집도가 낮다.
- 캡슐화란 변할 수 있는 것 어떤 것이라도 감추는 것이다.
- 내부속성을 감추는 것은 데이터 캡슐화로 캡슐화의 한가지 종류일 뿐
유연한 설계를 창조하기 위해서는 캡슐화를 설계의 첫 목표로 삼아야한다.
[11일차]
chapter.4 설계 품질과 트레이드 오프 (4)
데이터 중심 설계의 문제점
- 데이터 중심의 설계는 본질적으로 너무 이른 시기에 데이터에 관해 결정하도록 강요한다.
- 협력이라는 문맥을 고려하지 않고 오퍼레이션을 작성한다.
- 너무 이른 데이터 결정은 캡슐화에 실패하게 한다.
- 이미 구현된 객체의 인터페이스를 맞추게 된다. 파급효과가 발생한다.
Chapter.5 책임 할당하기 (1)
- 데이터 중심 설계의 문제점을 해결하는 방법은 책임에 초점을 맞추는 것
- 책임 할당 과정은 트레이드 오프 과정, 정답이 없다.
- 올바른 책임 할당을 위해서는 다양한 관점에서 설계를 평가할 수 있어야한다.
- 책임 할당의 기본 원리를 살펴보자.
5-1. 책임주도 설계를 향해
책임주도 설계 하는 법
- 데이터보다 행동 먼저 결정
- 객체가 수행해야하는 책임을 결정 → 책임에 필요한 데이터 결정
- 협력이라는 문맥 안에서 책입 결정
- 클라이언트의 의도에 맞는 메시지 먼저 결정 후 책임 할당
- 메시지는 클라이언트의 의도를 드러낸다.
- 메시지가 객체를 선택하도록 한다.
- 객체에 메시지를 처리할 책임을 할당한다.
- 협력이라는 문맥 안에서 객체가 수행할 책임에 초점을 둔다.
책임 주도 설계
[책임 주도 설계의 흐름]
- 시스템 전체의 책임 파악
- 시스템 책임을 작게 분할
- 분할된 책임을 적절한 객체에게 할당
- 책임 수행 도중 다른 객체 도움이 필요하면 객체 또는 역할을 찾는다.
- 객체 또는 역할에게 책임 할당하여 협력하게 한다.
5-2. 책임 할당을 위한 GRASP 패턴
- General Responsibility Assignment Software Pattern (크레이그 라만)
도메인 개념에서 출발하기
- 어떤 책임 할당 고민 시 가장 먼저 고민 유력후보는 도메인이다.
- 올바른 도메인 모델은 존재하지 않는다.
- 도메인은 구현시 참고할 유용한 개념 모음
- 도메인 예시
- 영화예매 도메인 (영화, 예매, 상영, 할인 금액, 할인 정책, 할인 조건…)
정보 전문가에게 책임을 할당하라
- 애플리케이션이 제공해야하는 기능이 애플리케이션의 책임
- 영화 예매 기능이 책임으로 간주한다면 예매하라 메시지를 정의
- 메시지를 전송할 객체, 메시지를 수신할 객체가 각각 무엇을 원하는지 생각한다.
- 책임을 수행할 정보를 알고 있는 전문가 객체를 수신 객체로 정한다,
- 정보 전문가가 반드시 정보를 저장하고 있을 필요는 없다.
- 정보 전문가에게 책임 할당 패턴만 따라도 자율성 높은 협력 구축 가능성이 높아진다.
[12일차]
Chapter.5 책임 할당하기 (2)
- GRASP 패턴을 더 살펴본다.
높은 응집도와 낮은 결합도
- 여러 설계 선택에서 낮은 결합도, 높은 응집도를 가져가는 선택을 해라
- LOW Coupling 패턴
- HIGH Cohesion 패턴
창조자에 객체 생성을 할당하라
- CREATOR 패턴
- 영화 예매 시스템의 최종 결과물은 Reservation 인스턴스이다.
- 어떤 객체가 생성하는 것이 좋을까?
- 아래 조건을 최대 만족하는 객체에게 생성을 할당하라.
- 생성할 객체를 포함하거나 참조한다.
- 생성할 객체를 기록한다.
- 생성할 객체를 긴밀하게 사용한다.
- 생성할 객체를 초기화하는데 필요한 데이터를 가지고 있다.
구현을 통한 검증
- 생성자 패턴 적용
- https://github.com/sendkite/oop
DiscountCondition 개선하기
- 변경의 이유에 따라 클래스를 분리해야한다.
- 예제 DiscountCondition은 1개 이상의 변경 이유를 가지기 때문에 응집도가 낮다.
- 새로운 할인 조건 추가
- 순번 조건 요구사항 변경
- 기간 조건 요구사항 변경
- 변경 이유 1개 이상인지 판단하는 방법
- 인스턴스 초기화되는 시점을 살펴본다.
- 응집도가 높은 클래스는 인스턴스 생성시 모든 속성을 초기화 한다.
- 초기화 속성 그룹 기준으로 코드를 분리한다 ⇒ DiscountContion을 PeriodCondition, SequenceCondition으로 분리
- 메서드들이 인스턴스 변수를 사용하는 방식을 살펴본다.
- 모든 메서드가 객체의 모든 속성을 사용하면 응집도가 높다.
- 속성 그룹과 메서드 그룹을 기준으로 코드를 분리한다. ⇒ DiscountContion을 PeriodCondition, SequenceCondition으로 분리
- 인스턴스 초기화되는 시점을 살펴본다.
반응형'독서 > 오브젝트' 카테고리의 다른 글
[책너두 4기] 개발 서적 스터디 - 오브젝트 chapter 5 ~ 7장 요약 (1) 2023.07.16 [책너두 4기] 개발 서적 스터디 - 오브젝트 chapter 1 ~ 2장 요약 (0) 2023.07.01