본문 바로가기

책 리뷰

책 리뷰 - 객체지향의 사실과 오해4

728x90
반응형

 

 

04 / 역할, 책임, 협력

 

어떤 상황에 처해 있느냐가 인간의 행동을 결정한다. -> 각 개인이 처해 있는 정황 또는 문맥이 인간의 행동 방식을 결정한다.

 

인간의 행동을 결정하는 문맥: 타인과의 협력
협력에 얼마나 적절한지에 따라 행동의 적합성이 결정되며 협력이라는 문맥이 인간의 행동 방식을 결정한다.

 

객체의 모양을 빚는 것은 객체가 참여하는 협력이다. 개별적인 객체의 행동이나 상태가 아니라 객체들 간의 협력에 집중하라!

 

협력

 

협력은 한사람 한 사람이 다른 사람에게 도움을 요청할 때 시작된다.
문제를 해결하기 위해 도움을 요청하고, 요청한 사람에게 필요한 지식이나 서비스를 제공하는 것으로 요청에 응답한다.
-> 협력: 다수의 요청과 응답으로 구성, 다수의 연쇄적인 요청과 응답의 흐름

 

"이상한 나라의 앨리스에서 하트 잭이 재판을 받는다. 왕이 재판을 하며 토끼에게 증인을 데꼬오라고 시키고, 토끼는 증인 모자 장수를 데려온다. 모자 장수는 증언을 한다."

 

하트 잭을 재판하기 위해 서로 협력하고 있다. 재판이라는 동일한 목적을 달성하기 위해 협력하고 있는 것


누군가가 왕에게 재판을 요청함으로써 재판이시작된다.
왕이 하얀 토끼에게 증인을 부를 것을 요청한다.
왕의 요청을 받은 토끼는 모자 장수에게 증인석으로 입장할 것을 요청한다.
모자 장수는 증인석에 입장함으로써 토끼의 요청에 응답한다.
모자 장수의 입장은 왕이 토끼에게 요청했던 증인 호출에 대한 응답이기도 하다.
이제 왕은 몯자 장수에게 증언하 것을 요청한다.
모자 장수는 자신이 알고 있는 내용을 증언함으로써 왕의 요청에 응답한다.

 


=> 요청하는 과정을 통해 협력이 이뤄짐

 

왕은 재판에 필요한 지식을 가지고 있으며 재판을 수행할 의무가 있다.
토끼는 목격자에 대해 알고 있으며 동시에 목격자를 부를 의무가 있다.
모자장수는 재판에 도움이 될만한 사건의 내용을 알고 증언할 의무가 있다.
=> 적절한 방식으로 응답하는 데 필요한 지식과 행동 방식을 가진다, 요청과 응답은 협력에 참여하는 객체가 수행할 책임을 정의한다.

 

책임

 

적절한 행동을 할 의무가 있는 경우 해당 객체가 책임을 가진다.
왕은 재판을 수행할 책임을 진다.
하얀 토끼는 목격자를 불러올 책임을 진다.
모자 장수는 증인석에 입장하고 증언할 책임을 진다.
=> 요청은 그 대상이 요청을 처리할 책임이 있음

 

객체지향에서 가장 중요한 능력: 책임을 능숙하게 소프트웨어 객체에 할당하는 것
책임을 어떻게 구현할 것인가 하는 문제는 객체와 책임이 제자리를 잡은 후에 고려해도 늦지않다. 변경에 취약하고 협력에 참여할 수 없는 비자율적인 객체를 낳을 수 있음

 

책임의 분류

 

협력에 참여하는 객체들은 목표를 달성하는 데 필요한 책임을 수행한다.
책임은 객체에 의해 정의되는 응집도 있는 행위의 집합으로, 객체가 알아야 하는 정보와 객체가 수행할 수 있는 행위에 대해 개략적으로 서술한 문장
객체의 책임: 객체가 무엇을 알고 있는가와 무엇을 할 수 있는가

 

하는 것:
객체를 생성하거나 계산을 하는 등의 스스로 하는 것
다른 객체의 행동을 시작시키는 것
다른 객체의 활동을 제어하고 조절하는 것

 

아는 것:
개인적인 정보에 관해 아는 것
관련된 객체에 관해 아는 것
자신이 유도하거나 계산할 수 있는 것에 관해 아는 것

 

왕: 다른 객체들의 활동을 제어하고 조율하고 있다. => 왕은 하는것과 관련된 책임 수행
하얀 토끼: 증인석에 입장하도록 요청함으로서 관련된 객체에 대해 아는 것에 해당하고 두번째 책임은 다른 객체의 행동을 시작시키는 것에 해당한다. => 두가지 종류의 책임 모두 수행

모자 장수: 증언할 책임을 가진다. 객체를 생성하거나 계산을 하는 등의 스스로 하는것에 해당하고 두 번째 책임은 자신이 유도하거나 계산할 수 있는 것에 관해 아는 것 => 두 가지 종류의 책임 모두 수행

 

