3장 역할, 책임, 협력
3장에서는 그 동안 이야기 하였던 역할, 책임, 협력을 보다 상세하게 설명하는 챕터였습니다. 3장을 다 읽은 지금 가장 기억에 남는 것 하나를 고르자면 역할은 슬롯과 같다는 말이였던것 같습니다.
객체지향의 본질은 협력하는 객체들의 공동체를 창조하는 과정에서 드러난다.
협력을 생각할때 중요하게 여겨야 하는 것중 하나라고 생각합니다.
1. 이처럼 객체들이 애플리케이션의 기능을 구현하기 위해 수행하는 상호작용을 협력이라고 한다.
2. 객체가 협력에 참여하기 위해 수행하는 로직을 책임이라고 부른다.
3. 객체들이 협력 안에서 수행하는 책임이 모여 객체가 수행하는 역할을 구성한다.
그 동안 자주 언급되었던 협력, 책임, 역할을 추상적으로 설명하는 것이 아닌 구체적으로 이야기하였기에 3장에서 가장 중요한 부분이라 생각합니다.
결과적으로 객체를 자율적으로 만드는 만드는 가장 기본적인 방법은 내부 구현을 캡슐화하는 것이다.
책에서 언급한 내용을 저의 생각을 토대로 다시 풀어 이야기하면 객체를 자율적으로 만들기 위해서는 객체가 가지고 있는 상태를 외부에 노출시키지 않아야 하며 이를 위해서는 캡슐화가 필연적이라고 생각합니다.
결론적으로 객체의 행동을 결정하는 것은 객체가 참여하고 있는 협력이다.
행동은 구체적으로 말하면 메소드라고 생각합니다.(비록 책에서 이야기하는 취지와는 다른 방향인듯 합니다.) 그러나 협력을 주된 관점으로 본다면 협력안에서 객체가 담당하고 있는 역할(행동)이 정해지는 것은 당연한 이야기라 생각합니다.
객체의 행동을 결정하는 것이 협력이라면 객체의 상태를 결정하는 것은 행동이다.
책에서는 협력에 의해 행동이 결정되고 행동에 의해 상태가 결정됩니다. 즉 큰 규모의 설계부터 작은 규모의 설계까지 흘러간다고 생각합니다. (Top-Down)
책임이란 객체에 의해 정의되는 응집도 있는 행위의 집합으로 객체가 유지해야 하는 정보와 수행할 수 있는 행동에 대해 개략적으로 서술한 문장이다.
"책임은 여러 행위의 집합이다." 라고 생각을 합니다. 즉 하나의 책임을 지기 위해 필요한 행위(행동)은 여러개가 될 수 있다 생각합니다.
- 하는 것(Doing)
- 객체를 생성하거나 계산을 수행하는 등의 스스로 하는 것
- 다른 객체의 행동을 시작시키는 것
- 다른 객체의 활동을 제어하고 조절하는 것
- 아는 것(Knowing)
- 사적인 정보에 관해 아는 것
- 관련된 객체에 관해 아는 것
- 자신이 유도하거나 계산할 수 있는 것에 관해 아는 것
크레이그 라만에 의해 나뉜 객체의 책임입니다. 크게 "하는 것"과 "아는 것"으로 나뉠 수 있습니다. 또한 "객체지향 개발에서 가장 중요한 능력은 책임을 능숙하게 소프트웨어 객체에 할당하는 것"이라는 말을 했을 정도로 책임을 보다 자세하게 나누어야 합니다.
자율적인 객체를 만드는 가장 기본적인 방법은 책임을 수행하는 데 필요한 정보를 가장 잘 알고 있는 전문가에게 그 책임을 할당하는 것이다.
객체들간의 협력을 구성하는데 중요한 내용중 하나라 생각합니다. 이때 전가해야할 책임과 스스로 담당해야하는책임을 잘 구분해야 합니다.
협력을 설계하는 출발점은 시스템이 사용자에게 제공하는 기능을 시스템이 담당할 하나의 책임으로 바라보는 것이다. 객체지향 설계는 시스템의 책임을 완료하는 데 필요한 더 작은 책임을 찾아내고 이를 객체들에게 할당하는 반복적인 과정을 통해 모양을 갖춰간다.
협력을 바라볼때 기능을 하나의 책임으로 바라본다는 말은 처음 설계에 대해 공부를 하였을때 들었으면 이라는 생각이 듭니다. 하나의 기능을 마치 양파까듯이 하나씩 벗기다보면 언젠가 하나의 작은, 나눌 수 없는 기능이 나오고 해당 기능을 객체의 책임으로 할당하면 객체지향적인 프로그램을 설계할 수 있다 생각합니다.
어떤 경우에는 응집도와 결합도의 관점에서 정보 전문가가 아닌 다른 객체에게 책임을 할당하는 것이 더 적절한 경우도 있다. 하지만 기본적인 전력은 책임을 수행할 정보 전문가를 찾는 것이다.
1장에서 그랬듯 기본적으로는 데이터와 이를 처리할 프로세스를 같이 두는 것이 정도라 생각합니다. 그러나 같은 방식으로 프로그램이 설계 되지 않기에 유동적으로 설계를 해야한다는 생각입니다.
이처럼 책임을 찾고 책임을 수행할 적절한 객체를 찾아 책임을 할당하는 방식으로 협력을 설계하는 방법을 책임 주도 설계 라고 부른다.
책임 주도 설계는 RDD라고 합니다. RDD는 책에서 언급하였듯 협력 -> 책임 -> 행동 순으로 설계를 한다면 최근 유행하는 DDD는 객체의 상태부터 하여 역순으로 설계한다고 합니다.
- 시스템이 사용자에게 제공해야 하는 기능인 시스템 책임을 파악한다.
- 시스템 책임을 더 작은 책임으로 분할한다.
- 분할된 책임을 수행할 수 있는 적절한 객체 또는 역할을 찾아 책임을 할당한다.
- 객체가 책임을 수행하는 도중 다른 객체의 도움이 필요한 경우 이를 책임질 적절한 객체 또는 역할을 찾는다.
- 해당 객체 또는 역할에게 책임을 할당함으로써 두 객체가 협력하게 한다.
위는 책임 주도 설계 방법의 과정입니다. 말이 거창하지 책에서 언급하는 내용을 요약한것뿐이라 생각합니다.
메시지가 객체를 선택하게 해야하는 이유는 두 가지가 있다.
1. 객체가 최소한의 인터페이스를 가질수 있게 된다.
2. 객체는 충분히 추상적인 인터페이스를 가질 수 있게 된다.
객체가 해야하는 행동(what)를 먼저 정의하면 외부에서는 정의된 행동 외에는 알 방법이 없어집니다. 그렇기에 자연스레 추상화와 캡슐화가 이루어지게 된다 생각합니다.
협력이 객체의 행동을 결정하고 행동이 상태를 결정한다. 그리고 그 행동이 바로 객체의 책임이 된다.
즉 협력 -> 행동(책임) -> 상태 순으로 정의가 된다고 정리할 수 있다고 생각합니다.
이처럼 객체가 어떤 특정한 협력 안에서 수행하는 책임의 집합을 역할이라고 부른다.
그리고 이러한 역할을 통해 유연하고 재사용 가능한 협력을 얻을 수 있기 때문입니다. 즉 "역할은 다른 것으로 교체할 수 있는 책임의 집합입니다." 책을 인용하면 마치 "슬롯"과 같다 생각합니다.
추상화라는 말에서 예상했겠지만 역할을 구현하는 가장 일반적인 방법은 추상 클래스와 인터페이스를 사용하는 것이다.
책에서도 짚고 넘어가지만 추상클래스를 이용한 구현방법과 인터페이스를 이용한 구현방법은 조금 성격이 다릅니다. 추상클래스를 이용해서 구현한 방법은 동일한 로직을 부모 클래스에서 구현해놓고 세부적인 로직만 수정이 필요할 경우 사용하고 인터페이스를 이용해 구현하는 방법은 역할은 동일하되 구현하는 방법은 완전히 다를때 사용하는 방법입니다.
역할은 객체가 참여할 수 있는 일종의 슬롯이다.
...
레베카 워프스브록의 말을 인용하자면 협력에 참여하는 후보가 여러 종류의 객체에 의해 수행될 필요가 있다면 그 후보는 역할이 되지만 단지 한 종류의 객체만이 협력에 참여할 필요가 있다면 후보는 객체가 된다.
즉 역할이 수행할 수 있는 객체가 여럿이 있다고 판단되면 이는 역할을 추상화해야 한다는 말이며 반대로 특정 역할은 하나의 객체만이 담당할 것이라 판단들면 이는 역할대신 바로 객체를 사용해도 된다는 말이다. 그리고 책에서는 정확한 판단이 서지 않는다면 구체적인 객체를 통해 구현하라고 추천하고 있습니다.
린스카우에 따르면 협력은 역할등의 상호작용으로 구성되고, 협력을 구성하기 위해 역할에 적합한 객체가 선택되며, 객체는 클래스르 이용해 구현되고 생성된다.
RDD의 설계 프로세스를 도식화했다고 생각합니다.