서문
참가자와 다른 사람의 이야기를 하는 과정에서의 실험 > 다른 사람의 소리는 녹음된 것이었음
다른 사람이 갑자기 발작을 일으킬 경우 자신밖에 없다고 생각했던 참가자는 85%가 심리학자들에게 도움을 요청
그러나 자신 말고도 또 다른 사람이 있다고 생각했던 참가자는 31%만 도움을 요청함
그 이유는 자신이 도움을 요청하지 않아도 된다고 생각했기 때문
- 사건에 대한 목격자가 많으면 많을수록 개인이 느끼는 책임감은 적어진다
- 따라서 객체지향에서도 명확한 책임과 역할을 부여해야만 객체가 자신의 책임이라고 느낄 것이다.
자율적인 책임
4장: 역할, 책임, 협력에서 작성하였듯이 적절한 책임을 적절한 객체에게 할당하는 것부터 실행되어야 한다.
또한 객체는 자신에게 부여된 책임을 충분히 자율적으로 수행할 수 있어야 한다.
그러나 객체가 자율적으로 수행하기 위해서는 부여받은 책임 자체도 자율적이어야 한다.
앨리스 예시: 왕이 모자 장수에게 “증언하라”라고 요청했다면, 모자 장수는 자신만의 방법으로 증언할 수 있을 것이다. 그러나 왕이 “목격했던 장면들을 떠올리고, 떠오르는 기억을 시간 순서대로 재구성하고, 말로 간결하게 표현하라”는 식으로 모자 장수에게 요청했다면, 모자 장수가 선택할 수 있는 자유의 범위가 지나치게 제한될 수 있다. 이는 자율적인 방식이 아니라 왕에게 의존하게 될 것이다.
그러나 책임을 포괄적이고 추상적으로 부여한다고 해서 무조건 좋은 것은 아니다.
책임은 협력에 참여하는 의도를 명확하게 설명할 수 있는 수준 안에서 추상적이어야 한다.
앨리스 예시: 왕이 모자 장수에게 “설명하라”라고 요청한다면 모자 장수는 어떤 것에 대해 설명해야 하나? 이런 식으로 협력의 의도를 흐릿하게 만드는 추상적인 책임은 올바르지 않다.
어떤 책임이 자율적인지를 판단하는 기준은 문맥에 따라 다르다. 어떤 책임이 가장 적절한가는 설계 중인 협력이 무엇인가에 따라 다르다.
자율적인 책임은 또한 객체가 무엇 (what)을 해야 하는가를 설명한다.
메시지와 메서드
메시지는 객체가 다른 객체에게 접근할 수 있는 유일한 방법이다. 메시지를 전송함으로써 객체의 책임이 수행되도록 한다.
메시지 전송은 수신자, 메시지 이름, 인자로 구분된다. 수신자는 위에서의 다른 객체를 의미하며, 메시지 이름은 객체가 요청하는 이름을 뜻한다. (ex: 앨리스 세계에서의 “증언하라”) 요청을 할 때 추가적인 정보를 보낼 경우, 이를 인자라고 한다.
메시지를 처리할 수 있다 = 객체가 해당 메시지에 해당하는 행동을 수행해야 할 책임이 있다
객체가 수신할 수 있는 메시지의 모양이 객체가 수행할 책임의 모양을 결정한다.
메시지를 기준으로 객체의 외부와 내부가 분리될 수 있다. 왜냐하면 메시지를 요청하는 객체는 메시지를 수신받은 객체가 어떤 방법으로 요청을 처리하는지는 몰라도 되기 때문이다. 객체가 제공하는 메시지는 공개된 영역 (외부)에 속하며, 객체가 메시지를 처리하는 방법은 자신의 사적인 영역 (내부)에 속한다.
메서드는 메시지를 처리하기 위해 내부적으로 선택하는 방법을 뜻한다. 메시지는 무엇을 해야 하는가를 명시할 뿐이고, 어떤 메서드를 선택할 것인지는 수신 객체의 결정에 좌우된다. 객체지향에서는 메서드를 실행 시간에 선택할 수 있다.
다형성은 서로 다른 유형의 객체가 동일한 메시지에 대해 서로 다르게 반응 (자신만의 방법 - 즉 메서드가 달라진다. 따라서 하나의 메시지와 여러 개의 메서드로 구성된다.) 하는 것을 의미한다. 동일한 메시지를 이해할 수 있다는 것은 객체들이 동일한 책임을 공유한다는 것을 의미하며, 결과적으로 같은 메시지를 이해하기 때문에 객체들은 대체 가능하다. 즉 다형성은 수신자의 종류를 캡슐화하는 효과가 있으며, 이는 송신자와 수신자 간의 객체 타입에 대한 결합도를 메시지에 대한 결합도로 낮추는 효과가 있다.
메시지와 다형성 덕분에 송신자는 수신자에 대해 매우 적은 정보만 알고 있어도 상호 협력이 가능하다. 따라서 다음과 같은 것들이 가능해진다.
- 협력이 유연해진다. > 송신자는 메시지를 이해하기만 한다면 수신자가 누가 되든지 상관하지 않는다.
- 협력이 수행되는 방식을 확장할 수 있다. > 수신자가 변경되더라도 송신자는 영향이 없기 때문에 협력이 수행되는 방식을 확장할 수 있다. 즉, 메서드를 자유롭게 추가할 수 있다.
- 협력이 수행되는 방식을 재사용할 수 있다. > 다양한 객체들이 수신자의 자리를 대체할 수 있기 때문에 다양한 문맥에서 협력을 재사용할 수 있다.
메시지를 따라라
클래스를 중심으로 생각하지 말고 객체와 메시지를 먼저 생각하라. 객체지향의 강력함은 계속 이야기했듯이 객체들이 주고받는 메시지로부터 나온다. 클래스는 단지 동적인 객체들의 특성과 행위를 정적인 텍스트로 표현하기 위해 사용할 수 있는 추상화 도구일 뿐이다.
4장: 역할, 책임, 협력에서 작성하였듯이 데이터를 먼저 생각하는 것은 협력적이어야 하는 객체의 특성을 올바르게 표현하지 못할 위험이 있다. 따라서 협력이라는 문맥을 고려하면서 객체를 설계해야 하며, 이는 곧 객체가 수행해야 할 메시지를 중점으로 설계해야 한다는 것을 의미한다. 그래야 메시지가 객체를 선택하도록 설계할 수 있다.
책임-주도 설계의 과정은 What/Who 사이클을 기반으로 진행된다. (참고: 4장: 역할, 책임, 협력)
협력을 위해 어떤 행위 (what - 메시지)를 수행할 것인지 결정한 후 누가 (who) 그 행위를 수행할 것인지를 결정하는 것이다. 책임이 먼저 오고 객체가 책임을 따른다!
메시지가 결정된 후 메시지를 처리할 객체를 선택하도록 하기 때문에 메시지를 결정하는 시점에서는 어떤 객체가 선택될지 알지 못한다. 따라서 메시지 중심의 설계는 메시지 수신자의 캡슐화를 증진시키며 송신자와 수신자가 느슨하게 결합된다고 할 수 있다.
“묻지 말고 시켜라”는 이처럼 송신자가 수신자를 잘 모른 상태에서 메시지를 전송하는 것을 뜻한다.
객체 인터페이스
인터페이스는 상호작용하기 위한 장치를 뜻한다. 예시로 자동차가 있다. (핸들, 변속기, 엑셀, 브레이크, 계기판)
- 인터페이스의 사용법만 알고 있으면 내부 구조나 동작 방법을 몰라도 된다.
- 운전자는 자동차가 내부적으로 어떻게 동작하는지 몰라도 된다.
- 인터페이스가 변경되지 않고 내부 구성이나 작동 방식이 변경되는 것은 사용자에게 영향을 끼치지 않는다.
- 자동차의 내부 부품이 변경되었다고 해서 사용 방법이 달라지는 것은 아니다.
- 인터페이스가 동일하면 어떤 대상과도 상호작용할 수 있다.
- 사용자는 다른 자동차도 동일하게 운전할 수 있다.
객체가 다른 객체와 상호작용하기 위한 유일한 방법은 메시지라고 했다. 따라서 인터페이스는 객체가 수신할 수 있는 메시지의 목록으로 구성된다. 인터페이스는 외부에서 접근 가능한 공개된 인터페이스 (공용 인터페이스)와 내부에서 자기 자신만 사용할 수 있는 감춰진 인터페이스로 구분된다.
객체가 협력에 참여하기 위해 수행하는 메시지가 공용 인터페이스의 모양을 암시한다.
인터페이스와 구현의 분리
맷 와이스펠드 (Matt Weisfeld)의 객체지향적인 사고방식을 이해하기 위한 세 가지 원칙
- 좀 더 추상적인 인터페이스 > 자율적인 책임에서의 작성한 것
- 최소 인터페이스 > 외부에서 사용할 필요가 없는 인터페이스는 최대한 노출하지 말라
- 인터페이스와 구현 간에 차이가 있다는 점을 인식 > 엄밀히 말해서 인터페이스는 외부에서 접근 가능한 공용 인터페이스를 뜻하며, 객체를 구성하지만 공용 인터페이스에 포함되지 않는 모든 것을 구현이라고 한다. 예시로 상태를 표현하는 방법과 메서드를 구성하는 코드가 구현의 종류이다.
공용 인터페이스와 구현을 분리하는 것은 말 그대로 인터페이스와 구현의 분리를 뜻한다.
분리해야 하는 이유는 소프트웨어가 항상 변경될 수 있기 때문이다. 객체의 모든 것이 외부에 있다면 작은 부분을 수정하더라도 변경에 의한 파급효과가 널리 퍼질 것이다.
자율적인 객체는 외부와 상관없이 메시지를 처리하는 메서드를 스스로 선택할 수 있어야 한다고 말했다. 이는 외부에 영향을 주지 않으면서 메서드를 자유롭게 변경할 수 있어야 한다는 것을 의미한다. 객체의 상태와 메서드 구현이 수정되더라도 객체 외부에 영향을 미쳐서는 안 된다. 객체 외부에 영향을 미치는 변경은 객체의 공용 인터페이스를 수정할 때뿐이다.
인터페이스와 구현을 분리하면서, 객체의 구현은 외부로부터 철저히 감춰진다. 이것은 곧 객체의 구현이 캡슐화되었음을 뜻한다.
객체의 외부와 내부를 명확하게 분리하는 것이 설계를 더 깔끔하고 변경하기 쉽게끔 만든다.
책임의 자율성이 협력의 품질을 결정한다
자율적인 책임에서 책임이 자율적이어야만 객체가 자율적으로 책임을 수행할 수 있다고 하였다.
자율적인 책임은 그렇지 않은 책임에 비해 협력을 이해하기 쉽고 유연하게 변경할 수 있도록 만든다.
- 협력을 단순하게 만든다. > 왕은 모자 장수에게 단순히 “증언하라”는 것만 요청한다.
- 객체의 외부와 내부를 명확히 분리한다. > 모자 장수가 증언할 방법은 모자 장수 스스로가 선택한다. 그 방법 (메서드)는 외부에서 알 수 없다.
- 책임을 수행하는 내부적인 방법을 변경하더라도 외부에 영향을 미치지 않는다. > 2번과 비슷한 뜻이다. 모자 장수가 다른 방식으로 증언하더라도 왕에게는 영향이 없다.
- 협력의 대상을 다양하게 선택할 수 있도록 한다. > 다른 객체가 증언할 수 있다면 모자 장수에서 다른 객체로 변경되더라도 문제가 되지 않는다. 이것이 명확히 되기 위해서는 협력이 단순해야 한다.
- 책임들이 자율적일수록 객체의 역할을 이해하기 쉬워진다. > “증인석에 입장한다”는 책임과 “증언하라”는 책임을 통해 모자 장수는 “증인”이라는 역할을 하고 있음을 쉽게 파악할 수 있다.
책임이 자율적일수록 적절하게 추상화되며, 응집도가 높아지고, 결합도가 낮아지며, 캡슐화가 증진되고, 인터페이스와 구현이 명확히 분리되며, 설계의 유연성과 재사용성이 향상된다!
요약
- 객체에게 부여된 책임은 충분히 자율적이어야 한다. 또한 협력의 의도를 명확하게 설명할 수 있는 수준 안에서 추상적이어야 한다. 이는 곧 협력을 이해하기 쉽고 유연하게 변경할 수 있도록 만든다.
- 동일한 메시지를 이해할 수 있다는 것은 다형성이 있음을 뜻한다. 다형성은 수신자의 종류를 캡슐화하기 때문에 결합도를 낮출 수 있다.
- 잘 변경되지 않는 공용 인터페이스와 변경의 위험이 많이 있는 객체의 상태 및 메서드를 분리하는 것은 설계를 더 깔끔하고 변경에 따른 파급효과를 줄일 수 있도록 해 준다.
- 메시지를 중점적으로 설계하라.
'도서 📚 > 📗 객체지향의 사실과 오해' 카테고리의 다른 글
7장: 함께 모으기 (0) | 2023.11.09 |
---|---|
6장: 객체 지도 (0) | 2023.11.08 |
4장: 역할, 책임, 협력 (0) | 2023.11.05 |
3장: 타입과 추상화 (1) | 2023.11.02 |
2장: 이상한 나라의 객체 (1) | 2023.11.01 |