"이 객체가 수행해야 하는 책임은 무엇인가"를 결정한 후에 "이 책임을 수행하는데 필요한 데이터는 무엇인가"를 결정한다.
책임은 객체의 입장이 아니라 객체가 참여하는 협력에 적합해야 한다.
메시지가 클라이언트의 의도를 표현한다.
클라이언트는 단지 임의의 객체가 메시지를 수신할 것이라는 사실을 믿고 자신의 의도를 표현한 메시지를 전송할 뿐이다.
그리고 메시지를 수신하기로 결정된 객체는 메시지를 처리할 '책임'을 할당 받게 된다.
여러 설계가 있을 경우 높은 응집도와 낮은 결합도를 얻을 수 있는 설계가 있다면 그 설계를 선택해야 한다.
polymorphism 패턴은 객체의 타입을 검사해서 타입에 따라 여러 대안들을 수행하는 조건적인 논리를 사용하지 말라고 경고한다. (if ~ else 또는 switch ~ case 등의 조건 논리)
대신 다형성을 이용해 새로운 변화를 다루기 쉽게 확장하자.
현재 설계에서 할인 정책코드가 상속을 사용했다면?
실행 중에 영화의 할인 정책을 변경하기 위해서는 새로운 인스턴스를 생성한 후 필요한 정보를 복사해야 한다.
또한 변경 전후의 인스턴스가 개념적으로는 동일한 객체를 가리키지만 물리적으로 서로 다른 객체이기 때문에 식별자의 관점에서 혼란스러울 수 있다.
즉 새로운 할인 정책이 추가될 때마다 인스턴스를 생성하고, 상태를 복사하고, 식별자를 관리하는 코드를 추가하는 일은 번거로울뿐만 아니라 오류가 발생하기도 쉽다.
해결 방법은 상속 대신 합성을 사용하는 것이다.
긴 메서드는 다양한 측면에서 코드의 유지 보수에 부정적인 영향을 미친다. (강한 결합, 낮은 응집도)
이런 경우 로직의 흐름을 이해하기 위해 주석이 필요한 경우가 대부분이다. 주석을 추가하는 대신 메서드를 작게 분해해서 각 메서드의 응집도를 높여라.
작은 메서들로 분해하면 전체적인 흐름을 이해하기도 쉽고 단 하나의 이유에 의해서만 변경된다.
자신이 소유하고 있는 데이터를 자기 스스로 처리하도록 만드느 것이 자율적인 객체를 만드는 지름길이다.
데이터를 사용하는 메서드를 데이터를 가진 클래스로 이동시키고 나면 캡슐화와 높은 응집도, 낮은 결합도를 가지는 설계를 얻게 된다.