# 04장 설계 품질과 트레이드 오프

조영호 저 "오브젝트: 코드로 이해하는 객체지향 설계, 2019"를 읽고 정리한 내용입니다.

객체지향 설계의 핵심은 역할,책임,협력

가장중요한 것은 책임

객체지향 설계 = 낮은 결합도 + 높은 응집도 + 적절한 책임 할당

결합도와 응집도를 합리적인 수준으로 유지할 수 있는 중요한 원칙 = 객체의 상태가 아니라 객체 의 행동에 초점을 맞추는 것

"이번 장에서는 영화 예매 시스템을 책임이 아닌 상태를 표현하는 데이터 중심의 설계를 살펴보고 객체 지향적으로 설계한 구조와 어떤 차이점이 있는지 살펴보겠다."

4.1 데이터 중심의 영화 예매 시스템

  • 객체 분할의 중심축 (상태=데이터 or 책임)

    • 저자는 책임에 초점을 둠

    • 상태에 초점을 맞출경우 캡슐화 원칙 위배 -> 인터페이스의 변경을 초래 -> 모든 객체에 영향 변경에 취약

    • 반면 객체의 책임은 인터페이스 -> 상태 캡슐화 -> 변경에 의한 외부파장 방지 안정적인 변경 가능

★ 2장이 책임에 초점을 맞춘 설계라면 4장에서는 상태(데이터)를 중심으로 설계하여 비교분석이 용이함

4.2 설계 트레이드오프

  • 캡슐화

    • 변경될 가능성이 높은 부분 = 구현, 상대적으로 안정적인 부분 = 인터페이스

  • 응집도와 결합도

    • 응집도 : 모듈에 포함된 내부 요소들이 연곤돼 있는 정도

      • 변경의 관점에서 응집도란 변경이 발생할 때 모듈 내부에서 발생하는 변경의 정도

111p

결합도 : 의존성의 정도

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

111p

4.3 데이터 중심의 영화 예매 시스템의 문제점

  • 캡슐화 위반

    • 접근자와 수정자에 과도하게 의존하는 설계방식인 추측에 의한 설계 전략(design-by-guessing strategy)

    • getter와 setter는 무조건 필요한가?

  • 높은 결합도

115p
  • 낮은 응집도

    • 두가지 설계의 문제 초래

      • 변경하는 코드가 아무상관 없는 코드들에 영향을 미침 (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