본문 바로가기
책/오브젝트

06. 메시지와 인터페이스

by 오오오오니 2025. 3. 17.

06. 메시지와 인터페이스

비어 있음
2024년 4월 15일

협력과 메시지

객체는 협력에 참여하는 동안 클라이언트와 서버 역할을 동시에 수행하는 것이 일반적이다.
객체가 독립적으로 수행할 수 있는 것보다 더 큰 책임을 수행하기 위해서는 다른 객체와 협력해야 한다.
메시지 : 오퍼레이션명 + 인자
전통적인 방식의 함수 호출과 프로시저 호출은 다르다.
전통적인 방식 : 어떤 코드가 실행될지를 정확하게 알고 있는 상황에서 함수 호출이나 프로시저 호출 구문을 작성한다. 코드의 의미가 컴파일 시점과 실행 시점에 동일하다는 것
객체는 메시지와 메서드라는 두 가지 서로 다른 개념을 실행 시점에 연결해야 하기 때문에 컴파일 시점과 실행 시점의 의미가 달라질 수 있다.
실행 시점에 메시지와 메서드를 바인딩하는 메커니즘은 두 객체 사이의 결합도를 낮춤으로써 유연하고 확장 가능한 코드를 작성할 수 있다.
객체가 수신할 수 있는 메시지가 객체의 퍼블릭 인터페이스가 객체의 품질을 결정하기 때문에 결국 메시지가 객체의 품질을 결정한다.

인터페이스와 설계 품질

책임 주도 설계 방법을 따르면 추상적인 인터페이스를 설계할 수 있다.
메시지를 먼저 선택함으로써 협력과는 무관한 오퍼레이션이 인터페이스에 스며드는 것을 방지한다.

디미터 법칙

객체의 내부 구조에 강하게 결합되지 않도록 협력 경로를 제한하라는 것이다.
협력 경로를 제한하면 결합도를 효과적으로 낮출 수 있다.
M의 인자로 전달된 클래스
C의 인스턴스 변수의 클래스
불필요한 어떤 것도 다른 객체에게 보여주지 않으며 (⇒ 캡슐화) 다른 객체의 구현에 의존하지 않는 코드를 작성할 수 있다.
하지만 무조건 적용하면 퍼블릭 인터페이스 관점에서 객체의 응집도가 낮아질 수도 있다.

묻지 말고 시켜라

:디미터 법칙의 스타일의 메시지 작성을 장려하는 원칙을 가리키는 용어
객체의 상태에 대해 묻지 말고 원하는 것을 시킨다.
객체의 정보를 이용하는 행동을 객체의 외부가 아닌 내부에 위치시키기 때문에 자연스럽게 정보와 행동을 동일한 클래스 안에 두게 된다.
내부의 상태를 묻는 오퍼레이션을 인터페이스에 포함시키고 있다면 더 나은 방법을 없었는지 고민해봐라.
이 원칙은 훌륭한 인터페이스를 제공하기 위해 포함해야 하는 오퍼레이션에 대한 힌트를 제공한다.

의도를 드러내는 인터페이스

메서드 명명법 - 켄트 백
메시지가 작업을 어떻게 수행하는지를 나타내도록 짓기
메서드 구현 방법이 드러나므로 좋지 않음, 캡슐화 위반
‘어떻게’가 아니라 ‘무엇’을 하는지를 드러내게 하기
코드를 읽기 쉽게 하고 유연하게 함.
클라이언트의 관점에서 동일한 작업을 수행하는 메서드들을 하나의 타입 계층으로 묶을 수 있는 가능성이 커진다. → Intention Revealing Selector

원칙의 함정

소프트웨어 설계에 법칙이란 존재하지 않는다. 법칙에는 예외가 없지만 원칙에는 예외가 넘쳐난다.
초보자는 원칙을 맹목적으로 추종한다. 심지어 적용하려는 원칙들이 서로 충돌하는 경우에도 원칙에 정당성을 부여하고 억지로 끼워 맞추려고 노력한다.

결합도와 응집도의 충돌

클래스는 하나의 변경 원인만을 가져야 한다. 책임들이 함께 뭉쳐있는 클래스는 작은 변경으로도 쉽게 무너진다. 따라서 디미터 법칙과 묻지말고 시켜라 원칙을 무작성 따르면 애플리케이션은 응집도가 낮은 객체로 넘쳐날 것이다.
할인 여부를 판단하는 코드를 어디에 두어야 할까?
Screening 에 두면 Screening 이 기간에 따른 할인 조건을 판단하는 책임을 안게 된다.
Screening 이 담당하는 본질적인 책임은 영화를 예매하는 것이며 이렇게 되면 객체의 응집도가 낮아진다.
PeriodCondition 은 할인 조건을 판단하는 책임이 본질적이다.
따라서 Screening 의 캡술화를 향상시키는 것보다 Screening 의 응집도를 높이고 ScreeningPeriodCondition 사이의 결합도를 낮추는 것이 전체적인 관점에서 더 좋은 방법이다.
설계는 트레이드오프의 산물이다. 소프트웨어 설계에 존재하는 몇 안되는 법칙 중 하나는 “경우에 따라 다르다”라는 사실을 명심하라.

명령-쿼리 분리 원칙

명령과 쿼리를 분리하기 위해서는 다음의 두가지 규칙을 준수해야 한다.
객체의 상태를 변경하는 명령은 반환값을 가질 수 없다.
객체의 정보를 반환하는 쿼리는 상태를 변경할 수 없다.
이런 스타일을 사용하면 객체의 캡슐화와 다양한 문맥에의 재사용을 보장할 수 있다.
명령과 쿼리를 섞으면 실행 결과를 예측하기가 어려워질 수 있다.
겉으로 보기엔 쿼리처럼 보이지만 내부적으로 부수효과를 가지는 메서드는 이해하기 어렵고, 잘못 사용하기 쉬우며, 버그를 양산하는 경향이 있다.

책임에 초점을 맞춰라

설명한 모든 방식의 중심에는 객체가 수행할 책임이 위치한다.
훌륭한 메시지를 얻기 위한 출발점은 책임 주도 설계 원칙을 따르는 것이다.

느낀점

디미터 법칙에 대해 자세히 알 수 있어서 좋았다. 클린코드에서 봤을 때 보다 이해가 잘 갔다.
또한 디미터 법칙을 맹신하면 안되는 이유도 알 수 있어서 좋았다.
소프트웨어에서는 법칙이 없고 원칙이 있으며 원칙에는 예외가 넘쳐난다라는 말이 인상깊었다.
다양한 책을 읽으면서 공부하고 있지만 해당 책을 읽을때마다 그 책이 말하고자하는 방식에 더 치중되는 것 같다. 이 책이 말하는 것처럼 원칙을 맹목적으로 따르지 않으려고 노력해야 할 것 같다.
책임을 중심으로 설계를 하는 것에 집중하고 트레이드 오프를 이해하면 도움이 될 것 같다.

' > 오브젝트' 카테고리의 다른 글

08. 의존성 관리하기  (0) 2025.03.17
07. 객체 분해  (0) 2025.03.17
05. 책임 할당하기  (0) 2025.03.17
04. 설계 품질과 트레이드 오프  (0) 2025.03.17
03. 역할, 책임, 협력  (0) 2025.03.17