Community

오브젝트 6장 메시지와 인터페이스

# 들어가기 - 훌륭한 객체지향 코드를 얻기 위해서는 클래스가 아니라 객체가 수행하는 책임에 초점을 맞춰야 한다. - 책임은 객체가 수신할 수 있는 메시지의 기반이 된다. - 객체가 수신하는 메시지들이 객체의 퍼블릭 인터페이스를 구성한다. - 이번 장에서는 유연하고 재사용 가능한 퍼블릭 인터페이스를 만드는데 도움이 되는 설계 원칙과 기법을 살펴본다. ### 01 협력과 메시지 - 협력은 어떤 객체가 다른 객체에게 무언가를 요청할 때 시작된다. - 두 객체사이의 협력관계를 위해 사용하는 전통적인 메타포는 클라이언트 - 서버 모델이다. - 메시지(message)는 객체들이 협력 하기 위해 사용할 수 있는 유일한 소통 수단이다. - 메시지는 오퍼레이션명과 인자로 구성되며, 메시지 전송은 여기에 수신자를 추가한 것이다. - 메시지를 수신했을 때 실제로 수행되는 함수 또는 프로시저를 메서드라고 부른다. - 런타임에는 객체의 타입이 달라질 수 있어서, 코드상으로는 동일한 이름의 변수에 동일한 메시지를 전송하더라도 실행되는 메서드가 달라질 수 있다. - 객체가 외부에 공개하는 메시지의 집합을 퍼블릭 인터페이스라고 한다. - 퍼블릭 인터페이스에 포함된 메시지를 오퍼레이션이라고 부른다. - 오퍼레이션은 수행가능한 행동에 대한 추상화 - 인터페이스에 정의된 요소는 오퍼레이션이다. - 오퍼레이션의 이름과 파라미터 목록을 합쳐 시그니처라고 부른다. - 하나의 오퍼레이션에 다양한 메서드를 구현하면 다형성을 사용할 수 있다. ### 02 인터페이스와 설계 품질 - 좋은 인터페이스는 최소한의 인터페이스와 추상적인 인터페이스라는 조건을 만족해야한다. - 최소한의 인터페이스 - 꼭 필요한 오퍼레이션을 인터페이스에 포함한다. - 추상적인 인터페이스는 어떻게가 아닌 무엇을 하는지를 표현한다. - 퍼블릭 인터페이스의 품질에 영향을 미치는 원칙과 기법 - 디미터 법칙 - 묻지말고 시켜라 - 의도를 드러내는 인터페이스 - 명령 - 쿼리 분리 디미터 법칙 - 객체의 내부 구조에 강하게 결합되지 않도록 협력 경로를 제한하라 - 낯선자에게 말하지 말라 - 인접한 이웃하고만 말하라 - Object-Oriented Programming: An Objective Sense of Style에서 처음소개. 해당 책의 저자들이 디미터라는 프로젝트를 진행중. 객체의 협력경로를 제한하면 결합도를 효과적으로 낮출 수 있다는 사실을 발견 - 특정한 조건을 만족하는 대상에게만 메시지를 전송하도록 프로그래밍 - 모든 클래스 C와 C에 구현된 모든 메서드 M에 대해서, M이 메시지를 전송할 수 있는 모든 객체는 다음과 같은 클래스의 인스턴스여야 한다. - M의 인자로 전달된 클래스 - C의 인스턴스 변수의 클래스 - 위 설명이 어렵다면 다음의 조건으로 확인 - this 객체 - 메서드의 매개변수 - this의 속성 - this의 속성인 컬렉션의 요소 - 메서드 내에서 생성된 지역 객체 - 디미터 법칙을 따르면 부끄럼 타는 코드를 작성할 수 있다. - 부끄럼 타는 코드 : 다른객체에게 불필요한 것을 보여주지 않음. 다른 객체에 의존하지 않음 - 기차 충돌(getter들이 기차처럼 연결된 코드)은 대표적인 디미터 법칙 위반이다. 다음과 같은 코드를 말함 `screening.getMovie().getDiscountCondition()` - 무비판적으로 디미터 법칙을 수용하면 객체의 응집도가 낮아질 수 있다. 묻지 말고 시켜라 (Tell, Don't Ask) - 절차적인 코드는 정보를 얻은 후에 결정한다. 객체지향 코드는 객체에게 그것을 하도록 시킨다. - 객체의 정보를 이용하는 행동을 외부가 아닌 내부에 위치시켜서 정보와 행동을 동일한 클래스에 두게 됨. - 내부의 상태를 이용해 어떤 결정을 내리는 로직이 외부에 존재한다면 해당객체가 책임져야하는 행동이 외부로 누수된 것이다. - 단순하게 묻지 않고 시킨다고 해서 모든 문제가 해결되지는 않음. 인터페이스는 개체가 어떻게 하는지가 아닌 무엇을 하는지를 서술해야한다. 의도를 드러내는 인터페이스 - 메서드 이름을 짓는 두가지 방법 - 어떻게 하는지 명시 - 무엇을 하는지 명시 - 무엇을 하는지 드러내는 이름이 유연한 코드를 만들기 편하다. - 무엇을 하느냐에 따라 메서드의 이름을 짓는 패턴을 `의도를 드러내는 선택자` 라고 부른다. - 켄트백은 메서드에 의도를 드러낼 수 있는 이름을 붙이기 위해 다음과 같이 생각해볼 것을 조언 > 매우 다른 두번째 구현을 상상하라. 그리고 해당 메서드에 동일한 이름을 붙인다고 상상해보라. 그렇게 하면 아마도 그 순간에 여러분이 할 수 있는 한 가장 추상적인 이름을 메서드에 붙일 것이다. - 에서는 `의도를 드러내는 인터페이스` 를 제시 - 수행 방법에 관해서는 언급하지 말고 결과와 목적만을 포함하도록 클래스와 오퍼레이션의 이름을 부여하라. ### 03 원칙의 함정 - 디미터 법칙과 묻지 말고 시켜라는 훌륭한 설계원칙이지만, 절대적인 원칙은 아니다. - 소프트웨어 설계에 법칙이란 존재하지 않는다. 디미터 법칙은 하나의 닷(.)을 강제하는 규칙이 아니다. - 자바의 IntStream을 사용한 코드는 기차 충돌을 야기하므로 디미터 법칙 위반이라고 하는 사람들이 있으나, 해당 코드는 다른 인스턴스를 참조하지 않으므로 결합도가 증가하지 않는다. 결합도와 응집도의 충돌 - 어떤 객체의 상태를 물어본 후 반환된 상태를 기반으로 결정을 내리고 그에따라 객체의 상태를 변경하는 코드는 묻지 말고 시켜라 스타일로 변경해야한다. (Theater의 enter메서드) - 디미터 법칙의 위반 여부는 대상이 객체인지, 자료구조인지에 달려있다. - 객체는 내부구조를 숨겨야하므로 디미터 법칙을 따르는 것이 좋지만, 자료구조라면 내부를 노출해야하므로 디미터 법칙을 따를 필요가 없다. - 원칙을 맹신하지 말라. ### 04 명령-쿼리 분리 원칙 - 프로시저와 함수의 차이점 - 프로시저는 정해진 절차에 따라 내부의 상태를 변경하는 루틴의 종류이다. - 함수는 어떠한 값을 계산해서 반환하는 루틴의 한 종류이다. - 프로시저는 부수효과를 발생시키지만, 값을 반환 하지 않는다. - 함수는 값을 반환하지만, 부수효과를 발생시키지 않는다. - 명령(Command)과 쿼리(Query)는 객체의 인터페이스 측면에서 프로시저와 함수를 부르는 또 다른 이름이다. - 객체의 상태를 변경하는 명령은 반환값을 가질 수 없다. - 객체의 정보를 반환하는 쿼리는 상태를 변경할 수 없다. - 기계로서의 메타포 - 동그란 버튼은 쿼리이고, 네모난 버튼은 명령이다. (empty와 search의 위치가 바뀐것 같다.) - 명령과 쿼리를 섞어서 사용하면 실행결과를 예측하기가 어려워진다. 책임에 초점을 맞춰라 - 메시지를 먼저 선택하고 해당 메시지를 처리할 객체를 선택하라. - 객체 구현 이전에 객체사이의 협력에 초점을 맞추고 협력방식을 단순하고 유연하게 만들자. - 책임 주도 설계를 하자. - 버트란드 마이어는 계약에 의한 설계 개념을 제안했다. 오브젝트 1장 https://careerly.co.kr/comments/92380 오브젝트 2장 https://careerly.co.kr/comments/92467 오브젝트 3장 https://careerly.co.kr/comments/92725 오브젝트 4장 https://careerly.co.kr/comments/93990 오브젝트 5장 https://careerly.co.kr/comments/96255

알림

알림이 없습니다