Intro
이번 4회차 스터디는 강남역 5번 출구 부근 더나은플레이스에서 진행했습니다.
건물의 지하 2층에 작은 투명한 문 하나가 있었고 문 안으로 들어가면 방이 3개있는 곳이었습니다.
전문 스터디 룸은 아니었고, 아늑하고 이쁜 공간에서 소규모로 미팅 같은 것을 할 수 있는 장소였습니다.
장소가 예뻐서 사진도 찍게 되었네요. (거울에 제 모습이 있는건 지금 올리다가 알았습니다.)
디퓨저도 있었고, 조용했습니다.
기존 전문 스터디 룸들 가격이 2시간 기준 4400원, 3000원이었던 것을 감안하면 이번 공간은 5000원이 었기 때문에 약간 비쌌지만, 그만큼 환경이 깔끔해서 이용 경험이 좋았습니다.
단점은 건물까지 찾아가는 게 어렵고, 건물에서도 공간 안내가 잘 되어있지 않았고, 들어가서도 어딘지 잘 알 수 없었다는 것입니다.
이번 스터디에는 @muki4742 님과 @freebear 님께서 불참하셨습니다.
4장부터는 구체적인 소스코드 예제를 통한 책임 기반 설계의 실제 리펙토링이 들어가기 때문에 어려운 내용이었고, 2명의 불참으로 시간이 많이 비었던만큼 4장의 내용에 대해서 나눔하기 적절했습니다.
독후감 문장
97P
결국 책임이 객체지향 애플리케이션 전체의 품질을 결정하는 것이다.
객체지향 설계란 올바른 객체에게 올바른 책임을 할당하면서 낮은 결합도와 높은 응집도를 가진 구조를 창조하는 활동이다. 이 정의에는 객체지향 설계에 관한 두 가지 관점이 섞여 있다. 첫 번째 관점은 객체지향 설계의 핵심이 책임이라는 것이다. 두 번째 관점은 책임을 할당하는 작업이 응집도와 결합도 같은 설계 품질과 깊이 연관돼 있다는 것이다.
설계는 변경을 위해 존재하고 변경에는 변경에는 어떤 식으로든 비용이 발생한다. 훌륭한 설계란 합리적인 비용 안에서 변경을 수용할 수 있는 구조를 만드는 것이다.
객체의 상태가 아니라 객체의 초점을 맞추는 것이다.
객체를 단순한 데이터의 집합으로 바라보는 시각은 객체의 내부 구현을 퍼블릭 인터페이스에 노출시키는 결과를 낳기 때문에 결과적으로 설계가 변경에 취약해진다.
98P
가끔씩은 좋은 설계보다는 나쁜 설계를 살펴보는 과정에서 통찰을 얻기도 한다.
데이터 중심의 관점에서 객체는 자신이 포함하고 있는 데이터를 조작하는 데 필요한 오퍼레이션을 정의한다. 책임 중심의 관점에서 객체는 다른 객체가 요청할 수 있는 오퍼레이션을 위해 필요한 상태를 보관한다.
데이터 중심의 관점은 객체의 상태에 초점을 맞추고 책임 중심의 관점은 객체의 행동에 초점을 맞춘다.
객체의 상태는 구현에 속한다. 구현은 불안정하기 때문에 변하기 쉽다.
99P
그에 비해 객체의 책임은 인터페이스에 속한다.
책임 중심의 설계가 '책임이 무엇인가’를 묻는 것으로 시작한다면 데이터 중심의 설계는 객체가 내부에 저장해야 하는 '데이터가 무엇인가’를 묻는 것으로 시작한다.
106P
ReservationAgeny는 데이터 클래스들을 조합해서 영화 예매 절차를 구현하는 클래스다.
109P
객체를 설계하기 위한 가장 기본적인 아이디어는 변경의 정도에 따라 구현과 인터페이스를 분리하고 외부에서는 인터페이스에만 의존하도록 관계를 조절하는 것이다.
객체지향 설계의 가장 중요한 원리는 불안정한 구현 세부사항을 안정적인 인터페이스 뒤로 캡슐화하는 것이다.
훌륭한 프로그래밍 기술을 적용해서 캡슐화를 향상시킬 수는 있겠지만 객체지향 프로그래밍을 통해 전반적으로 얻을 수 있는 장점은 오직 설계 과정 동안 캡슐화를 목표로 인식할 때만 달성될 수 있다[Wirfs-Brock89].
설계가 필요한 이유는 요구사항이 변경되기 때문이고, 캡슐화가 중요한 이유는 불안정한 부분과 안정적인 부분을 분리해서 변경의 영향을 통제할 수 있기 때문이다.
정리하면 캡슐화란 변경 가능성이 높은 부분을 객체 내부로 숨기는 추상화 기법이다. 객체 내부에 무엇을 캡슐화해야 하는가? 변경될 수 있는 어떤 것이라도 캡슐화해야 한다.
유지보수성이 목표다. 여기서 유지보수성이란 두려움 없이, 주저함 없이, 저항감 없이 코드를 변경할 수 있는 능력을 말한다.
110P
일반적으로 좋은 설계란 높은 응집도와 낮은 결합도를 가진 모듈로 구성된 설계를 의미한다.
좋은 설계란 오늘의 기능을 수행하면서 내일의 변경을 수용할 수 있는 설계다.
112P
이것은 "인터페이스에 대해 프로그래밍하라[GOF94]"라는 격언으로도 잘 알려져 있다.
기능적인 측면에서만 놓고 보면 이번 장에서 구현한 데이터 중심의 설계는 2장에서 구현한 책임 중심의 설게와 완전히 동일하다. 하지만 설계 관점에서는 완전히 다르다.
114P
설계할 때 협력에 관해 고민하지 않으면 캡슐화를 위반하는 과도한 접근자와 수정자를 가지게 되는 경향이 있다.
앨런 홀럽(Allen Holub)은 이처럼 접근자와 수정자에 과도하게 의존하는 설계 방식을 추측에 의한 설계 전략(design-by-guessing strategy)[Holub04]이라고 부른다. 이 전략은 객체가 사용될 협력을 고려하지 않고 객체가 다양한 상황에서 사용될 수 있을 것이라는 막연한 추측을 기반으로 설계를 진행한다. 따라서 프로그래머는 내부 상태를 드러내는 메서드를 최대한 많이 추가해야 한다는 압박에 시달릴 수 밖에 없으며 결과적으로 대부분의 내부 구현이 퍼블릭 인터페이스에 그대로 노출될 수밖에 없는 것이다.
116P
데이터 중심의 설계는 전체 시스템을 하나의 거대한 의존성 덩어리로 만들어 버리기 때문에 어떤 변경이라도 일단 발생하고 나면 시스템 전체가 요동칠 수밖에 없다.
117P
속성의 가시성을 private으로 설정했다고 해도 접근자와 수정자를 통해 속성을 외부로 제공하고 있다면 캡슐화를 위반하는 것이다.
119P
코드 중복은 악의 근원이다.
객체는 단순한 데이터 제공자가 아니다.
120P
다시 말해 새로운 데이터 타입을 만들 수 있는 것이다.
126P
내부 구현의 변경이 외부로 퍼져나가는 **파급 효과(ripple effect)**는 캡슐화가 부족하다는 명백한 증거다. 따라서 변경 후의 설계는 자기 자신을 스스로 처리한다는 점에서는 이전의 설계보다 분명히 개선됐지만 여전히 내부의 구현을 캡슐화하는 데는 실패한 것이다.
127P
calculateAmountDiscountedFee, calculatePercentDiscountedFee, calculateNoneDiscountedFee라는 세 개의 메서드는 할인 정책에는 금액 할인 정책, 비율 할인 정책, 미적용의 세 가지가 존재한다는 사실을 만천하에 드러내고 있다.
128P
다시 한번 강조하지만 캡슐화란 변할 수 있는 어떤 것이라도 감추는 것이다.
132P
객체지향 애플리케이션을 구현한다는 것은 협력하는 객체들의 공동체를 구축한다는 것을 의미한다.
이번 장에서는 데이터 주도 설계에서 책임 주도 설계로 넘어가는 실질적인 소스코드 예제가 나왔습니다. 하지만 아직 추상화가 완벽하지 않다고 하면서 4챕터가 마무리됩니다.
이번 챕터는 실제적으로 변화하는 과정을 담고 있기 때문에 객체지향적이지 않은 것과 객체지향 적인 것과 차이의 중간과정을 볼 수 있는 챕터라고 생각하여 아주 중요하게 생각합니다.
챕터를 거듭해가면서 점점 더 고급스럽고 원칙에 입각한 설계가 나올 것이라고 기대가 됩니다.