오늘은 이전, 5장에 이어 6장을 정리해보고자 한다.
6장에서는 이전에 나왔던 메시지에 대한 내용과 인터페이스 관련된 주제로서 이야기함을 알 수 있었다.
한번 하나씩 살펴보도록해보자!
두 객체 사이의 협력 관계를 설명하기 위해 사용하는 전통적인 메타포이다.
클라이언트
서버
협력은 클라이언트가 서버의 서비스를 요청하는 단방향 상호작용이다.
위 예제를 통해 협력관계를 파악해보도록 하자
Screening 객체는 클라이언트 , Movie는 서버로 볼수있다.
Screening 객체는 Movie에게 가격을 계산하라는 요청을 보내고 Movie는 가격 계산 서비스를 제공해줌으로써 이 메시지에 응답하게 된다.
해당 부분을 통해 알 수 있듯, 메시지는 두 객체 사이의 협력을 가능하게 해주는 매개체로 볼 수 있다.
메시지
클라이언트 - 서버 모델 관점에서 전송자는 클라이언트, 수신자는 서버라고 부르기도 한다.
메시지는 오퍼레이션명 (operation name)과 인자(argument)로 구성되며 메시지 전송은 여기에 메시지 수신자를 추가한 것이다.
다음은 각 언어별 메시지 전송 표기법을 나타낸 그림이다.
메시지를 수신했을 때 실제로 어떤 코드가 실행되는지는 메시지 수신자의 실제 타입이 무엇인가에 달려있다.
메시지를 수신했을 때 실제로 실행되는 함수 또는 프로시저를 메서드라고 한다.
여기서 중요한건 코드 상에서 동일한 이름이 변수에게 동일한 메시지를 전송하더라도 객체의 타입에 따라 실행되는 메서드가 달리질 수 있다는 것이다.
전통적인 방식의 함수 호출은 컴파일과 런타임에 실행되는 함수가 동일하지만, 객체는 메시지와 메서드 두 가지의 서로 다른 개념을 런타임에 연결해야 하기에 컴파일 시점과 런타임의 의미가 달라질 수 있다.
실행 시점에 메시지와 메서드 ( 런타임 시점 )를 바인딩하는 메커니즘 ( 동적 바인딩 ) 은 두 객체 사이의 결합도를 낮춤으로써 유연하고 확장 가능한 코드를 작성할 수 있게 만든다.
객체는 안과 밖을 구분하는 뚜렷한 경계를 가진다.
외부에서 볼 때 객체의 안쪽은 검은 장막으로 가려진 미지의 영역 즉, 외부에서는 안을 확인할 수 없다.
외부의 객체는 오직 객체가 공개하는 메시지를 통해서만 객체와 상호작용할 수 있다.
객체가 의사소통을 위해 외부에 공개하는 메시지의 집합을 퍼블릭 인터페이스라고 한다.
퍼블릭 인터페이스에 포함된 메시지를 오퍼레이션이라고 한다.
시그니처는 오퍼레이션의 이름과 파라미터 목록을 합쳐 부르는 용어
위 그림은 각 사이의 관계에 대해 이야기를 하고 있다.
프로그래밍 언어의 관점에서 객체가 다른 객체에게 메시지를 전송하면 런타임 시스템은 메시지 전송을 오퍼레이션 호출로 해석하고 메시지를 수신한 객체의 실제 타입을 기반으로 적절한 메서드를 찾아 실행한다.
퍼블릭 인터페이스와 메시지의 관점에서 보면 '메서드 호출' 보다는 '오퍼레이션 호출'이라는 단어 선택이 더 적절하다.
시그니처
오퍼레이션 ( or 메서드 )의 이름과 파라미터 목록을 합쳐 시그니처라고 부른다.
오퍼레이션은 실행 코드 없이 시그니처만을 정의한 것이고 메서드는 이 시그니처에 구현을 더한 것이다.
일반적으로 메시지를 수신하면 오퍼레이션의 시그니처와 동일한 메서드가 실행된다.
이제, 각 용어들에 대한 정리를 다시 한번 해보자
객체의 퍼블릭 인터페이스가 객체의 품질을 결정하기 때문에 결국 메시지가 객체의 품질을 결정한다고 할 수 있다.
좋은 인터페이스는 최소한의 인터페이스와 추상적인 인터페이스라는 조건을 만족해야 한다.
디미터 법칙 ( Law Of Demeter )
낯선 자에게 이야기하지 마라 + 인접한 이웃하고만 말하라
무슨 이야기일까?
해당 객체의 내부 그 안에 있는 내부의 객체와 이야기하는 것이 아닌 단순 A, B 객체와 소통하라 즉, getter를 남용하지 마라 라는 의미로 나는 들렸다.
해당 부분은 다음과 같은 내용을 통해 정답이 아닐까라는 생각이 들었다.
만약, 자바같이 도트 (.)를 이용해 메시지 전송을 표현하는 언어라면 오직 하나의 도트만을 사용하라
TDA ( Tell Don't Ask ) 기법은 디미터 법칙을 준수하는 협력을 만들기 위한 스타일을 제시한 기법임을 다시 한번 확인이 가능했다.
묻지 말고 시켜라의 원칙은 이전 포스팅에서도 많이 다루었기에 스킵!
해당 인터페이스가 어떠한 내용인지 의도를 명확하게 들어내야 한다.
클라이언트가 객체에게 무엇을 원하는지 명확하게 표현이 가능해야 한다.
의도를 드러내는 인터페이스 원칙은 객체의 퍼블릭 인터페이스에 어떤 이름이 드러나야 하는지에 대한 지침을 제공함으로써 코드의 목적을 명확하게 커뮤니케이션할 수 있게 해 준다.
디미터의 법칙과 묻지 말고 시켜라 스타일은 객체의 퍼블릭 인터페이스를 깔끔하고 유연하게 만들 수 있는 훌륭한 설계 원칙이지만 절대적인 법칙은 아니다.
즉, 위 내용이 전부 정답은 아니다 라는걸 이야기하는 의미라고 나는 생각이 들었다.
축약한다면 여러 개의 도트를 사용한다고 하더라도 객체의 내부 구조를 노출하고 있지 않는다면? 이는 원칙을 어긴 것이 아니다. 즉, 내부 객체 구조를 노출하지 않는 것이 나는 핵심이라는 생각이 들었다.
명령 - 쿼리 분리 원칙은 퍼블릭 인터페이스에 오퍼레이션을 정의할 때 참고할 수 있는 지침을 제공해준다.
어떤 절차를 묶어 호출 가능하도록 이름을 부여한 기능 모듈을 루틴(Routine)이라고 한다.
루틴은 다시 프로시져(Procedure)와 함수(Function)으로 구분할 수 있다.
프러시저와 함수를 혼용해서 사용하는 경우가 많은데 명확하게 구분해야 한다.
프러시저
함수
프러시저는 부수효과를 발생시킬 수 있지만 값을 반환할 수 없다.
함수는 값을 반환할 수 있지만 부수효과를 발생시킬 수 없다.
명령(Command)과쿼리(Query)는 객체의 인터페이스 측면에서 프로시저와 함수를 부르는 또 다른 이름이다.
명령 - 쿼리 분리 원칙의 요지는 오퍼레이션은 부수효과를 발생시키는 명령이거나 부수효과를 발생시키지 않는 쿼리 중 하나여야 한다는 것이다.
이전, 내용에 나는 실무가 이론보다 우선이다라는 말이 기억이 났다.
이전 중고등학교 당시 때처럼 정해진 답들이 있고 이 답을 해나가는 것이 아닌 학문 자체는 정답이 따로 존재하지 않다고 생각이 들었다.
즉, 실무를 통해 해당 내용에 대해 이해하고 책을 접할 때와 모르는 상태에서 책을 접하였을 때 어느 정도의 거를 내용과 좋은 내용에 대한 부분이 명확하게 갈리는 경험을 할 것이다라는 이야기를 접한 적이 있었다.
맞는 말이라고 나는 생각이 들었다.
해당 내용 중 정답은 아니다는 이야기가 있는 것처럼 모든 이론들이 다 어쩌면 맞는 이야기가 아닐 가능성도 있다.
공부를 하더라도 이러한 부분들에 대해 깨어진 눈을 가진 사람이 될 수 있도록 더욱 노력해야겠다는 생각이 들었다.
[BOOK: 오브젝트 10장] 상속과 코드 재사용 (0) | 2022.11.18 |
---|---|
[BOOK: 오브젝트 7장] 객체 분해 (0) | 2022.11.11 |
[BOOK: 오브젝트 5장] 책임 할당하기 (0) | 2022.11.05 |
[BOOK : 오브젝트 4장] 설계 품질과 트레이드 오프 (0) | 2022.10.30 |
[BOOK : 3장] 역할, 책임, 협력 (2) | 2022.10.27 |