책임은 객체지향 설계의 품질을 결정하는 중요한 요소 => 명확한 책임이 애플리케이션의 미래를 결정짓는다.

 

책임은 객체의 외부에 제공해 줄 수 있는 정보(아는 것의 측면) 외부에 제공해 줄 수 있는 서비스(하는 것의 측면)의 목록
=> 책임은 객체의 공용 인터페이스를 구성한다.

 

책임과 메시지

 

협력 안에서 객체는 다른 객체로부터 요청이 전송됐을 경우에만 자신에게 주어진 책임을 수행한다.
메시지 전송(message-send) : 주어진 책임을 수행하도록 요청을 보내는 것
협력은 메시지를 통해 이뤄진다. 송신자, 수신자

 

왕은 '증언하라'는 메시지 전송하고 모자 장수는 '증언하라' 메시지를 수신할 수 있다. 둘이 협력할 수 있는 이유는 왕이 모자장수가 이해라 수 있는 메시지를 전송할 수 있고 모자 장수는 메시지에 대해 적절한 책임을 수행할 수 있다.
=> 왕과 모자 장수 사이의 상호 협력이 가능해 진다.

 

역할

모자 장수는 '증인'이라는 역할을 수행하고 있고 왕은'판사'라는 역할을 수행하고 있다.
책임의 집합: 객체가 협력 안에서 수행하는 역할
재사용 가능하고 유연한 객체지향 설계를 낳는 매우 중요한 구성요소이다.

 

"왕은 너무 머리가 아파서 왕비에게 왕비에게 자리를 위임했다. 또다른 증인들인 요리사와 앨리스가 나왔다"

 

모자 장수, 요리사, 앨리스가 증인으로 참석하는 재판과정도 전체적으로 그 흐름이 매우 유사하다.
왕 -> 여왕
모자 장수 -> 요리사, 앨리스 만 바뀌었다.
=> 모자 장수, 요리사, 앨리스 세 개의 협력이 필요하지만 하나의 협력으로 다루고 싶다.

 

왕, 하트 여왕은 '판사'의 역할을 수행한다. 모자 장수, 요리사, 앨리스는 '증인'의 역할을 수행한다. 판사와 증인이라는 역할을 사용하면 세가지 협력을 모두 포괄할 수 있는 하나의 협력으로 추상화 할 수 있다.

 


누군가가 '판사'에게 재판을 요청함으로써 재판이시작된다.
'판사'는 하얀 토끼에게 증인을 부를 것을 요청한다.
'판사'의 요청을 받은 토끼는 '증인'에게 증인석으로 입장할 것을 요청한다.
'증인'은 증인석에 입장함으로써 토끼의 요청에 응답한다.
'증인'의 입장은 왕이 토끼에게 요청했던 증인 호출에 대한 응답이기도 하다.
이제 '판사'는 '증인'에게 증언하 것을 요청한다.
'증인'은 자신이 알고 있는 내용을 증언함으로써 '판사'의 요청에 응답한다.


=> 역할은 협력 내에서 해당 역할을 수행할 수 있는 다른 객체로 대체할 수 있음

 

수신할 수 있는 메시지를 동일한 방식으로 이해해야한다.
판사가 수신할 수 있는 '재판하라'라는 메시지를 동일하게 이해하고 처리할 수 있다.
증인은 증인석에 입장하라, 증언하라 라는 메시지를 이해할 수 있다.
=> 대체할 수 있는 객체는 동일한 메시지를 이해라 수 있는 객체로 한정된다.
=> 동일한 책임의 집합을 수행하 수 있다.

 

다양한 객체들이 동일한 협력에 참여할 수 있기 때문에 재사용성이 높아진다.
객체지향 설계의 단순성, 유연성, 재사용성을 뒷받침한다.

 

협력의 추상화

 

설계자가 다뤄야 하는 협력의 개수를 줄이는 동시에 구체적인 객체를 추상적인 역할로 대체함으로써 협력의 양상을 단순화한다.
=> 애플리케이션의 설계를 이해하고 기억하기 쉬워진다.

구체적인 객체를 추상적인 역할로 대체함(판사-하얀토끼-증인) 하나의 추상적인 협력으로 대체할 수 있다.

 

대체 가능성

 

역할은 다른 객체에 의해 대체 가능함을 의미한다.
=>역할이 수행하는 모든 책임을 동일하게 수행할 수 있어야한다.

 

객체가 주어진 책임 이외에 다른 책임을 수행할 수도 있다.왕은 재판할 책임뿐만 아니라 국정을 돌봐야할 추가 책임이 있다.
모자 장수는 증언도하고 모자 판매도한다.
=> 객체는 역할이 암시하는 책임보다 더 많은 책임을 가질 수 있다. 객체의 타입과 역할 사이에는 일반화/특수화 관계가 성립한다.

 

