- 객체지향의 본질은 협력하는 객체들의 공동체를 창조하는 것이다.
- 객체지향 설계의 핵심은 협력을 구성하기 위해 적절한 객체를 찾고 적절한 책임을 할당하는 과정에서 드러난다.
- 객체지향에서 가장 중요한 것은 역할, 책임, 협력이다.
01. 협력 #
- 협력 : 객체들이 앱의 기능을 구현하기 위해 수행하는 상호작용
- 책임 : 객체가 협력에 참여하기 위해 수행하는 로직
- 역할 : 객체들이 협력 안에서 수행하는 책임들이 모여 수행하는 것
협력 #
- 객체지향 시스템은 자율적인 객체들의 공동체이다.
- 객체는 고립된 존재가 아니라 시스템의 기능이라는 더 큰 목표를 달성하기 위해 다른 객체와 협력하는 사회적 존재이다.
- 협력은 기능을 구현할 수 있는 유일한 방법이다.
- 메시지 전송으로부터 협력이 시작된다.
- 메시지를 수신한 객체는 메서드를 실행해 요청에 응답한다.
- 객체가 메시지를 처리할 방법은 스스로 선택한다는 점이 중요 → 자율성
- 객체를 자율적으로 만드는 가장 기본적인 방법은 내부 구현을 캡슐화하는 것이다.
- 캡슐화를 통해 변경에 대한 파급효과를 제한할 수 있기 때문에 자율적인 객체는 변경하기 쉬워진다.
협력이 설계를 위한 문맥을 결정한다. #
- 객체의 행동을 결정하는 것은 객체가 참여하고 있는 협력이다.
- 협력이 바뀌면 객체가 제공해야 하는 행동 역시 바뀌어야 한다.
- 협력은 객체가 필요한 이유와 객체가 수행하는 행동의 동기를 제공한다.
- 객체의 행동을 결정하는 것이 협력이라면, 객체의 상태를 결정하는 것은 행동이다.
- 객체의 상태는 그 객체가 행동을 수행하는 데 필요한 정보가 무엇인지로 결정된다.
- 객체는 자신의 상태를 스스로 결정하고 관리하는 자율적인 존재이기 때문에 객체가 수행하는 행동에 필요한 상태도 함께 가지고 있어야 한다.
- 상태는 객체가 행동하는데 필요한 정보에 의해 결정되고 행동은 협력 안에서 객체가 처리할 메시지로 결정된다.
- 결과적으로 객체가 참여하는 협력이 객체를 구성하는 행동과 상태 모두를 결정한다.
- 따라서 협력은 객체를 설계하는 데 필요한 일종의 문맥을 제공한다.
02. 책임 #
책임이란 무엇인가 #
- 협력에 참여하기 위해 객체가 수행하는 행동을 책임이라고 부른다.
- 책임이란 객체에 의해 정의되는 응집도 있는 행위의 집합으로, 객체가 유지해야 하는 정보와 수행할 수 있는 행동에 대해 개략적으로 서술한 문장이다.
- 객체의 책임은 무엇을 알고 있는가?(하는 것)와, 무엇을 할 수 있는가? (아는 것) 로 구성된다.
- 하는 것
- 객체를 생성하거나 계산을 수행하는 등 스스로 하는 것
- 다른 객체의 행동을 시작시키는 것
- 다른 객체의 활동을 제어하고 조절하는 것
- 아는 것
- 사적인 정보에 관해 아는 것
- 관련된 객체에 관해 아는 것
- 자신이 유도하거나 계산할 수 있는 것에 관해 아는 것
- 협력안에서 객체에게 할당한 책임이 외부의 인터페이스와 내부의 속성을 결정한다.
- 책임과 메시지의 크기는 다르다.
- 책임은 객체가 수행할 수 있는 행동을 종합적이고 간략하게 서술하기 때문에 메시지보다 추상적이고 개념적으로도 더 크다.
- 객체지향 개발에서 가장 중요한 능력은 책임을 능숙하게 소프트웨어 객체에 할당하는 것이다.
- 적절한 협력이 적절한 책임을 제공하고, 적절한 책임을 적절한 객체에게 할당해야만 단순하고 유연한 설계를 창조할 수 있다.
- 객체에게 얼마나 적절한 책임을 할당하느냐가 설게의 전체적인 품질을 결정한다.
책임 할당 #
- 자율적인 객체를 만드는 가장 기본적인 방법은 책임을 수행하는 데 필요한 정보를 가장 잘 알고 있는 전문가에게 그 책임을 할당하는 것이다.
- 객체들 역시 협력에 필요한 지식과 방법을 가장 잘 알고 있는 객체에게 도움을 요청한다.
- 요청에 응답하기 위해 필요한 행동이 객체가 수행할 책임으로 이어진다.
- 객체에게 책임을 할당하기 위해서는 먼저 협력이라는 문맥을 정의한다.
- 협력을 설계하는 출발점은 시스템이 사용자에게 제공하는 기능을 시스템이 담당할 하나의 책임으로 바라보는 것이다.
- 객체지향 설계는 시스템의 책임을 완료하는 데 필요한 더 작은 책임을 찾아내고 이를 객체들에게 할당하는 반복적인 과정을 통해 모양을 갖춰간다.
- 객체지향 설계는 협력에 필요한 메시지를 찾고 메시지에 적절한 객체를 선택하는 반복적인 과정을 통해 이뤄진다.
- 이렇게 결정된 메시지는 객체의 퍼블릭 인터페이스를 구성한다.
- 협력을 설계하면서 객체의 책임을 식별해 나가는 과정에서 최종적으로 시스템을 구성하는 객체들의 인터페이스와 오퍼레이션 목록을 얻게 된다.
책임 주도 설계 #
- 협력을 설계하기 위해서는 책임에 초점을 맞춰야 한다.
- 어떤 책임을 선택하느냐가 전체적인 설계의 방향과 흐름을 결정한다.
- 책임을 찾고 책임을 수행할 적절한 객체를 찾아 책임을 할당하는 방식으로 협력을 설계하는 방법을 책임주도 설계라고 부른다.
- 설계 과정
- 시스템이 사용자에게 제공해야 하는 기능인 시스템 책임을 파악한다.
- 시스템 책임을 더 작은 책임으로 분할한다.
- 분할된 책임을 수행할 수 있는 적절한 객체 또는 역할을 찾아 책임을 할당한다.
- 객체가 책임을 수행하는 도중 다른 객체의 도움이 필요한 경우 이를 책임질 적절한 객체 또는 역할을 찾는다.
- 해당 객체 또는 역할에게 책임을 할당함으로써 두 객체가 협력하게 한다.
메시지가 객체를 결정한다. #
- 객체에게 책임을 할당하는 데 필요한 메시지를 먼저 식별하고 메시지를 처리할 객체를 나중에 선택했다는 것이 중요하다.
- 메시지가 객체를 선택하게 해야 하는 이유
- 최소한의 인터페이스를 가질 수 있게 된다.
- 필요한 메시지가 식별될 때까지 객체의 퍼블릭 인터페이스에 어떤 것도 추가하지 않기 때문에 객체는 앱에 크지도, 작지도 않은 꼭 필요한 크기의 인터페이스를 가질 수 있다.
- 충분히 추상적인 인터페이스를 가질 수 있게 된다.
- 객체의 인터페이스는 무엇을 하는지는 표현해야 하지만 어떻게 수행하는지는 노출해선 안된다.
- 메시지는 외부의 객체가 요청하는 무언가를 의미하기 때문에 메시지를 먼저 식별하면 무엇을 수행할지에 촞머을 맞추는 인터페이스를 얻을 수 있다.
행동이 상태를 결정한다. #
- 객체의 행동은 객체가 협력에 참여할 수 있는 유일한 방법이다.
- 객체는 협력에 필요한 행동을 제공해야 한다.
- 객체를 객체답게 만드는 것은 상태가 아니라 행동이다.
- 객체지향을 갓 입문한 사람이 가장 쉽게 빠지는 실수가 객체의 행동이 아니라 상태에 초점을 맞추는 것이다.
- 필요한 상태가 무엇인지 먼저 결정하면 객체의 내부 구현이 인터페이스에 노출되도록 만들기 때문에 캡슐화를 저해한다.
- 캡슐화를 위반하지 않도록 구현에 대한 결정을 뒤로 미루면서 객체의 행위를 고려하기 위해서는 항상 협력이라는 문맥 안에서 객체를 생각해야 한다.
03. 역할 #
역할과 협력 #
- 객체는 협력이라는 문맥 안에서 특정한 목적을 갖게 된다.
- 객체의 목적은 협력 안에서 객체가 맡게 되는 책임의 집합으로 표시된다.
- 책임의 집합 ⇒ 역할
유연학 재사용 가능한 협력 #
- 역할이 중요한 이유는 역할을 통해 유연하고 재사용 가능한 협력을 얻을 수 있기 때문이다.
- 메시지를 수신할 수 있는 객체가 여러개라면, 그들의 대표자를 역할이라는 개념으로 추상화할 수 있음.
- 2장 예제의 AmountDiscountPolicy, PercentDiscountPolicy 각각의 객체를 추상클래스인 DiscountPolicy로 포괄해서 생각할 수 있음.
- 역할을 이용하면 불필요한 중복 코드를 제거할 수 있으며, 협력이 더 유연해진다.
- 어떤 객체라도 동일한 역할을 수행한다면 협력에 참여할 수 있게 된다.
- 책임과 역할을 중심으로 협력을 바라보는 것이 바로 변경과 확장이 용이한 유연한 설계로 나아가는 첫걸음이다.
- 역할을 구현하는 가장 일반적인 방법은 추상 클래스와 인터페이스를 이용하는 것임.
객체 대 역할 #
- 역할은 객체가 참여할 수 있는 일종의 슬롯이다.
- 따라서 유용하고 재사용 가능한 설계라는 문맥에서 역할은 중요함.
- 만약 한 종류의 객체만이 협력에 참여한다면? 굳이 역할로 추상화 하지 않고 객체로 바라봐도 된다.
- 설계 초반에는 적절한 책임과 협력의 큰 그림을 탐색하는 것이 가장 중요한 목표여야 하고, 역할과 객체를 명확하게 구분짓는 것은 그렇게 중요하진 않다.
- 구분하기 애매하다면 단순하게 객체로 시작하고 반복적으로 책임과 협력을 정제해가면서 필요한 순간에 객체로부터 역할을 분리해내는 것이 가장 좋은 방법이다.
역할과 추상화 #
- 역할은 공통의 책임을 바탕으로 객체의 종류를 숨기기 때문에 이런 관점에서 역할을 객체의 추상화로 볼 수 있다.
- 역할의 가장 큰 장점은 설계의 구성 요소를 추상화할 수 있다는 것이다.
- 추상화의 장점
- 세부 사항에 억눌리지 않고도 상위 수준의 정책을 쉽고 간단하게 표현할 수 있다.
- 협력이라는 관점에서 세부적인 사항을 무시하고 추상화에 집중하는 것이 유용하다.
- 설계를 유연하게 만든다.
- 협력 안에서 동일한 책임을 수행하는 객체들은 동일한 역할을 수행하기 때문에 서로 대체 가능하다.
- 따라서 역할은 다양한 환경에서 다양한 객체들을 수용하게 해주므로 협력을 유연하게 만든다.