6장 정리
애플리케이션은 클래스로 구성되지만 메시지를 통해 정의된다는 사실을 기억해야 한다.
객체지향 프로그래밍의 애플리케이션에서는 클래스라는 구현 도구가 아닌 객체들이 주고 받는 메시지에 초점을 둔다.
객체가 수신하는 메시지들이 객체의 퍼블릭 인터페이스를 구성한다.
훌륭한 퍼블릭 인터페이스를 얻기 위해서는 책임 주도 설계 방법 뿐 아니라, 유연하고 재사용 가능한 퍼블릭 인터페이스를 만드는 데 도움이 되는 설계 원칙과 기법을 익히고 적용해야 한다.
인터페이스와 설계 품질
객체가 수신할 수 있는 메시지가 객체의 퍼블릭 인터페이스와 그 안에 포함될 오퍼레이션을 결정한다.
객체의 퍼블릭 인터페이스가 객체의 품질을 결정하기 때문에 결국 메시지가 객체의 품질을 결정한다.
책임 주도 설계 방법은 훌륭한 인터페이스를 얻을 수 있는 지침을 제공하지만, 더 넓은 안목과 올바른 설계를 위해서는 퍼블릭 인터페이스의 품질에 영향을 미치는 설계 원칙과 기법을 익히고 적용해야 한다.
디미터 법칙
흔히들 "낯선 자에게 말하지 말라", 자바같은 언어에서는 "오직 하나의 도트만 사용하라" 라는 말로 요약되는 법칙이다.
디미터 법칙을 따르기 위해서는 클래스가 특정한 조건을 만족하는 대상에게만 메시지를 전송하도록 프로그래밍 해야한다.
- this 객체
- 메서드의 매개변수
- this의 속성
- this의 속성인 컬렉션의 요소
- 메서드 내에서 생선된 지역 객체
디미터 법칙을 따르면 불필요한 어떤 것도 다른 객체에게 보여주지 않으며, 다른 객체의 구현에 의존하지 않는 부끄럼타는 코드(shy code) 를 작성할 수 있다.
묻지 말고 시켜라
객체의 상태에 관해 묻지 말고 원하는 것을 시키는 메시지 작성을 장려하는 원칙이다.
묻지 말고 시켜라 원칙을 따르면 객체의 정보를 이용하는 행동을 객체의 외부가 아닌 내부에 위치시키기 때문에 자연스럽게 정보와 행동을 동일한 클래스 안에 두게 된다.
이 원칙을 따른다면 자연스럽게 정보 전문가에게 책임을 할당하게 되고, 높은 응집도를 가진 클래스를 작성할 확률이 높아진다.
의도를 드러내는 인터페이스
훌륭한 인터페이스는 객체가 어떻게 하는지가 아니라 무엇을 하는지를 서술해야 한다.
무엇을 하는지를 드러내는 인터페이스는 코드를 읽고 이해하기 쉽우며, 유연한 코드를 낳는다.
의도를 드러내는 인터페이스를 한 마디로 요약하면 구현과 관련된 모든 정보를 캡슐화하고 객체의 퍼블릭 인터페이스에는 협력과 관련된 의도만을 표현해야 한다는 것이다.
함께 모으기
디미터 법칙, 묻지 말고 시켜라, 의도를 드러내는 인터페이스라는 원칙들을 통해 결합도가 낮으면서도 의도를 명확히 드러내는 간결합 협력을 구현할 수 있다.
원칙의 함정
원칙을 맹목적으로 추종하지 말라.
현재 상황에 어떤 원칙이 부적합하다고 판단된다면 과감하게 원칙을 무시할 필요도 있다.
원칙을 아는 것보다 더 중요한 것은 언제 원칙이 유용하고 언제 유용하지 않은지를 판단할 수 있는 능력을 기르는 것이다.
디미터 법칙은 하나의 도트(.)를 강제하는 규칙이 아니다
스트림이 좋은 예시다.
IntStream.map(o -> o +1).filter(o -> o % 2 == 0) 에서
map, filter 는 IntStream 을 또 다른 IntStream 인스턴스로 변환할 뿐 내부 구조를 노출 시키지 않는다.
디미터 법칙은 결합도와 관련된 것이며, 이 결합도가 문제 되는 것은 객체의 내부 구조가 외부로 노출되는 경우이다.
결합도와 응집도의 충돌
묻지 말고 시켜라와 디미터 법칙을 준수하는 것이 항상 긍정적인 결과로만 귀결되지는 않는다.
맹목적으로 위임 메서드를 추가하면 하나의 객체 안에 상관 없는 책임들이 공존하게 되고, 결과적으로 응집도가 낮아진다.
가끔씩은 묻는 것 외에는 다른 방법이 존재하지 않을 수도 있다. 컬렉션에 포함된 객체들을 처리하는 유일한 방법은 객체에게 물어보는 것이다.
디미터 법칙의 위반 여부는 묻는 대상이 객체인지, 자료 구조인지에 따라 달려있다. 객체의 내부 구조를 드러내는건 문제가 되지만, 자료 구조의 내부를 노출하는건 문제가 되지 않는다.
결국 설계는 트레이드오프의 산물이며, 원칙을 맹목적으로 따르지 말고 언제나 "경우에 따라 다르다"라는 사실을 명심해야 한다.
명령-쿼리 분리 원칙
프로시저 - 부수효과 발생, void
함수 - 부수효과 x, return 값 있음
개념적으로 프로시저는 명령, 함수는 쿼리라고 할 수 있다.
명령은 부수효과를 일으키므로 상태를 변경하고 결과 값을 반환하지 않는다.
쿼리는 몇번을 실행해도 똑같은 결과를 보장할 수 있으므로 결과 값을 반환한다.
명령과 쿼리가 합쳐진 코드는 내부 상태도 변경하고 결과 값도 반환하므로 예측하기 힘들고 디버깅이 쉽지 않다.
따라서 퍼블릭 인터페이스를 설계할 때 명령과 쿼리를 분리하면 예측 가능하고 이해하기 쉬우며 디버깅이 용이하여 유지보수에 수월한 코드를 작성할 수 있다.
인상깊었던 점
"원칙을 아는 것보다 더 중요한 것은 언제 원칙이 유용하고 언제 유용하지 않은지를 판단할 수 있는 능력을 기르는 것이다."
이번 장에서 인상 깊었던 문장은 이 문장이었다.
1장부터 그랬지만 이 책은 "단순히 객체지향은 이렇게 해야한다." 라고 말하기 보다는 객체지향이 목표하는 것을 설명하고, 훌륭한 객체지향 프로그램을 개발하기 위해서 알아두면 좋은 설계 원칙과 기법을 알려주고 있다.
동시에 원칙을 맹목적으로 추종하지 말고 언제 원칙이 유용하고 언제 유용하지 않은지를 판단할 수 있는 능력을 기르는데 초점을 맞추라고 말한다.
무지성 클린코드 추종자처럼 이상론자가 되지 말고 꾸준히 코드를 작성하면서 생각하고, 체감하고, 공부해서 제대로 이해하고 적용하는게 중요하다고 말하는 점이 좋았다.