BookReview/오브젝트
04_설계 품질과 트레이드 오프
Fkaa
2023. 1. 9. 01:23
[오브젝트 - 코드로 이해하는 객체지향 설계] 의 4번째 챕터 [설계 품질과 트레이드 오프]에 대한 파트이다.
이번 챕터에서는 영화 예매 시스템을 책임이 아닌 상태를 표현하는 데이터 중심의 설계로 살펴보고, 객체지향으로 설계한 구조와 어떤 차이점이 있는지를 살펴보고자 한다.
00_들어가기
- 책임 주도 설계
- 역할, 책임, 협력 중에서 가장 중요한 것은 책임
- 책임이 객체지향 애플리케이션 전체의 품질을 결정
- 객체지향 설계
- 올바른 객체에게 올바른 책임을 할당하면서 낮은 결합도와 높은 응집도를 가진 구조를 창조하는 활동
- 객체지향 설계에 관한 두 가지 관점
- 객체지향 설계의 핵심은 책임
- 책임을 할당하는 작업이 응집도와 결합도 같은 설계 품질과 깊이 연관돼 있다.
- 책임은 객체의 상태에서 행동으로, 나아가 객체와 객체 사이의 상호작용으로 설계 중심을 이동시키고, 결합도가 낮고 응집도가 높으며 구현을 효과적으로 캡슐화 하는 객체들을 창조할 수 있는 기반을 제공한다.
01_데이터 중심의 영화 예매 시스템
- 객체지향 설계에서는 두 가지 방법을 이용해 시스템을 객체로 분할할 수 있다.
- 상태를 분할의 중심축으로 삼는 방법
- 객체는 자신이 포함하고 있는 데이터를 조작하는데 필요한 오퍼레이션을 정의
- 객체의 상태에 초점
- 객체 = 독립된 데이터 덩어리
- 책임을 분할의 중심축으로 삼는 방법
- 객체는 다른 객체가 요청할 수 있는 오퍼레이션을 위한 필요한 상태를 보관
- 객체의 행동에 초점
- 객체 = 협력하는 공동체의 일원
- 상태를 분할의 중심축으로 삼는 방법
- 훌륭한 객체 지향 설계는 데이터가 아닌 책임에 초점을 맞춰야 한다.
- 객체의 상태는 구현에 속한다.
- 상태(데이터)를 객체 분할의 중심축으로 삼으면 구현에 관한 세부사항이 객체의 인터페이스에 스며들게 되어 캡슐화의 원칙이 무너지고, 결과적으로 상태의 변경은 인터페이스의 변경을 초래하며 이 인터페이스에 의존하는 모든 객체에게 변경의 영향이 퍼지게 된다.
- 객체의 책임은 인터페이스에 속한다.
- 책임을 객체 분할의 중심축으로 삼으면 객체는 책임을 드러내는 안정적인 인터페이스 뒤로 책임을 수행하는데 필요한 상태를 캡슐화함으로써 구현 변경에 대한 파장이 외부로 퍼져나가는 것을 방지하여 상대적으로 변경에 안정적인 설계를 얻을 수 있게 된다.
- 객체의 상태는 구현에 속한다.
- 데이터 중심의 설계
- 객체 내부에 저장되는 데이터를 기반으로 시스템을 분할하는 방법
- 객체가 내부에 저장해야 하는 데이터가 무엇인가를 묻는것으로 시작
- 캡슐화를 위한 방법
- 내부 데이터를 반환하는 접근자(accessor)와 데이터를 변경하는 수정자(mutator) 정의
- Github 01_ 영화 예매 애플리케이션의 데이터 주도 설계
- https://github.com/JIHYEON-PF/book_review_object/pull/9
04_설계 품질과 트레이드 오프 첫 번째 커밋 - 데이터 주도 설계 by JIHYEON-PF · Pull Request #9 · JIHYEON-
오브젝트의 04 챕터 설계 품질과 트레이드 오프에 대한 내용이다. 02장 객체지향 프로그래밍에서 진행하였던 영화 예매 애플리케이션을 데이터 주도 설계 방식을 바탕으로 설계하였으며 전체적
github.com
02_설계 트레이드오프
- 데이터 중심 설계와 책임 중심 설계의 장단점 비교
- 캡슐화
- 변경 가능성이 높은 부분(구현)을 객체 내부로 숨기는 추상화 기법
- 응집도와 결합도
- 응집도
- 모듈에 포함된 내부 요소들이 연관돼 있는 정도
- 모듈 내 요소들이 하나의 목적을 위해 긴밀하게 협력한다. → 높은 응집도
- 객체지향 관점 : 객체 또는 클래스에 얼마나 관련 높은 책임들을 할당했는지를 나타낸다.
- 변경의 관점 : 변경이 발생할 때 모듈 내부에서 발생하는 변경의 정도
- 결합도
- 의존성의 정도를 나타내며, 다른 모듈에 대해 얼마나 많은 지식을 갖고 있는지를 나타내는 척도
- 어떤 모듈이 다른 모듈에 대해 너무 자세한 부분까지 알고있다. → 높은 결합도
- 객체지향 관점 : 객체 또는 클래스가 협력에 필요한 적절한 수준의 관계만을 유지하고 있는지를 나타낸다.
- 변경의 관점 : 한 모듈이 변경되기 위해서 다른 모듈의 변경을 요구하는 정도
- 내부 구현을 변경했을 때 이것이 다른 모듈에 영향을 미치는 경우 → 두 모듈 사이의 결합도가 높다.
- 일반적으로 좋은 설계한 높은 응집도와 낮은 결합도를 가진 모듈로 구성된 설계를 의미
- 응집도
- 캡슐화의 정도가 응집도와 결합도에 영향을 미친다.
- 캡슐화를 지키면 모듈 안의 응집도는 높아지고, 모듈 사이의 결합도는 낮아진다.
- 응집도와 결합도를 고려하기 전에 먼저 캡슐화를 향상시켜야 한다.
- 캡슐화
03_데이터 중심의 영화 예매 시스템의 문제점
- 책임 중심 설계의 영화 예매 시스템과 데이터 중심 설계의 영화 예매 시스템은 기능적으로는 완전히 동일하지만, 설계의 관점에서는 근본적으로 캡슐화를 다루는 방식에서 차이점이 있다.
- 데이터 중심 설계
- 캡슐화를 위반하고 객체의 내부 구현을 인터페이스의 일부로 만든다.
- 캡슐화를 위반하기 쉽기 대문에 책임 중심 설계에 비해 응집도가 낮고 결합도가 높은 객체들을 양산하게 될 가능성이 높다.
- 책임 중심 설계
- 객체의 내부 구현을 안정적인 인터페이스 뒤로 캡슐화 한다.
- 데이터 중심 설계의 대표적 문제점
- 캡슐화 위반
- 추측에 의한 설계 전략 : 접근자와 수정자에 과도하게 의존하는 설계 방식
- 객체가 사용될 협력을 고려하지 않고 객체가 다양한 상황에서 사용될 수 있을것이라는 막연한 추측을 기반으로 설계를 진행
- 추측에 의한 설계 전략 : 접근자와 수정자에 과도하게 의존하는 설계 방식
- 높은 결합도
- 여러 데이터들을 사용하는 제어 로직이 특정 객체 안에 집중되기 때문에 하나의 제어 객체가 다수의 데이터 객체에 강하게 결합된다.
- 어떤 데이터 객체를 변경하더라도 제어 객체를 함께 변경할 수 밖에 없다.
- 데이터 중심 설계는 전체 시스템을 하나의 거대한 의존성 덩어리로 만들어 버리기 때문에 변경이 발생하게 되면 시스템 전체가 변경되는 위험을 가지고 있다.
- 여러 데이터들을 사용하는 제어 로직이 특정 객체 안에 집중되기 때문에 하나의 제어 객체가 다수의 데이터 객체에 강하게 결합된다.
- 낮은 응집도
- 서로 다른 이유로 변경되는 코드가 하나의 모듈 안에 공존할 때 모듈의 응집도는 낮다.
- 낮은 응집도의 설계 문제점
- 변경과 아무 상관 없는 코드들이 영향을 받게 된다.
- 하나의 요구사항을 변경하기 위해 동시에 여러 모듈을 수정해야 한다.
- 캡슐화 위반
04_자율적인 객체를 향해
- 캡슐화를 지켜라
- 캡슐화는 설계의 제 1원리이다.
- 데이터 중심의 설계가 낮은 응집도와 높은 결합도라는 문제를 야기한 근본적인 원인은 캡슐화의 원칙을 위반했기 때문이다.
- 객체는 스스로의 상태를 책임져야 하며 외부에서는 인터페이스에 정의된 메서드를 통해서만 상태에 접근할 수 있어햐 한다.
- 스스로 자신의 데이터를 책임지는 객체
- 객체 설계를 위한 질문
- 이 객체가 어떤 데이터를 포함해야 하는가?
- 이 객체가 데이터에 대해 수행해야 하는 오퍼레이션은 무엇인가?
- 위 질문을 통해 객체의 내부 상태를 저장하는 방식과 저장된 상태에 대해 호출할 수 있는 오퍼레이션의 집합을 얻을 수 있다.
- 새로운 데이터 타입을 만들 수 있다.
- 객체 설계를 위한 질문
- github 02 _ 영화 예매 애플리케이션의 리펙토링 - 자율적인 객체로 수정하기
- https://github.com/JIHYEON-PF/book_review_object/pull/10
04_설계 품질과 트레이드오프 두 번째 커밋 - 자율적인 객체로 변환 by JIHYEON-PF · Pull Request #10 · JI
데이터 주도 설계를 통해 작성되었던 영화 예매 애플리케이션이 각 객체가 스스로 책임을 지는 자율적인 객체가 될 수 있도록 리팩토링 되었다. DiscountCondition Movie ReservationAgency Screening 위 4개의
github.com
05_하지만 여전히 부족하다(github)
- github 예제의 첫 번째 설계보다 두 번재 설계가 향상되었다.
- 여전히 존재하는 문제점
- 여전히 데이터 중심의 설계 방식에 속한다
- 첫 번째 설계에서 발생했던 대부분의 문제점이 여전히 존재한다.
- 캡슐화 위반
- DiscountCondition
- isDiscountCondition을 통해 내부 속성 dayOfWeek, startTime, endTime, sequence의 타입(DayOfWeek, LocalTime, int)이 외부로 노출됨
- getType을 통해 내부에 DiscountConditionType을 포함한다는 것을 외부로 노출
- DiscountCondition의 속성이 변경될 경우 isDiscountCondition이 수정되고, 해당 메서드를 사용하는 모든 클라이언트도 동시에 수정되어야 한다.(파급효과)
- Movie
- 메서드 calculateAmountDiscountedFee(), calculatePercentDiscountedFee(), calculateNoneDiscountedFee()를 통해 할인 정책에 금액 할인 정책, 비율 할인 정책, 미적용의 세가지가 존재한다는 정보를 외부로 노출
- 할인 정책이 추가, 삭제 등의 변경이 일어날 경우 해당 메서드에 의존하는 모든 클라이언트가 영향을 받음(파급효과)
- DiscountCondition
- 높은 결합도
- DiscountCondition의 내부 구현이 외부로 노출되었기 때문에 Movie와 DiscountCondition 사이에 높은 결합도가 발생
- 낮은 응집도
- DiscountCondition의 할인 여부 판단에 대한 정보가 변경
- Movie의 isDiscount 메서드로 전달해야 하는 파라미터의 종류 변경
- Screening에서 Movie의 isDiscount 메서드 호출부분 변경
- DiscountCondition의 할인 여부 판단에 대한 정보가 변경
- 여전히 존재하는 문제점
06_데이터 중심 설계의 문제점
- 데이터 중심의 설계가 변경에 취약한 이유
- 데이터 중심의 설계는 본질적으로 너무 이른 시기에 데이터에 관해 결정하도록 강요한다.
- 데이터 중심의 설계에서는 협력이라는 문맥을 고려하지 않고 객체를 고립시킨 채 오퍼레이션을 결정한다.
- 데이터 중심 설계는 객체의 행동보다는 상태에 초점을 맞춘다.
- 데이터 중심 설계 방식에 익숙한 개발자들은 일반적으로 데이터와 기능을 분리하는 절차적 프로그래밍 방식에 따름
- 상태와 행동을 하나의 단위로 캡슐화 하는 객체지향 패러다임에 반하는 것
- 데이터를 처리하는 작업과 데이터를 같은 객체 안에 두더라도 데이터에 초점이 맞춰져 있다면 만족스러운 캡슐화를 얻기 어렵다.
- 데이터 중심 설계 방식에 익숙한 개발자들은 일반적으로 데이터와 기능을 분리하는 절차적 프로그래밍 방식에 따름
- 데이터 중심 설계는 객체를 고립시킨 채 오퍼레이션을 정의하도록 만든다.
- 올바른 객체 지향 설계의 무게중심은 항상 객체의 내부가 아니라 외부에 맞춰져 있어야 한다.
- 데이터 중심 설계의 초점은 객체의 외부가 아닌 내부로 향한다.
07_Review
- 04_설계 품질과 트레이드를 읽으면서 내가 해오던 설계에 대해 회의감을 느끼게 되었다. 내가 생각하기에 나는 객체지향적으로 설계를 하고 있고 책을 읽으면서 완벽하게는 아니더라도 책임 주도 설계를 하고있다고 생각했다. 그런데 데이터 주도 설계에 대한 예시를 보면서부터 내 생각은 완전히 무너졌다. 내가 하던 것은 철저하게 데이터 주도 설계였다. 물론 예시처럼 클래스의 모든 속성을 public으로 두고 다른 객체에서 해당 객체로 바로 접근할 수 있거나, 캡슐화 실패로 인해 지나치게 응집도가 낮고 결합도가 높은 형식의 모델링은 아니지만, 이것은 회사의 컨벤션을 따라가면서 나도모르게 고쳐진 부분이었다. 그 전 개인 프로젝트를 보면 누가봐도 문제점이다. 하나의 시스템 전체가 커다란 유기체처럼 활동하고 있다. 명확한 경계가 없이 상호 의존적이며 캡슐화 실패, 낮은 응집도, 높은 결합도 모든 문제의 산물이다.... 지금이라도 깨닫고 다른 방향으로 재설계하고 리팩토링 방향을 잡아갈 수 있어서 다행스럽다.
- 책 내용에서 가장 중요하다고 느꼈던 개념은 캡슐화였다. 책에서는 책임이라는 키워드를 통해 모든것을 유기적으로 연결하여 설명하고 있지만, 아직까지 그 개념이 정확하게 와닿지 않아서 캡슐화가 대신해서 뇌리에 박혔다. 모든 설계 품질을 결정하는것은 캡슐화 인것같다. (물론 책에서는 책임이 설계품질을 좌우한다고 하고있다.) 캡슐화가 잘 되어있는 설계는 결국 낮은 응집도와 높은 결합도를 유도할 수 있고, 궁극적으로 높은 품질의 설계를 이끌어 낼 수 있다고 생각하게 되었다.
- 이제부터라도 도메인을 설계하면서 각 객체들의 역할과 책임, 그리고 캡슐화에 대해 중점을 두고 설계품질을 올리도록 노력해야겠다.
(참고문헌: 조영호, 오브젝트 - 코드로 이해하는 객체지향 설계, 위키북스, 2022.11.30(6쇄 발행), p.97 ~ p.132)