▼ What ?
다섯 번째 챕터인 "책임과 메시지"에서 중요한 키워드는 '자율적인 객체'과 '메시지'인 것 같다. 왜 객체지향 시스템이 다른 패터다임보다 더 뛰어나다고 평가받는지, 그리고 그러한 객체지향 시스템의 이점을 최대화시키기 위해서 반드시 알고 있어야 할 첫 번째 개념인 '메시지'와 객체의 내부와 외부의 분리로 탄생한 '자율적인 객체'에 대해 생각해보는 시간을 가졌다.
▼ Summory & Comment
이 챕터를 읽고 나서 기억에 남는 말 !
어떤 것도 동시에 객체의 내부와 외부에 포함될 수 없다.
- 이번 챕터에서 '메시지'가 왜 중요하고 책임을 왜 '자율적'으로 설계해야 하며
저자가 거듭해서 강조한 '자율적인 객체'가 무엇인지를 한 문장으로 표현해낸 것 같아 기억에 남는다.
사실 이번 챕터를 읽으면서 내용들이 상당히? 추상적이라 읽으면서 집중력이 자주 흐트려졌던 것 같다.
(시험 기간 때문에 스터디를 지연시켰다가 다시 읽어서 그런가...)
그래서 해당 내용을 정확히 이해하고 넘어가고 있는 것인지를 스스로 확인하기가 힘들었는데,
이 추상적인 구절이 이번 챕터를 제대로 이해했는지 스스로 확인해볼 수 있는 구절이라는 생각이 들었다!
자율적인 책임
- 자율적인 객체가 가능하기 위해선, 즉 객체가 자율적으로 책임을 수행하기 위해선 객체에게 할당되는 책임부터 자율적이어야 가능하다.
- 🤴🏻왕 ⇢ "증언하라!" ⇢ 💂🏻♀️모자 장수
➙ "모자 장수"는 "증언"이라는 책임을 자율적인 절차를 통해 수행 가능하다 ! - 🤴🏻왕 ⇢
"목격했던 장면을 떠올려라!"
"떠오르는 기억을 시간 순서대로 재구성하라!"
"간결하게 말하라!"
⇢ 💂🏻♀️모자 장수
➙ 이처럼 자율적이지 못한 책임을 할당하게 되면, "모자 장수"는 "증언"을 위한 과정을 수행하는 데 있어서 지나친 제약을 받게 된다.
- 🤴🏻왕 ⇢ "증언하라!" ⇢ 💂🏻♀️모자 장수
- 하지만, 자율적인 책임을 할당해야 한다고 해서 아래처럼 너무 포괄적이고 추상적인 책임을 선택해도 문제가 생긴다.
ex) 🤴🏻왕 ⇢ "설명하라!" ⇢ 💂🏻♀️ 모자 장수
- 어떤 책임이 자율적인지는 설계 중인 협력이 무엇인지에 따라 달라진다.
➙ "이상한 나라의 엘리스"에서 "재판"이라는 협력 안에선 "증언하라!"가 적절한 수준의 책임이지만,
다른 협력 속에선 "증언하라!"보다 "설명하라!"라는 책임이 더 적절할 수 있다는 것이다 !
- 자율적인 책임을 설계할 땐 어떤 식으로?
'어떻게(HOW)'가 아닌 '무엇(WHAT)'을 해야 하는지를 생각하자 !
책임을 자극하는 '메시지'
- '메시지'는 '메시지 이름'과 '(인자)' 두 가지 부분으로 구성되어 있다.
ex) 증언하라(어제, 왕국)
'메시지 전송'은 '수신자'와 '메시지'의 조합이다.
ex) 모자장수.증언하라(어제, 왕국)
➙ 메시지 전송 문법은 언어마다 달라질 수 있기 때문에, 메시지 전송을 구성하는 요소를 기억하자 !
- 메시지는 객체들이 서로 협력하기 위해 사용할 수 있는 유일한 의사소통 수단이다.
➙ "모자 장수"가 "왕"에게 받은 두 가지 메시지는 "모자 장수"가 수행해야 할 책임의 모양(범위?)을 결정한다 !
("증인석에 입장하라!", "증언하라!")
- "왕"은 "모자 장수"가 메시지(what)를 '어떻게(how)' 처리할 것인지는 알 필요가 없다 !
➙ 자연스럽게 객체의 '외부'와 '내부'가 분리 !
메시지는 '무엇(what)'을 수행할지를 명시하고, '어떻게(how)' 수행할지는 메시지 수신자가 결정할 일이다.
- "모자 장수"가 수신한 '메시지'를 처리하기 위해 내부적으로 선택하는 방법이 바로 '메서드'이다.
- 메시지와 메서드와 관계는 다형성과도 밀접하게 얽혀있다.
➙ "증언하라!"라는 동일한 메시지는 '수신자(모자 장수, 요리사, 앨리스)'에 따라 다른 방식(메서드)으로 처리되지만, '송신자(왕)'의 입장에선 어차피 같은 결과를 받게 되는데, 이러한 특성을 바로 다형성이라 하는 것이다 !
➙ 이러한 다형성이 '메시지 송신자'의 관점에서 동일한 역할을 수행하는 다양한 타입의 객체와 협력할 수 있게 해준다 !
(다형성은 곧 동일한 역할을 수행할 수 있는 객체들 사이의 대체 가능성을 의미한다.)
이러한 다형성은 '송신자'와 '수신자' 간의 객체 타입에 대한 결합도를 메시지에 대한 결합도로 낮춤으로써 달성된다.
- 설계의 품질은 흔히 아는 클래스나 메서드가 아닌 '메시지'에 따라 달라진다.
➙ 즉, 훌륭한 메시지가 설계를 유연하고 확장 가능하며 재사용 가능하게 한다 !
객체가 메시지를 선택하는 것이 아닌 메시지가 객체를 선택하게, 즉 메시지를 중심으로 협력을 설계해야 한다.
* '협력'이라는 문맥에서 벗어나 독립된 객체를 고민하는 것 = 클래스에 초점을 맞추는 것
➙ 메시지를 중심으로 협력을 설계하는 방식이 바로 앞선 챕터들에서 다뤘던 "책임-주도 설계" 방식이다.
🔻 What/Who 사이클
(객체 사이의 협력을 설계하는 과정을 의미한다.)
- '어떤 행위(what)'를 수행할 것인지를 먼저 결정.
- '누가(who)' 그 행위(메시지)를 수행할 것인지를 결정.
➙ 즉, '협력'이라는 문맥 속에서 필요한 메시지를 먼저 결정한 후에 해당 메시지를 수신하기에 적합한 객체를 선택하도록 설계하는 것이다.
- "묻지 말고 시켜라" 스타일
➙ 메시지가 결정되기 전까진 어떤 객체가 해당 메시지를 수신할지 모른다.
➙ 즉, 메시지 송신자는 메시지 수신할 객체의 내부 상태를 알 수 없기 때문에 다른 객체와 상관없이 오직 자신의 상태에 기반해서 '자율적'으로 행동하게 된다.
➙ 자연스럽게 객체를 자율적으로 만들면서 캡슐화도 보장하게 되고 객체 사이의 결합도도 낮춰줌으로써 설계를 유연하게 만들어준다 !
메시지는 '어떻게' 해야 하는지를 지시하는 것이 아니라 '무엇'을 해야 하는지를 요청하기 위한 것 !
➙ '어떻게(how)'에서 '무엇(what)'으로 전환하게 되면서 객체의 인터페이스 크기⇣
➙ 외부에서 해당 객체에게 의존해야 하는 부분⇣
➙ 객체 사이의 결합도가 낮아지면서 유연한 설계가 가능해진다.
자율적인 객체의 근원, '인터페이스'
- 인터페이스의 세 가지 장점
(자동차와 운전자의 관계를 함께 생각해보면 이해하기 쉽다)
- 인터페이스의 사용법만 알고 있으면 대상의 내부 구조나 동작 방법을 몰라도 상호작용 가능 !
➙ 자동차의 내부를 몰라도 운전법만 알면 된다. - 인터페이스가 변경되지 않고 단순히 내부 구성이나 작동 방식이 변경되는 것은 인터페이스 사용자에게 아무런 영향 X
➙ 자동차 엔진 같은 것은 교체되도 운전을 새로 배울 필요 X
(자동차가 제공하는 핸들, 변속기, 엑셀, 브레이크 등이 인터페이스 개념이다.) - 인터페이스가 동일하기만 하면 어떤 대상과도 상호작용 가능 !
➙ 어떤 자동차라도 운전은 가능하다.
- 인터페이스의 사용법만 알고 있으면 대상의 내부 구조나 동작 방법을 몰라도 상호작용 가능 !
- 이전에 객체끼리 상호작용하기 위한 유일한 방법은 '메시지'라 했듯이, 결국 객체가 어떤 메시지를 수신할 수 있는지에 따라 해당 객체의 인터페이스의 모양이 결정된다 !
- 그럼 모든 인터페이스는 외부에서 접근 가능한 것인가 ?
➙ No, 객체의 내부에서만 접근 가능한 사적인 인터페이스와 외부에 공개된 공용 인터페이스로 구분된다 !
➙ 단, 모든 인터페이스는 항상 메시지 전송을 통해서만 접근 가능하다는 것을 기억하자 !
(자기 자신과의 상호작용도 예외 X)
- 외부에서 전송 가능한 '메시지 집합'인 공용 인터페이스
➙ "왕"과 "모자 장수"가 협력할 수 있는 유일한 방법은 "증언하라"라는 메시지를 전송하는 것이었다.
➙ "왕"과 "모자 장수" 사이엔 "증언하라"라는 메시지를 송신하고 수신할 수 있는 '공용 인터페이스'가 존재하는 것 !
➙ 즉, 공용 인터페이스는 객체의 외부와 내부가 명확하게 분리되도록 도와준다 !
- 객체지향적인 사고 방식에서 중요한 세 가지 원칙
- 좀 더 추상적인 인터페이스
➙ "목격했던 장면을 떠올려라!", "간결하게 말하라!" ➟ "증언하라!" - 최소 인터페이스
➙ 메시지를 먼저 결정하고 객체를 나중에 선택하는 '책임-주도 설계' 방법을 따르면 자연스럽게 달성 가능하다. - 인터페이스와 구현의 분리 원칙(separation of interface and implementation)
- 좀 더 추상적인 인터페이스
- 구현(implementation) ?
: 객체지향 세계에서 내부 구조와 작동 방식을 가리키는 고유의 용어.
➙ 객체를 구성하지만 공용 인터페이스에 포함되지 않는 모든 것이 '구현'에 포함된다.
(객체의 상태, 메서드의 구현부 같은 것들이 객체의 구현 부분이다.)
- 객체 설계의 핵심
: 객체를 두 개의 분리된 요소로 분할하여 설계하는 것 !
➙ 내부에 숨겨지는 '구현' (~ 캡슐화) / 외부에 공개되는 '인터페이스'
변경에 대해 무방한 안전 지대가 '구현(implementation)'이고,
변경했을 경우 외부에 영향을 미치는 위험 지대가 '인터페이스(interface)'인 것.
➙ 쉽게 말해서, 변경될 만한 부분은 내부에 꽁꽁 숨겨 놓는다는 것이다 !
변경에 대한 '안전 지대'와 '위험 지대'를 명확하게 구분한다면 ?
➙ 메시지를 처리하는 메서드를 자유롭게 변경해도 외부에 영향을 주지 않기 때문에 객체의 자율성이 보장된다 !
🔻 데이터 캡슐화(Data encapsulation)
➙ 객체는 '상태'와 '행위'를 하나의 단위로 묶는 자율적인 실체라는 관점에서,
데이터 캡슐화는 '인터페이스'와 '구현'을 분리하기 위한 전제 조건이다.
➙ 데이터 캡슐화가 이루어진 이후에 외부에서 반드시 접근해야만 하는 행위만을 골라 '공용 인터페이스'를 통해 노출하는 것이다 !
🔻 사적인 비밀의 캡슐화
➙ 변경이 빈번하게 일어나는 불안정한 비밀(구현과 관련된 세부 사항)을 안정적인 '공용 인터페이스' 뒤로 숨기는 것을 말한다.
(외부의 객체 역시 공용 인터페이스에만 의존해야 하고 구현 세부 사항에 대해선 직접적으로 의존 X)
'자율적인 객체'란, 객체의 내부와 외부가 엄격하게 분리된 것이며
이러한 객체들로 구성된 협력 공동체가 '객체지향'인 것이다 !
자율적인 책임과 협력 간의 관계
- 첫째, 자율적인 책임은 협력을 단순하게 만든다.
- 둘째, 자율적인 책임은 모자 장수의 외부와 내부를 명확하게 분리한다.
- 셋째, 책임이 자율적일 경우 책임을 수행하는 내부적인 방법을 변경하더라도 외부에 영향을 미치지 않는다.
- 넷째, 자율적인 책임은 협력의 대상을 다양하게 선택할 수 있는 유연성을 제공한다.
- 다섯째, 객체가 수행하는 책임들이 자율적일수록 객체의 역할을 이해하기 쉬워진다.
(모두 앞서 설명한 구절들이다.)
▼ Study
응집도는 높을수록 좋다는데, 응집도가 제대로 무엇을 의미하는걸까? (cf. 계층형 구조)
- 응집도(Cohesion)
: 하나의 모듈 내에서 구성 요소 간의 밀접한 정도
* 여기서 말하는 모듈은 하나의 클래스(class)를 의미하는 것 같다. - 응집도가 높다는 것은 하나의 모듈 내에 하나의 기능을 구현하기 위해 필요한 요소(함수, 데이터)들이 '최소한'으로 구성되어 있다는 것이고,
응집도가 낮다는 것은 모듈 내부에 서로 다른 기능을 구현하기 위한 요소들, 즉 서로 관련이 없는 요소들로 구성되어 있다는 것이다. - 최근에 공부했던 스프링의 패키지 구조인 '계층형 구조(by Layer)'의 단점 중에 도메인별 응집도가 낮다는 점을 떠올려보니 '응집도'를 이해하는 데 도움이 됐다!
➙ '계층형 구조'는 Controller, Service, Dto, Repository 등 어플리케이션에서 사용하는 계층별로 패키지를 분류하다 보니 한 패키지에 주문 처리를 담당하는 클래스도 있고 회원 정보 처리를 담당하는 클래스도 있다.
따라서, 하나의 도메인(주문)을 수정하게 되면 여러 패키지를 수정해야 하는 상황이 발생하게 되는데, 이러한 문제가 발단하게 된 원인이 도메인별 '응집도'가 낮다는 점인 것이다!
[Spring] Spring Boot Package Structure : 계층형(by Layer) vs 도메인형(by Domain)
What ? "악쓰는하마"라는 노래방 키오스크의 백엔드 서비스를 만들어보는 토이 프로젝트를 하기 전에 일단 스프링 부트의 패키지 구조에 대해 공부해보고, 계층형 구조와 도메인형 구조 중 어떤
ukym-tistory.tistory.com
이번 챕터에서 말하는 인터페이스의 개념의 범위는?
- 스터디를 하기 전까진 당연히 '자바에서의 인터페이스(interface)'라고 생각하고 읽었었다.
하지만, 저자가 말하는 "사적인 인터페이스"라는 것은 내부에서만 접근 가능하고 자주 변경되는 불안정한 인터페이스인데, 자바(java)에서의 인터페이스는 객체 내부에서 접근 불가능한 개념이라는 점에서 의문이 들었다 !
따라서, 이번 챕터에서 말하는 '인터페이스'는 자바에서의 인터페이스(interface)에 한정된 것이 아니라 메서드(Method), (Function) 같은 개념도 모두 포함하고 있는 것이라고 생각을 정리하게 되었다.
➙ 자바에서 "사적인 인터페이스"와 "공용 인터페이스"에 해당되는 개념은 아래와 같이 분류해줄 수 있을 것 같다.
- 사적인 인터페이스 = 세부 구현(implementation)
- 공용 인터페이스 = 인터페이스(interface)
Issue_1
시스템을 구현할 책임을 구현하기 위해 협력 관계를 시작할 적절한 객체를 먼저 찾아 시스템의 책임을 객체의 책임으로 할당한다. 객체가 책임을 완수하기 위해 다른 개체의 도움이 필요하다고 판단되면 도움을 요청하기 위해 어떤 메시지가 필요한지 결정한다. 메시지를 결정한 후에는 메시지를 수신하기에 적합한 객체를 선택한다.
이 과정을 "이상한 나라의 앨리스" 이야기에 비유해서 이야기해보면 좋을 것 같습니다~
(추가적으로, 메시지에 적합한 객체가 없을 땐 어떻게 해야 하는걸까요?)
- 시스템을 구현한 책임인 "재판"을 위한 협력 관계를 시작할 적절한 객체는 "왕"입니다.
➙ "재판"을 "왕"의 책임으로 할당합니다.
➙ "왕"이 자신의 책임인 "재판"을 완수하기 위해선 "하얀 토끼", "앨리스", "모자 장수" 등의 도움이 필요합니다.
➙ 예를 들어, 도움을 요청하기 위해 필요한 메시지는 "증언하라!"가 있을 것이고, 이 메시지를 수신하기에 적합한 객체로 "모자 장수"를 선택하게 됩니다. - 메시지에 적합한 객체가 없다면 메시지를 수행할 수 있는 객체를 만들어줘야 한다고 생각합니다.
Issue_2
모자 장수가 책임을 수행하기 위해 증언 방법과 순서를 자신의 의지에 따라 선택할 수 있는 자유를 누린다.
라고 되어있는데 순서가 어떤 걸 의미하나요? 증언을 설명할 방법 순서를 뜻하는 건가요?
- 증언을 하기 위한 과정 자체를 스스로 설계할 수 있다는 것 같습니다.
Issue_3
다형성은 송신자와 수신자 간의 객체 타입에 대한 결합도를 메시지에 대한 결합도로 낮춤으로써 달성된다.
전혀 이해가 되지 않는 문장입니다.
- 서로 다른 객체간의 공통된 메서드를 사용하고 있을 경우, 이를 하나의 인터페이스에 하나로 묶어서 결합도를 낮춘다는 이야기인 것 같습니다.
▼ What ?
다섯 번째 챕터인 "책임과 메시지"에서 중요한 키워드는 '자율적인 객체'과 '메시지'인 것 같다. 왜 객체지향 시스템이 다른 패터다임보다 더 뛰어나다고 평가받는지, 그리고 그러한 객체지향 시스템의 이점을 최대화시키기 위해서 반드시 알고 있어야 할 첫 번째 개념인 '메시지'와 객체의 내부와 외부의 분리로 탄생한 '자율적인 객체'에 대해 생각해보는 시간을 가졌다.
▼ Summory & Comment
이 챕터를 읽고 나서 기억에 남는 말 !
어떤 것도 동시에 객체의 내부와 외부에 포함될 수 없다.
- 이번 챕터에서 '메시지'가 왜 중요하고 책임을 왜 '자율적'으로 설계해야 하며
저자가 거듭해서 강조한 '자율적인 객체'가 무엇인지를 한 문장으로 표현해낸 것 같아 기억에 남는다.
사실 이번 챕터를 읽으면서 내용들이 상당히? 추상적이라 읽으면서 집중력이 자주 흐트려졌던 것 같다.
(시험 기간 때문에 스터디를 지연시켰다가 다시 읽어서 그런가...)
그래서 해당 내용을 정확히 이해하고 넘어가고 있는 것인지를 스스로 확인하기가 힘들었는데,
이 추상적인 구절이 이번 챕터를 제대로 이해했는지 스스로 확인해볼 수 있는 구절이라는 생각이 들었다!
자율적인 책임
- 자율적인 객체가 가능하기 위해선, 즉 객체가 자율적으로 책임을 수행하기 위해선 객체에게 할당되는 책임부터 자율적이어야 가능하다.
- 🤴🏻왕 ⇢ "증언하라!" ⇢ 💂🏻♀️모자 장수
➙ "모자 장수"는 "증언"이라는 책임을 자율적인 절차를 통해 수행 가능하다 ! - 🤴🏻왕 ⇢
"목격했던 장면을 떠올려라!"
"떠오르는 기억을 시간 순서대로 재구성하라!"
"간결하게 말하라!"
⇢ 💂🏻♀️모자 장수
➙ 이처럼 자율적이지 못한 책임을 할당하게 되면, "모자 장수"는 "증언"을 위한 과정을 수행하는 데 있어서 지나친 제약을 받게 된다.
- 🤴🏻왕 ⇢ "증언하라!" ⇢ 💂🏻♀️모자 장수
- 하지만, 자율적인 책임을 할당해야 한다고 해서 아래처럼 너무 포괄적이고 추상적인 책임을 선택해도 문제가 생긴다.
ex) 🤴🏻왕 ⇢ "설명하라!" ⇢ 💂🏻♀️ 모자 장수
- 어떤 책임이 자율적인지는 설계 중인 협력이 무엇인지에 따라 달라진다.
➙ "이상한 나라의 엘리스"에서 "재판"이라는 협력 안에선 "증언하라!"가 적절한 수준의 책임이지만,
다른 협력 속에선 "증언하라!"보다 "설명하라!"라는 책임이 더 적절할 수 있다는 것이다 !
- 자율적인 책임을 설계할 땐 어떤 식으로?
'어떻게(HOW)'가 아닌 '무엇(WHAT)'을 해야 하는지를 생각하자 !
책임을 자극하는 '메시지'
- '메시지'는 '메시지 이름'과 '(인자)' 두 가지 부분으로 구성되어 있다.
ex) 증언하라(어제, 왕국)
'메시지 전송'은 '수신자'와 '메시지'의 조합이다.
ex) 모자장수.증언하라(어제, 왕국)
➙ 메시지 전송 문법은 언어마다 달라질 수 있기 때문에, 메시지 전송을 구성하는 요소를 기억하자 !
- 메시지는 객체들이 서로 협력하기 위해 사용할 수 있는 유일한 의사소통 수단이다.
➙ "모자 장수"가 "왕"에게 받은 두 가지 메시지는 "모자 장수"가 수행해야 할 책임의 모양(범위?)을 결정한다 !
("증인석에 입장하라!", "증언하라!")
- "왕"은 "모자 장수"가 메시지(what)를 '어떻게(how)' 처리할 것인지는 알 필요가 없다 !
➙ 자연스럽게 객체의 '외부'와 '내부'가 분리 !
메시지는 '무엇(what)'을 수행할지를 명시하고, '어떻게(how)' 수행할지는 메시지 수신자가 결정할 일이다.
- "모자 장수"가 수신한 '메시지'를 처리하기 위해 내부적으로 선택하는 방법이 바로 '메서드'이다.
- 메시지와 메서드와 관계는 다형성과도 밀접하게 얽혀있다.
➙ "증언하라!"라는 동일한 메시지는 '수신자(모자 장수, 요리사, 앨리스)'에 따라 다른 방식(메서드)으로 처리되지만, '송신자(왕)'의 입장에선 어차피 같은 결과를 받게 되는데, 이러한 특성을 바로 다형성이라 하는 것이다 !
➙ 이러한 다형성이 '메시지 송신자'의 관점에서 동일한 역할을 수행하는 다양한 타입의 객체와 협력할 수 있게 해준다 !
(다형성은 곧 동일한 역할을 수행할 수 있는 객체들 사이의 대체 가능성을 의미한다.)
이러한 다형성은 '송신자'와 '수신자' 간의 객체 타입에 대한 결합도를 메시지에 대한 결합도로 낮춤으로써 달성된다.
- 설계의 품질은 흔히 아는 클래스나 메서드가 아닌 '메시지'에 따라 달라진다.
➙ 즉, 훌륭한 메시지가 설계를 유연하고 확장 가능하며 재사용 가능하게 한다 !
객체가 메시지를 선택하는 것이 아닌 메시지가 객체를 선택하게, 즉 메시지를 중심으로 협력을 설계해야 한다.
* '협력'이라는 문맥에서 벗어나 독립된 객체를 고민하는 것 = 클래스에 초점을 맞추는 것
➙ 메시지를 중심으로 협력을 설계하는 방식이 바로 앞선 챕터들에서 다뤘던 "책임-주도 설계" 방식이다.
🔻 What/Who 사이클
(객체 사이의 협력을 설계하는 과정을 의미한다.)
- '어떤 행위(what)'를 수행할 것인지를 먼저 결정.
- '누가(who)' 그 행위(메시지)를 수행할 것인지를 결정.
➙ 즉, '협력'이라는 문맥 속에서 필요한 메시지를 먼저 결정한 후에 해당 메시지를 수신하기에 적합한 객체를 선택하도록 설계하는 것이다.
- "묻지 말고 시켜라" 스타일
➙ 메시지가 결정되기 전까진 어떤 객체가 해당 메시지를 수신할지 모른다.
➙ 즉, 메시지 송신자는 메시지 수신할 객체의 내부 상태를 알 수 없기 때문에 다른 객체와 상관없이 오직 자신의 상태에 기반해서 '자율적'으로 행동하게 된다.
➙ 자연스럽게 객체를 자율적으로 만들면서 캡슐화도 보장하게 되고 객체 사이의 결합도도 낮춰줌으로써 설계를 유연하게 만들어준다 !
메시지는 '어떻게' 해야 하는지를 지시하는 것이 아니라 '무엇'을 해야 하는지를 요청하기 위한 것 !
➙ '어떻게(how)'에서 '무엇(what)'으로 전환하게 되면서 객체의 인터페이스 크기⇣
➙ 외부에서 해당 객체에게 의존해야 하는 부분⇣
➙ 객체 사이의 결합도가 낮아지면서 유연한 설계가 가능해진다.
자율적인 객체의 근원, '인터페이스'
- 인터페이스의 세 가지 장점
(자동차와 운전자의 관계를 함께 생각해보면 이해하기 쉽다)
- 인터페이스의 사용법만 알고 있으면 대상의 내부 구조나 동작 방법을 몰라도 상호작용 가능 !
➙ 자동차의 내부를 몰라도 운전법만 알면 된다. - 인터페이스가 변경되지 않고 단순히 내부 구성이나 작동 방식이 변경되는 것은 인터페이스 사용자에게 아무런 영향 X
➙ 자동차 엔진 같은 것은 교체되도 운전을 새로 배울 필요 X
(자동차가 제공하는 핸들, 변속기, 엑셀, 브레이크 등이 인터페이스 개념이다.) - 인터페이스가 동일하기만 하면 어떤 대상과도 상호작용 가능 !
➙ 어떤 자동차라도 운전은 가능하다.
- 인터페이스의 사용법만 알고 있으면 대상의 내부 구조나 동작 방법을 몰라도 상호작용 가능 !
- 이전에 객체끼리 상호작용하기 위한 유일한 방법은 '메시지'라 했듯이, 결국 객체가 어떤 메시지를 수신할 수 있는지에 따라 해당 객체의 인터페이스의 모양이 결정된다 !
- 그럼 모든 인터페이스는 외부에서 접근 가능한 것인가 ?
➙ No, 객체의 내부에서만 접근 가능한 사적인 인터페이스와 외부에 공개된 공용 인터페이스로 구분된다 !
➙ 단, 모든 인터페이스는 항상 메시지 전송을 통해서만 접근 가능하다는 것을 기억하자 !
(자기 자신과의 상호작용도 예외 X)
- 외부에서 전송 가능한 '메시지 집합'인 공용 인터페이스
➙ "왕"과 "모자 장수"가 협력할 수 있는 유일한 방법은 "증언하라"라는 메시지를 전송하는 것이었다.
➙ "왕"과 "모자 장수" 사이엔 "증언하라"라는 메시지를 송신하고 수신할 수 있는 '공용 인터페이스'가 존재하는 것 !
➙ 즉, 공용 인터페이스는 객체의 외부와 내부가 명확하게 분리되도록 도와준다 !
- 객체지향적인 사고 방식에서 중요한 세 가지 원칙
- 좀 더 추상적인 인터페이스
➙ "목격했던 장면을 떠올려라!", "간결하게 말하라!" ➟ "증언하라!" - 최소 인터페이스
➙ 메시지를 먼저 결정하고 객체를 나중에 선택하는 '책임-주도 설계' 방법을 따르면 자연스럽게 달성 가능하다. - 인터페이스와 구현의 분리 원칙(separation of interface and implementation)
- 좀 더 추상적인 인터페이스
- 구현(implementation) ?
: 객체지향 세계에서 내부 구조와 작동 방식을 가리키는 고유의 용어.
➙ 객체를 구성하지만 공용 인터페이스에 포함되지 않는 모든 것이 '구현'에 포함된다.
(객체의 상태, 메서드의 구현부 같은 것들이 객체의 구현 부분이다.)
- 객체 설계의 핵심
: 객체를 두 개의 분리된 요소로 분할하여 설계하는 것 !
➙ 내부에 숨겨지는 '구현' (~ 캡슐화) / 외부에 공개되는 '인터페이스'
변경에 대해 무방한 안전 지대가 '구현(implementation)'이고,
변경했을 경우 외부에 영향을 미치는 위험 지대가 '인터페이스(interface)'인 것.
➙ 쉽게 말해서, 변경될 만한 부분은 내부에 꽁꽁 숨겨 놓는다는 것이다 !
변경에 대한 '안전 지대'와 '위험 지대'를 명확하게 구분한다면 ?
➙ 메시지를 처리하는 메서드를 자유롭게 변경해도 외부에 영향을 주지 않기 때문에 객체의 자율성이 보장된다 !
🔻 데이터 캡슐화(Data encapsulation)
➙ 객체는 '상태'와 '행위'를 하나의 단위로 묶는 자율적인 실체라는 관점에서,
데이터 캡슐화는 '인터페이스'와 '구현'을 분리하기 위한 전제 조건이다.
➙ 데이터 캡슐화가 이루어진 이후에 외부에서 반드시 접근해야만 하는 행위만을 골라 '공용 인터페이스'를 통해 노출하는 것이다 !
🔻 사적인 비밀의 캡슐화
➙ 변경이 빈번하게 일어나는 불안정한 비밀(구현과 관련된 세부 사항)을 안정적인 '공용 인터페이스' 뒤로 숨기는 것을 말한다.
(외부의 객체 역시 공용 인터페이스에만 의존해야 하고 구현 세부 사항에 대해선 직접적으로 의존 X)
'자율적인 객체'란, 객체의 내부와 외부가 엄격하게 분리된 것이며
이러한 객체들로 구성된 협력 공동체가 '객체지향'인 것이다 !
자율적인 책임과 협력 간의 관계
- 첫째, 자율적인 책임은 협력을 단순하게 만든다.
- 둘째, 자율적인 책임은 모자 장수의 외부와 내부를 명확하게 분리한다.
- 셋째, 책임이 자율적일 경우 책임을 수행하는 내부적인 방법을 변경하더라도 외부에 영향을 미치지 않는다.
- 넷째, 자율적인 책임은 협력의 대상을 다양하게 선택할 수 있는 유연성을 제공한다.
- 다섯째, 객체가 수행하는 책임들이 자율적일수록 객체의 역할을 이해하기 쉬워진다.
(모두 앞서 설명한 구절들이다.)
▼ Study
응집도는 높을수록 좋다는데, 응집도가 제대로 무엇을 의미하는걸까? (cf. 계층형 구조)
- 응집도(Cohesion)
: 하나의 모듈 내에서 구성 요소 간의 밀접한 정도
* 여기서 말하는 모듈은 하나의 클래스(class)를 의미하는 것 같다. - 응집도가 높다는 것은 하나의 모듈 내에 하나의 기능을 구현하기 위해 필요한 요소(함수, 데이터)들이 '최소한'으로 구성되어 있다는 것이고,
응집도가 낮다는 것은 모듈 내부에 서로 다른 기능을 구현하기 위한 요소들, 즉 서로 관련이 없는 요소들로 구성되어 있다는 것이다. - 최근에 공부했던 스프링의 패키지 구조인 '계층형 구조(by Layer)'의 단점 중에 도메인별 응집도가 낮다는 점을 떠올려보니 '응집도'를 이해하는 데 도움이 됐다!
➙ '계층형 구조'는 Controller, Service, Dto, Repository 등 어플리케이션에서 사용하는 계층별로 패키지를 분류하다 보니 한 패키지에 주문 처리를 담당하는 클래스도 있고 회원 정보 처리를 담당하는 클래스도 있다.
따라서, 하나의 도메인(주문)을 수정하게 되면 여러 패키지를 수정해야 하는 상황이 발생하게 되는데, 이러한 문제가 발단하게 된 원인이 도메인별 '응집도'가 낮다는 점인 것이다!
[Spring] Spring Boot Package Structure : 계층형(by Layer) vs 도메인형(by Domain)
What ? "악쓰는하마"라는 노래방 키오스크의 백엔드 서비스를 만들어보는 토이 프로젝트를 하기 전에 일단 스프링 부트의 패키지 구조에 대해 공부해보고, 계층형 구조와 도메인형 구조 중 어떤
ukym-tistory.tistory.com
이번 챕터에서 말하는 인터페이스의 개념의 범위는?
- 스터디를 하기 전까진 당연히 '자바에서의 인터페이스(interface)'라고 생각하고 읽었었다.
하지만, 저자가 말하는 "사적인 인터페이스"라는 것은 내부에서만 접근 가능하고 자주 변경되는 불안정한 인터페이스인데, 자바(java)에서의 인터페이스는 객체 내부에서 접근 불가능한 개념이라는 점에서 의문이 들었다 !
따라서, 이번 챕터에서 말하는 '인터페이스'는 자바에서의 인터페이스(interface)에 한정된 것이 아니라 메서드(Method), (Function) 같은 개념도 모두 포함하고 있는 것이라고 생각을 정리하게 되었다.
➙ 자바에서 "사적인 인터페이스"와 "공용 인터페이스"에 해당되는 개념은 아래와 같이 분류해줄 수 있을 것 같다.
- 사적인 인터페이스 = 세부 구현(implementation)
- 공용 인터페이스 = 인터페이스(interface)
Issue_1
시스템을 구현할 책임을 구현하기 위해 협력 관계를 시작할 적절한 객체를 먼저 찾아 시스템의 책임을 객체의 책임으로 할당한다. 객체가 책임을 완수하기 위해 다른 개체의 도움이 필요하다고 판단되면 도움을 요청하기 위해 어떤 메시지가 필요한지 결정한다. 메시지를 결정한 후에는 메시지를 수신하기에 적합한 객체를 선택한다.
이 과정을 "이상한 나라의 앨리스" 이야기에 비유해서 이야기해보면 좋을 것 같습니다~
(추가적으로, 메시지에 적합한 객체가 없을 땐 어떻게 해야 하는걸까요?)
- 시스템을 구현한 책임인 "재판"을 위한 협력 관계를 시작할 적절한 객체는 "왕"입니다.
➙ "재판"을 "왕"의 책임으로 할당합니다.
➙ "왕"이 자신의 책임인 "재판"을 완수하기 위해선 "하얀 토끼", "앨리스", "모자 장수" 등의 도움이 필요합니다.
➙ 예를 들어, 도움을 요청하기 위해 필요한 메시지는 "증언하라!"가 있을 것이고, 이 메시지를 수신하기에 적합한 객체로 "모자 장수"를 선택하게 됩니다. - 메시지에 적합한 객체가 없다면 메시지를 수행할 수 있는 객체를 만들어줘야 한다고 생각합니다.
Issue_2
모자 장수가 책임을 수행하기 위해 증언 방법과 순서를 자신의 의지에 따라 선택할 수 있는 자유를 누린다.
라고 되어있는데 순서가 어떤 걸 의미하나요? 증언을 설명할 방법 순서를 뜻하는 건가요?
- 증언을 하기 위한 과정 자체를 스스로 설계할 수 있다는 것 같습니다.
Issue_3
다형성은 송신자와 수신자 간의 객체 타입에 대한 결합도를 메시지에 대한 결합도로 낮춤으로써 달성된다.
전혀 이해가 되지 않는 문장입니다.
- 서로 다른 객체간의 공통된 메서드를 사용하고 있을 경우, 이를 하나의 인터페이스에 하나로 묶어서 결합도를 낮춘다는 이야기인 것 같습니다.