서문
전통적인 경제학 > 인간은 이기적이며 합리적인 행동을 한다.
실제 실험 결과 > 인간은 이기적이며 합리적인 행동을 하지만, 다른 사람들과의 관계를 맺는 과정 속에서 인간은 본연의 특성을 배제하고 자신의 이익을 최소화하는 불합리한 선택을 한다.
즉 중요한 것은 인간 본연의 특성이 아니라 인간이 처한 환경 (타인과의 협력)이다.
객체지향의 세계에서도 협력이 객체의 행동 방식을 결정한다. 중요한 것은 객체들 간에 이뤄지는 협력이다.
협력
실제 상황에서의 협력은 다음과 같다.
- 협력은 한 사람이 다른 사람에게 요청할 때 발생하게 된다.
- 요청을 받은 사람은 자신의 방식으로 응답하게 된다.
- 이때 요청을 받은 사람은 자신 말고도 다른 사람을 필요로 할 수도 있다. 그때는 그 사람에게도 새로운 요청이 전달된다.
- 즉 협력은 요청과 응답이 연쇄적으로 발생한다.
앨리스 세계에서의 협력 과정도 다음과 같다.
- 누군가가 왕에게 재판을 요청했다. 왕에게 요청한 이유는 왕이 재판을 수행할 의무가 있으며, 재판에 필요한 지식이 있기 때문이다.
- 왕이 하얀 토끼에게 목격자를 불러오라고 요청했다. 토끼에게 요청한 이유는 목격자에 대해 알고 있으며 목격자를 부를 의무가 있기 때문이다.
- 왕이 모자 장수에게 증언하라고 요청했다. 모자 장수에게 요청한 이유는 재판에 도움이 될 만할 지식을 가지고 있으며 증언할 의무가 있기 때문이다.
결국 어떤 객체들이 특정한 요청을 받아들일 수 있는 이유는 그 요청에 대해 적절한 방식으로 응답하는 데 필요한 지식과 행동 방식을 가지고 있기 때문이며, 요청과 응답은 협력에 참여하는 객체가 수행할 책임을 정의한다.
책임
객체지향 개발에서 가장 중요한 능력은 책임을 능숙하게 소프트웨어 객체에 할당하는 것이다 - 크레이그 라만 (Craig Larman)
객체의 책임은 객체가 무엇을 알고 있는가와 무엇을 할 수 있는가로 구성된다. 일반적으로 객체의 책임은 외부에서 접근 가능한 공용 서비스의 관점에서 이야기하기에, 책임은 객체의 공용 인터페이스 (public interface)를 구성한다.
1장: 협력하는 객체들의 공동체에서 작성하였듯이, 객체지향 설계라는 예술은 적절한 객체에게 적절한 책임을 할당하는 것에서 시작되며, 책임은 객체지향 설계의 품질을 결정하는 가장 중요한 요소다.
책임은 요청을 수신하는 한쪽 객체 관점에서 무엇을 할 수 있는지를 나타낸 것이다.
메시지는 협력에 참여하는 두 객체 사이의 관계를 강조한 것이다.
따라서 객체지향 설계는 협력에 참여하기 위해 어떤 객체가 어떤 책임을 수행해야 하고 어떤 객체로부터 메시지를 수신할 것인지를 결정하는 것으로부터 시작된다.
역할
역할은 재사용 가능하고 유연한 객체지향 설계가 되도록 하는 요소이다.
왕을 판사라고 부르고 모자 장수를 증인으로 부르는 이유는 왕과 모자 장수가 아닌 객체들이 그 역할을 대체함으로써 재사용 가능한 설계가 될 수 있기 때문이다.
따라서, 역할은 협력 내에서 다른 객체로 대체할 수 있음을 나타내는 일종의 표식이다.
이때 역할을 대체할 수 있는 객체는 동일한 메시지를 이해할 수 있는 객체로 한정된다.
왕에서 여왕으로 판사가 변경될 수 있는 이유는 여왕이 왕과 같이 재판하라는 메시지를 이해할 수 있기 때문이다.
역할을 사용하면 유사한 협력을 추상화하여 인지 과부하를 줄일 수 있고, 다양한 객체들을 사용할 수 있어 재사용성이 증가한다. 협력의 추상화는 곧 애플리케이션의 설계를 이해하고 기억하기 쉽게 만든다. 이는 객체지향만의 힘이다.
객체는 역할에 주어진 책임 이외에 다른 책임을 수행할 수도 있다. 모자 장수는 본래의 모자를 판매할 책임은 잠시 제외하고 증언할 책임을 맡았다.
역할의 대체 가능성은 행위 호환성을 의미하며 행위 호환성은 동일한 책임의 수행을 의미한다!
객체의 모양을 결정하는 협력
데이터는 단지 객체가 행위 (책임)를 수행하는 데 필요한 재료들일뿐이다. 따라서 데이터를 중점적으로 객체지향을 설계하는 것은 옳지 못하다.
클래스를 중점적으로 객체지향을 설계하는 것 또한 옳지 않다. 앨리스 세계에서의 왕은 현실의 왕과 다르게 근엄하고 위엄 있을 필요가 없다. 협력에 참여하기 위한 것만 가지고 있으면 충분하다. 따라서 객체가 참여하는 협력을 먼저 설계해야 한다.
올바른 객체 설계 방법은 다음과 같다.
- 객체지향 설계에 참여하는 객체들이 주고받을 요청과 응답의 흐름을 결정한다.
- 앨리스 세계에서 현재 필요한 것은 “재판을 진행” 하는 협력이다. 이를 위해서는 “재판을 할 책임”, “증언할 책임”, “목격자를 불러올 책임” 등이 필요하다.
- 각 객체에게 적절한 책임을 부여한다.
- “재판을 할 책임”은 왕 객체에게, “증언할 책임”은 모자 장수 객체에게, “목격자를 불러올 책임”은 토끼 객체에게 할당한다.
- 각 객체가 책임을 수행할 때 필요한 데이터들을 정의한다.
- 그다음 클래스의 구현 방법을 정의한다. (따라서 데이터와 클래스는 뒤에 결정된다.)
따라서 객체를 먼저 충분히 협력적으로 만든 후, 협력에 참여할 때 자신만의 방법으로 처리할 수 있도록 자율적인 존재로 설계하면 된다.
객체지향 설계 기법
위의 역할, 책임, 협력을 토대로 객체지향을 설계하는 기법은 크게 다음과 같이 나뉜다.
책임-주도 설계
책임 주도 설계는 2장: 이상한 나라의 객체에서도 작성했던 설계 방법이다.
- 시스템이 사용자에게 제공해야 하는 기능인 시스템 책임을 파악한다.
- 시스템 책임을 더 작은 책임으로 분할한다.
- 분할된 책임을 수행할 수 있는 적절한 객체 또는 역할을 찾아 책임을 할당한다.
- 객체가 책임을 수행하는 중에 다른 객체의 도움이 필요한 경우 이를 책임질 적절한 객체 또는 역할을 찾는다. (책임을 여러 종류의 객체가 수행할 수 있다면 추상적인 역할로 대체된다.)
- 해당 객체 또는 역할에게 책임을 할당함으로써 두 객체가 협력하게 한다.
말 그대로 책임을 먼저 생각한 후 책임을 작게 쪼갠 다음 각 책임을 수행할 객체를 선택해 나가는 설계 방식이다.
디자인 패턴
책임 주도 설계는 객체의 역할, 책임, 협력을 고안하기 위한 방법과 절차를 제안하지만, 디자인 패턴은 책임 주도 설계의 결과를 표현하는 데 사용된다.
패턴 (Pattern): 일정한 형태나 양식 또는 유형 - 네이버 사전
즉 패턴은 특정한 상황에서 설계를 돕기 위해 모방하고 수정할 수 있는 과거의 실제 경험이다.
디자인 패턴은 책임 주도 설계를 기반으로 작성한 패턴들을 의미한다. 이를 참고해 사람들은 더 빠르게 책임 주도 설계를 어떻게 해야 하는지 습득할 수 있다. 그런 점에서 디자인 패턴은 책임 주도 설계를 구현할 수 있는 지름길과도 같은 역할을 한다.
디자인 패턴 중 하나인 COMPOSITE 패턴을 보자.
- Client는 요청할 클라이언트를 의미한다.
- Component는 클라이언트와 협력할 수 있는 공용 인터페이스를 정의한 역할을 수행한다.
- Leaf는 공용 인터페이스에 대한 오퍼레이션 호출에 응답할 수 있는 기본 행위를 구현한다.
- Composite는 외부로부터 부분에 대한 세부 사항을 감추고 포함된 부분을 하나의 단위로 행동하는 역할이다.
테스트-주도 개발
테스트 주도 개발은 테스트를 작성하고, (중복이 있을 수 있는) 간단한 코드를 작성한 뒤, 리팩터링 작업을 통해 중복을 제거해 나가는 개발 방법이다. 그러나 초보자들은 어떤 테스트를 어떤 식으로 작성해야 하는지 잘 모를 수 있다. 객체가 이미 존재한다고 가정하고 객체에게 어떤 메시지를 전송할 것인지에 먼저 생각할 것을 알려주지만, 역할, 책임, 협력 관점에서 객체를 바라봐야만 효과가 있다.
테스트 주도 개발의 핵심은 책임을 수행할 객체 또는 클라이언트가 기대하는 객체의 역할이 메시지를 수신할 때 어떤 결과를 반환하고 그 과정에서 어떤 객체와 협력할 것인지에 대한 기대를 코드의 형태로 작성하는 것이다.
따라서 이 객체가 적절한 방식으로 책임에 따른 적절한 기댓값을 도출해 내는지를 테스트 장치로 안전하게 검증해 내는 것이 테스트 주도 개발의 목적이라 할 수 있겠다.
따라서 테스트 주도 개발은 역할, 책임, 협력의 관점에서 객체지향을 충분히 바라볼 수 있어야지만 다룰 수 있는 개발 방법이다.
요약
- 역할, 책임, 협력을 기반으로 설계하는 것이 가장 중요하다.
- 역할은 다른 객체가 동일하게 요청에 대해 응답할 수 있다면 다른 객체로 변경할 수 있다는 재사용성을 내포한다.
- 책임은 객체가 무엇을 할 수 있는가와 무엇을 알고 있는가가 결정되게 한다. 책임은 객체지향 설계의 품질을 결정한다.
- 협력은 객체가 요청하고 응답하는 과정에서 이루어진다. 요청과 응답은 협력에 참여하는 객체가 수행할 책임을 정의한다.
- 역할, 책임, 협력을 기반으로 설계된 방법은 크게 세 가지로 있다.
- 책임 주도 설계는 말 그대로 시스템에서 구현해야 할 책임을 먼저 생각하고 그 객체를 분할한 뒤 각 책임을 수행할 수 있는 객체와 수행할 행동을 나중에야 고민하는 방법이다.
- 디자인 패턴은 반복되는 상황에서 책임 주도 설계를 빠르게 구현할 수 있도록 참고할 수 있는 패턴이다.
- 테스트 주도 개발은 역할, 책임, 협력을 충분히 고민해 보고 책임 주도 설계를 많이 해 본 사람만 효과적으로 개발할 수 있는 개발법이다.
'도서 📚 > 📗 객체지향의 사실과 오해' 카테고리의 다른 글
6장: 객체 지도 (0) | 2023.11.08 |
---|---|
5장: 책임과 메시지 (0) | 2023.11.07 |
3장: 타입과 추상화 (1) | 2023.11.02 |
2장: 이상한 나라의 객체 (1) | 2023.11.01 |
1장: 협력하는 객체들의 공동체 (2) | 2023.10.31 |