Message: 객체가 다른 객체와 협력하기 위해 사용하는 의사소통 메커니즘. 일반적으로 객체의 오퍼레이션이 실행되도록 요청하는 것을 “메시지 전송”이라고 부른다. 메시지는 협력에 참여하는 전송자와 수신자 양쪽 모두를 포함하는 개념이다.
Operation: 객체가 다른 객체에게 제공하는 추상적인 서비스다. 메시지가 전송자와 수신자 사이의 협력 관계를 강조하는 데 비해 오퍼레이션은 메시지를 수신하는 객체의 인터페이스를 강조한다. 다시 말해서 메시지 전송자는 고려하지 않은 채 메시지 수신자의 관점만을 다룬다. 메시지 수신이란 메시지에 대응되는 객체의 오퍼레이션을 호출하는 것을 의미한다.
Method: 메시지에 응답하기 위해 실행되는 코드 블록을 메서드라고 부른다. 메서드는 오퍼레이션의 구현이다. 동일한 오퍼레이션이라고 해도 메서드는 다를 수 있다. 오퍼레이션과 메서드의 구분은 다형성의 개념과 연결된다.
Public interface: 객체가 협력에 참여하기 위해 외부에서 수신할 수 있는 메시지의 묶음. 클래스의 퍼블릭 메서드들의 집합이나 메시지의 집합을 가리키는 데 사용된다. 객체를 설계할 때 가장 중요한 것은 훌륭한 퍼블릭 인터페이스를 설계하는 것이다.
SIgnature: 시그니처는 오퍼레이션이나 메서드의 명세를 나타낸 것으로, 이름과 인자의 목록을 포함한다. 대부분의 언어
는 시그니처의 일부로 반환 타입을 포함하지 않지만 반환 타입을 시그니처의 일부로 포함하는 언어도 존재한다.
02 인터페이스와 설계 품질
디미터의 법칙
디미터 법칙을 간단하게 요약하면 객체의 내부 구조에 강하게 결합되지 않도록 협력 경로를 제한하라는 것이다.
디미터 법칙은 “낯선 자에게 말하지 말라(don’t talk to strangers)[Larman04]” 또는 “오직 인접한 이웃하고만 말하라(only talk to your immediate neighbors)[Metz12]”로 요약할 수 있다.
디미터 법칙과 캡슐화
디미터 법칙은 캡슐화를 다른 관점에서 표현한 것이다.
디미터 법칙이 가치 있는 이유는 클래스를 캡슐화하기 위해 따라야 하는 구체적인 지침을 제공하기 때문이다. 캡슐화 원칙이 클래스 내부의 구현을 감춰야 한다는 사실을 강조한다면 디미터 법칙은 협력하는 클래스의 캡슐화를 지키기 위해 접근해야 하는 요소를 제한한다.
디미터 법칙은 협력과 구현이라는 사뭇 달라 보이는 두 가지 문맥을 하나의 유기적인 개념으로 통합한다.
클래스의 내부 구현을 채워가는 동시에 현재 협력하고 있는 클래스에 관해서도 고민하도록 주의를 환기시키기 때문이다.
묻지 말고 시켜라
디미터 법칙은 훌륭한 메시지는 객체의 상태에 관해 묻지 말고 원하는 것을 시켜야 한다는 사실을 강조한다.
묻지 말고 시켜라(Tell, Don’t Ask)는 이런 스타일의 메시지 작성을 장려하는 원칙을 가리키는 용어다.
의도를 드러내는 인터페이스
어떻게 하느냐가 아니라 무엇을 하느냐에 따라 메서드의 이름을 짓는 패턴을 의도를 드러내는 선택자(Intention Revealing Selector)라고 부른다. 켄트 벡은 메서드에 의도를 드러낼 수 있는 이름을 붙이기 위해 다음과 같이 생각할 것을 조언한다.
하나의 구현을 가진 메시지의 이름을 일반화하도록 도와주는 간단한 훈련 방법을 소개하겠다.
매우 다른 두 번째 구현을 상상하라. 그러고는 해당 메서드에 동일한 이름을 붙인다고 상상해보라.
그렇게 하면 아마도 그 순간에 여러분이 할 수 있는 한 가장 추상적인 이름을 메서드에 붙일 것이다[Beck96].
《도메인 주도 설계》[Evans03]에서 에릭 에반스(Eric Evans)는 켄트 벡의 의도를 드러내는 선택자를 인터페이스 레벨로 확장한 의도를 드러내는 인터페이스(Intention Revealing Interface)를 제시했다.
의도를 드러내는 인터페이스를 한 마디로 요약하면 구현과 관련된 모든 정보를 캡슐화하고 객체의 퍼블릭 인터페이스에는 협력과 관련된 의도만을 표현해야 한다는 것이다.
함께 모으기
1장의 티켓 판매 도메인을 리팩터링 하면서 확인
디미터 법칙을 위반하는 티켓 판매 도메인
묻지 말고 시켜라
인터페이스에 의도를 드러내자
결합도가 낮으면서도 의도를 명확히 드러내는 간결한 협력을 원한다.
디미터 법칙과 묻지 말고 시켜라 스타일, 의도를 드러내는 인터페이스가 우리를 도울 것이다.
정보 은닉 말고도 “묻지 말고 시켜라” 스타일에는 좀 더 미묘한 이점이 있다.
이 스타일은 객체 간의 상호작용을 getter의 체인 속에 암시적으로 두지 않고 좀 더 명시적으로 만들고 이름을 가지도록 강요한다[Freeman09].
03 원칙의 함정
설계를 적절하게 트레이드오프할 수 있는 능력이 숙련자와 초보자를 구분하는 가장 중요한 기준이라고 할 수 있다.
초보자는 원칙을 맹목적으로 추종한다. 심지어 적용하려는 원칙들이 서로 충돌하는 경우에도 원칙에 정당성을 부여하고 억지로 끼워 맞추려고 노력한다.
결과적으로 설계는 일관성을 잃어버리고 코드는 무질서 속에 파묻히며 개발자는 길을 잃은 채 방황하게 된다.
원칙이 현재 상황에 부적합하다고 판단된다면 과감하게 원칙을 무시하라.원칙을 아는 것보다 더 중요한 것은 언제 원칙이 유용하고 언제 유용하지 않은지를 판단할 수 있는 능력을 기르는 것이다.
디미터 법칙은 하나의 도트(.)를 강제하는 규칙이 아니다.
결합도와 응집도의 충돌
로버트 마틴은 《클린 코드》[Martin08]에서 디미터 법칙의 위반 여부는 묻는 대상이 객체인지, 자료 구조인지에 달려있다고 설명한다.
객체는 내부 구조를 숨겨야 하므로 디미터 법칙을 따르는 것이 좋지만 자료 구조라면 당연히 내부를 노출해야 하므로 디미터 법칙을 적용할 필요가 없다.
객체에게 시키는 것이 항상 가능한 것은 아니다. 가끔씩은 물어야 한다. 여기서 강조하고 싶은 것은 소프트웨어 설계에 법칙이란 존재하지 않는다는 것이다.
원칙을 맹신하지 마라. 원칙이 적절한 상황과 부적절한 상황을 판단할 수 있는 안목을 길러라.
설계는 트레이드오프의 산물이다. 소프트웨어 설계에 존재하는 몇 안 되는 법칙 중 하나는 “경우에 따라 다르다”라는 사실을 명심하라.
04 명령-쿼리 분리 원칙
명령-쿼리 분리 원칙은 퍼블릭 인터페이스에 오퍼레 이션을 정의할 때 참고할 수 있는 지침을 제공한다.
어떤 절차를 묶어 호출 가능하도록 이름을 부여한 기능 모듈을 루틴(routine)이라고 부른다.
루틴은 다시 프로시저(procedure)와 함수(function)로 구분할 수 있다
프로시저는 부수효과를 발생시킬 수 있지만 값을 반환할 수 없다.
함수는 값을 반환할 수 있지만 부수효과를 발생시킬 수 없다.
명령(Command)과 쿼리(Query)는 객체의 인터페이스 측면에서 프로시저와 함수를 부르는 또 다른 이름이다.
객체의 상태를 수정하는 오퍼레이션을 명령이라고 부르고 객체와 관련된 정보를 반환하는 오퍼레이션을 쿼리라고 부른다.
따라서 개념적으로 명령은 프로시저와 동일하고 쿼리는 함수와 동일 하다.
CHAPTER 06 메시지와 인터페이스
01 협력과 메시지
02 인터페이스와 설계 품질
디미터의 법칙
디미터 법칙을 간단하게 요약하면 객체의 내부 구조에 강하게 결합되지 않도록 협력 경로를 제한하라는 것이다. 디미터 법칙은 “낯선 자에게 말하지 말라(don’t talk to strangers)[Larman04]” 또는 “오직 인접한 이웃하고만 말하라(only talk to your immediate neighbors)[Metz12]”로 요약할 수 있다.
묻지 말고 시켜라
디미터 법칙은 훌륭한 메시지는 객체의 상태에 관해 묻지 말고 원하는 것을 시켜야 한다는 사실을 강조한다. 묻지 말고 시켜라(Tell, Don’t Ask)는 이런 스타일의 메시지 작성을 장려하는 원칙을 가리키는 용어다.
의도를 드러내는 인터페이스
어떻게 하느냐가 아니라 무엇을 하느냐에 따라 메서드의 이름을 짓는 패턴을 의도를 드러내는 선택자(Intention Revealing Selector)라고 부른다. 켄트 벡은 메서드에 의도를 드러낼 수 있는 이름을 붙이기 위해 다음과 같이 생각할 것을 조언한다.
《도메인 주도 설계》[Evans03]에서 에릭 에반스(Eric Evans)는 켄트 벡의 의도를 드러내는 선택자를 인터페이스 레벨로 확장한 의도를 드러내는 인터페이스(Intention Revealing Interface)를 제시했다. 의도를 드러내는 인터페이스를 한 마디로 요약하면 구현과 관련된 모든 정보를 캡슐화하고 객체의 퍼블릭 인터페이스에는 협력과 관련된 의도만을 표현해야 한다는 것이다.
함께 모으기
1장의 티켓 판매 도메인을 리팩터링 하면서 확인
결합도가 낮으면서도 의도를 명확히 드러내는 간결한 협력을 원한다. 디미터 법칙과 묻지 말고 시켜라 스타일, 의도를 드러내는 인터페이스가 우리를 도울 것이다.
03 원칙의 함정
설계를 적절하게 트레이드오프할 수 있는 능력이 숙련자와 초보자를 구분하는 가장 중요한 기준이라고 할 수 있다. 초보자는 원칙을 맹목적으로 추종한다. 심지어 적용하려는 원칙들이 서로 충돌하는 경우에도 원칙에 정당성을 부여하고 억지로 끼워 맞추려고 노력한다. 결과적으로 설계는 일관성을 잃어버리고 코드는 무질서 속에 파묻히며 개발자는 길을 잃은 채 방황하게 된다.
원칙이 현재 상황에 부적합하다고 판단된다면 과감하게 원칙을 무시하라.원칙을 아는 것보다 더 중요한 것은 언제 원칙이 유용하고 언제 유용하지 않은지를 판단할 수 있는 능력을 기르는 것이다.
로버트 마틴은 《클린 코드》[Martin08]에서 디미터 법칙의 위반 여부는 묻는 대상이 객체인지, 자료 구조인지에 달려있다고 설명한다. 객체는 내부 구조를 숨겨야 하므로 디미터 법칙을 따르는 것이 좋지만 자료 구조라면 당연히 내부를 노출해야 하므로 디미터 법칙을 적용할 필요가 없다.
객체에게 시키는 것이 항상 가능한 것은 아니다. 가끔씩은 물어야 한다. 여기서 강조하고 싶은 것은 소프트웨어 설계에 법칙이란 존재하지 않는다는 것이다. 원칙을 맹신하지 마라. 원칙이 적절한 상황과 부적절한 상황을 판단할 수 있는 안목을 길러라. 설계는 트레이드오프의 산물이다. 소프트웨어 설계에 존재하는 몇 안 되는 법칙 중 하나는 “경우에 따라 다르다”라는 사실을 명심하라.
04 명령-쿼리 분리 원칙
명령-쿼리 분리 원칙은 퍼블릭 인터페이스에 오퍼레 이션을 정의할 때 참고할 수 있는 지침을 제공한다.
어떤 절차를 묶어 호출 가능하도록 이름을 부여한 기능 모듈을 루틴(routine)이라고 부른다. 루틴은 다시 프로시저(procedure)와 함수(function)로 구분할 수 있다
명령(Command)과 쿼리(Query)는 객체의 인터페이스 측면에서 프로시저와 함수를 부르는 또 다른 이름이다. 객체의 상태를 수정하는 오퍼레이션을 명령이라고 부르고 객체와 관련된 정보를 반환하는 오퍼레이션을 쿼리라고 부른다. 따라서 개념적으로 명령은 프로시저와 동일하고 쿼리는 함수와 동일 하다.