# 04장 설계 품질과 트레이드 오프
조영호 저 "오브젝트: 코드로 이해하는 객체지향 설계, 2019"를 읽고 정리한 내용입니다.
객체지향 설계의 핵심은 역할,책임,협력
가장중요한 것은 책임
객체지향 설계 = 낮은 결합도 + 높은 응집도 + 적절한 책임 할당
결합도와 응집도를 합리적인 수준으로 유지할 수 있는 중요한 원칙 = 객체의 상태가 아니라 객체 의 행동에 초점을 맞추는 것
"이번 장에서는 영화 예매 시스템을 책임이 아닌 상태를 표현하는 데이터 중심의 설계를 살펴보고 객체 지향적으로 설계한 구조와 어떤 차이점이 있는지 살펴보겠다."
4.1 데이터 중심의 영화 예매 시스템
객체 분할의 중심축 (상태=데이터 or 책임)
저자는 책임에 초점을 둠
상태에 초점을 맞출경우 캡슐화 원칙 위배 -> 인터페이스의 변경을 초래 -> 모든 객체에 영향 변경에 취약
반면 객체의 책임은 인터페이스 -> 상태 캡슐화 -> 변경에 의한 외부파장 방지 안정적인 변경 가능
★ 2장이 책임에 초점을 맞춘 설계라면 4장에서는 상태(데이터)를 중심으로 설계하여 비교분석이 용이함

4.2 설계 트레이드오프
캡슐화
변경될 가능성이 높은 부분 = 구현, 상대적으로 안정적인 부분 = 인터페이스
응집도와 결합도
응집도 : 모듈에 포함된 내부 요소들이 연곤돼 있는 정도
변경의 관점에서 응집도란 변경이 발생할 때 모듈 내부에서 발생하는 변경의 정도

결합도 : 의존성의 정도
변경의 관점에서 결합도란 한 모듈이 변경되기 위해서 다른 모듈의 변경을 요구하는 정도

4.3 데이터 중심의 영화 예매 시스템의 문제점
캡슐화 위반
접근자와 수정자에 과도하게 의존하는 설계방식인 추측에 의한 설계 전략(design-by-guessing strategy)
getter와 setter는 무조건 필요한가?
높은 결합도

낮은 응집도
두가지 설계의 문제 초래
변경하는 코드가 아무상관 없는 코드들에 영향을 미침 (ex. ReservationAgency 할인정책)
하나의 요구사항 변경을 반영하기 위해 동시에 여러 모듈 수정(ex. 할인정책 추가시 MovieType, ReservationAgency, Movie 클래스 변경)
4.4 자율적인 객체를 향해
반드시 getter와 setter 통해 다른 클래스에서 맴버변수에 접근 및 수정을 허용하는것 보다 책임전가를 함으로서 스스로 자신의 데이터를 책임지게 하라
스스로 자신의 데이터를 책임지는 객체
이 객체가 어떤 데이터를 포함해야 하는가? + 이 객체가 데이터에 대해 수행해야 하는 오퍼레이션은 무엇인가? = 새로운 데이터 타입 생성
DiscountCondition 클래스에 자신의 데이터인 할인조건에 대해 스스로에게 할인가능 여부를 판단할 수 있게끔 책임전가
Movie 클래스에 자신의 데이터인 할인조건 목록에 대해 스스로 할인가능 여부를 판단할 수 있게끔 책임전가
Screening 클래스에 자신의 예매요금을 Movie 클래스의 메소드를 빌려 스스로 계산할 수 있게끔 책임전가
ReservationAgency 클래스에 예매요금을 Screening 클래스의 메소드를 빌려 스스로 계산하고 Reservation을 생성할 수 있게끔 책임전가

4.5 하지만 여전히 부족하다
캡슐화는 향상되었지만 여전히 만족스럽지는 않고 캡슐화 위반이 여전히 남아있음
캡슐화 위반
DiscountCondition의 isDiscountable 메소드의 파라미터를 통해 객체 내부의 인스턴스 변수들의 타입을 알 수 있음
Movie의 메소드들은 파라미터가 없어 괜찮아 보이지만, 금액 할인 정책, 비율 할인 정책, 미적용의 세가지 할인정책이 존재한다는 것을 메소드의 이름을통해 공개함
높은 결합도
캡슐화 위반 -> 내부 구현 노출 -> 결합도 상승 (Moive & DiscountCondition)
DiscountCondtion의 기간 할인 조건 명칭이 PERIOD에서 다른 값으로 변경된다면 Movie를 수정해야 한다
DiscountCondtion의 종류가 추가 및 삭제된다면 Moive안의 if ~ else 구문을 수정해야 한다
★ 모든 문제는 캡슐화를 지키지 않았기 때문이다!
낮은 응집도
DiscountCondition이 할인 여부를 판단하는데 필요한 정보 변경 -> Movie의 isDiscountable 메소드의 파라미터 변경 -> Screening 클래스에서 Movie의 isDiscountable 메소드를 호출하는 부분도 변경필요 -> 응집도가 낮다
★ 모든 문제는 캡슐화를 지키지 않았기 때문이다!
4.6 데이터 중심 설계의 문제점
변경에 취약한 이유
이른 시기에 데이터에 관해 결정하도록 강요
접근자와 수정자를 과도하게 추가 -> 분리된 별도의 객체 안에서 사용함으로서 구현 -> 캡슐화 위반 (첫번째 설계가 실패한 이유)
데이터를 먼저 결정하고 데이터를 처리하는데 필요한 오퍼레이션을 나중에 결정하는 방식은 데이터에 관한 지식이 객체의 인터페이스에 고스란히 드러남 -> 객체의 인터페이스는 구현을 캡슐화하는 데 실패하고 코드는 변경에 취약 (두번째 설계가 실패한 이유)
결론적으로 데이터 중심의 설계는 너무 이른 시기에 데이터에 대해 고민하기 때문에 캡슐화에 실패하고 변경에 취약한 코드를 낳음
협력을 고려하지 않고 객체를 고립시킨 채 오퍼레이션 결정
설계의 초점은 객체의 외부가 아니라 내부 -> 데이터의 세부 정보부터 결정 -> 추후 인터페이스를 억지로 끼워맞춤 -> 객체의 인터페이스에 구현이 노출 -> 협력이 구현 세부사항에 종속 -> 내부변경 할 때 협력하는 모든 객체가 영향을 받음 (두번째 설계가 실패한 이유)
Last updated