협력을 따라 흐르는 객체의 책임

 

객체에게 책임을 할당하고 나면 책임은 객체가 외부에 제공하게 될 행동이 된다.
행동을 결정한 후 그 행동을 수행하는데 필요한 데이터 고민한다.->클래스의 구현방법을 결정해야한다.
=> 클래스와 데이터는 협력과 책임의 집합이 결정된 후에야 무대 위에 등장할 수 있다.

일련의 책임을 먼저 고안 -> 그 책임을 수행하는 데 필요한 객체 선택 -> 책임을 각 객체에 할당 -> 외부에 제공하게 될 행동 정의 -> 필요로 하는 데이터 정의 -> 클래스 개발

 

객체지향 설계 기법

 

책임-주도 설계 방법은 협력에 필요한 책임들을 식별하고 적합한 객체에게 책임을 할당한다.
디자인패턴은 반복적으로 사용하는 해결 방법을 정의해 놓은 설계 템플릿 모음(이미 식별해 놓은 역할, 책임, 협력의 모음)
테스트-주도 개발은 테스트를 먼저 작성하고 테스트를 통과하는 구체적인 코드를 추가하면서 애플리케이션을 완성해가는 방식
테스트가 아니라 설계를 위한 기법, 역할,책임,협력을 식별하고 적합한지를 피드백 받는 것

 

책임-주도 설계

욕를 만족시킬 수 있는 기능을 제공하는 동시에 이해하기 쉽고, 단순하며, 유연한 상호작용을 제공하는 객체들의 공동체 구축
협력 관계를 고안하고, 협력에 필요한 역할과 책임을 식별한 후 이를 수행할 수 있는 적절한 객체를 식별해 나가는 과정


객체지향 설계의 핵심은 올바른 책임을 올바른 객체에게 할당하는 것

시스템이 사용자에게 제공해야 하는 기능인 시스템 책임을 파악한다.
시스템 책임을 더 작은 책임으로 분할한다.
분할된 책임을 수행할 수 있는 적절한 객체 또는 역할을 찾아 책임을 할당한다.
객체가 책임을 수행하는 중에 다른 객체의 도움이 필요한 경우 이를 책임질 적절한 객체 또는 역할을 찾는다.
해당 객체 또는 역할에게 책임을 할당함으로써 두 객체가 협력하게 한다.

 

디자인 패턴

책임-주도 설계의 결과를 표현한다. 이전의 훌륭한 결과물을 모방하고 약간의 수정을 거쳐 원하는 결과물을 만들어 낸다는 것, 특정한 상황에서 설계를 돕기 위해 모방하고 수정할 수 있는 과거의 설계 경험이다.

 

문제와 그 문제에 대한 해법의 쌍으로 정의된다. 패턴은 해결하려고 하는 문제가 무엇인지를 명확하게 서술하고, 패턴을 적용할 수 있는 상황과 적용할 수 없는 상황을 함께 설명한다.

 

테스트 주도 개발

 

애자일 방법론의 한 종류인 XP의 기본 프랙티스
실패하는 테스트를 작성하고 , 테스트를 통과하는 가장 간단한 코드 작성 한다. 리팩토링을 통해 중복을 제거한다. -> 작동하는 깔끔한 코드를 얻을 수 있다.

 

응집도가 높고 결합도가 낮은 클래스로 구성된 시스템을 개발할 수 있다.
초보자들에겐 어떤 테스트를 어떤식으로 작성해야 하는지를 결정하는 데 큰 어려움을 느낀다.

 

책임-주도 설계를 통해 도달해야 하는 목적지를 테스트라는 안전장치를 통해 좀 더 빠르고 견고한 방법으로 도달할 수 있도록 해주는 최상의 설계 프랙티스

 

회고

 

간단한 게시판 프로그램 짤 때가 기억이 났다. 문제로 여러 클래스 이름이 주어지고 각 클래스를 만들고 기능을 구현해야했다. 처음에는 무작정 필요한 데이터를 넣고 필요기능을 넣기 시작하니 각각 클래스간의 관계가 너무 복잡해 질 것 같았다.

 

하던 것을 멈추고 구조를 생각했다. 이 클래스는 사용자가 메뉴를 보는 클래스, 이 클래스는 게시판을 수정삭제추가하는 기능을 가진 클래스, 게시판정보를 가진클래스에게 '역할'을 찾았다. 그러니 어느쪽으로 '메시지'를 보내야하는지와 메시지를 받아 '응답'하는 책임이 보이기 시작했다.

 

그 문제를 제한시간내에 다 완성하지는 못했지만 처음으로 단순한 알고리즘이 아닌 처음으로 전체적인 구조를 생각해본 경험이었다. 이 책에서 내가 경험해 본 내용을 구체적으로 표현해 주어서 공감가며 읽었다.

반응형