티켓판매 어플리케이션
- Theater의 enter 메서드를 이해하기 위해서 Audience 가 Bag 을 가지고 있고, Bag 안에는 현금과 티켓이 들어 있으며 TicketSeller 가 TicketOffice 에서 티켓을 판매하고, TicketOffice 안에 돈과 티켓이 보관돼 있다는 모든 사실을 동시에 기억하고 있어야 한다. (모든 책임이 Theater 에 몰려 있다)
하나의 클래스나 메서드에서 너무 많은 세부사항을 다루기 때문에 코드를 작성하는 사람뿐만 아니라 코드를 읽고 이해해야 하는 사람 모두에게 큰 부담을 지운다.
이런 코드를 변경에 취약한 코드라 볼 수 있다. 예상치 못한 변수에 대응하기 어려운 코드이다.
- 객체 사이의 의존성과 관련된 문제로 정의할 수 있다. (의존성은 변경에 대한 영향을 의미한다)
- 최소한의 의존성만 유지하고 불필요한 의존성을 제거해야 한다.
- 객체 내부의 상태를 캡슐화하고 객체 간에 메세지를 통해서만 상호작용하도록 한다.
결합도(Coupling)을 낮추고 변경에 용이한 설계로 변경한다.
밀접하게 연관된 작업만 수행하고 연관성 없는 작업은 다른 객체에게 위임하여 응집도를 높인다.
- 요구하는 기능을 온전히 수행하면서 내일의 변경을 수용할 수 있는 설계다.
- 협력하는 개체 사이의 의존성을 적절하게 관리하는 설계이다.
- 코드를 수정하겠다는 마음이 들 수 있는 이해하기 쉬운 변경 가능한 코드를 작성해야 한다.
영화 예매 시스템
- 특정 조건을 만족하는 경우(순서 조건, 기간 조건, 순서 + 기간 조건), 그에 맞는 할인정책(금액 할인, 비율 할인)을 수행하는 어플리케이션 설계
- 영화별로 하나의 할인 정책만 할당할 수 있다
- 사용자가 예매를 완료하면 시스템은 예매 정보를 생성한다
어떤 객체들이 필요한가 고민한다
객체를 독립적인 존재가 아닌 협력에 필요한 존재로 인식한다
도메인
객체를 통해 의미를 풍부하게 표현할 수 있는 수단으로 전체적인 설계의 명확성과 유연성을 높인다
Movie : 영화에 대한 기본 정보
Screeinging : 실제로 관람객이 영화를 관람하는 사건을 표현하는 상영이라는 개념
DiscountPolicy : 할인 정책
AmountDiscountPolicy : 금액 할인 정책
PercentDiscountPolicy : 비율 할인 정책
DiscountCondition : 할인 조건
SequenceCondition : 순서 할인 조건
PeriodCondition : 기간 할인 조건
Reservation : 예매 정보
- 접근제어 매커니즘을 통해 클래스의 내부와 외부를 구분함으로써 객체의 자율성을 보장하고, 프로그래머에게 구현의 자유를 제공한다
인터페이스와 구현의 분리
객체 내부에 대한 접근을 통제하여 외부의 간섭을 최소화함으로써 객체가 스스로 행동하는 자율적인 존재로 만든다
프로그래머의 자유
변경 가능성이 있는 내용을 내부에 감춤으로서 구현의 자율성이 증가하고 변경으로 인한 혼란을 줄인다
협력
객체는 인터페이스로 공개된 시그니처를 통해 서로 요청하고 응답하며 협력한다.
- 객체 지향 설계가 가지는 특징은 코드의 의존성과 실행시점의 의존성이 다르다는 것
다형성
동일한 메시지를 수신했을 때 객체의 타입에 따라 다르게 응답할 수 있다는 것을 말한다
구현 상속과 인터페이스 상속 등 다형성을 구현하는 방식은 다양하다
코드 의존성과 실행 시점의 의존성이 다르다는 사실을 기반으로 서로 다른 메서드를 실행할 수 있게 한다
컴파일 시간 의존성은 인터페이스나 상위 객체로 향할 수 있지만 실행 시간 의존성은 구체 구현 객체로 향한다
상속의 단점
자식 클래스가 부모 클래스의 내부 구조, 구현을 알수 밖에 없기 때문에 캡슐화를 위반한다
캡슐화의 약화를 통해 부모 자식 클래스 간의 강결합이 형성되기 때문에 변경하기 어려운 코드가 된다
상속은 부모 클래스와 자식 클래스의 의존성을 컴파일 시점에 결정하여 실행 시점에 객체 종류를 변경할 수 없다
인터페이스의 사용
인터페이스와 구현객체의 의존성이 약하다
인터페이스를 통해 제공 기능을 전달받을 수 있지만 내부 구현은 알지 못한다
설계는 트레이드오프의 산물, 의존성의 양면성
코드 의존성과 실행시점의 의존성이 다르면 다를수록 코드는 더 유연해지고 확장 가능해지지만, 객체를 생성하고 연결하는 부분을 찾아야 하기 때문에 코드를 이해하기 어려워진다
추상화의 장점
상위 개념만으로 도메인의 중요 개념을 쉽고 간단하게 표현할 수 있다
애플리케이션의 협력 흐름을 쉽게 파악할 수 있다
추상화를 통한 상위 정책을 기술함으로써 자식 객체들을 추가할때 상위 개념의 협력 흐름을 따르게 되며 새로운 기능을 쉽게 추가 확장 할 수 있는 유연한 설계가 된다
- 애플리케이션의 기능을 구현하기 위해 협력에 참여하는 객체들 사이의 상호작용에 초점을 맞추는 것
- 협력에 참여하는 객체들의 역할과 책임을 수행하도록 한다
- 클래스와 상속과 같은 개념은 객체지향적인 설계를 위한 도구이다