역할

책임의 집합이 의미하는

어떤 객체가 수행하는 책임의 집합은 객체가 협력 안에서 수행하는 역할을 암시한다.

역할은 재사용 가능하고 유연한 객체지향 설계를 낳는 매우 중요한 구성요소.

 

재사용 관점을 중심 예시

김 의사가 진료를 하다, 박 의사와 교대를 해도 의사 역할 수행에는 문제가 없다.

즉, 역할 관점에서는 변화된 것이 하나도 없다.(인터페이스라 생각해보자)

 

역할이 답이다

역할을 사용하면 하나의 협력으로 추상화 있다.

역할은 협력 내에서 다른 객체로 대체할 있다

, 역할을 대체할 있는 객체는 동일한 메시지를 이해할 있는 객체로 한정 된다.

 

메시지는 책임을 의미한다.

동일한 역할을 수행한다는 것은 협력 내에서 동일한 책임의 집합을 수행한다는 것이다.

부분은 객체지향에서 매우 중요한 개념이다.

 

역할의 개념을 사용하면 유사한 협력을 추상화해서 인지 과부하를 줄일 있다.

다양한 객체들이 동일한 협력에 참여할 있기 때문에 재사용성이 높아진다.

역할은 객체지향 설계의 단순성(simplicity), 유연성(flexibility), 재사용성(resuability) 뒷받침하는 핵심 개념이다.

 

협력의 추상화

역할의 가치는 협력을 추상화할 있다는 것이다.

협력의 개수를 줄여 보다 추상적인 역할로 단순화해 이해하기 쉬워진다.

협력의 추상화는 근본적으로 역할의 대체 가능성에서 비롯된다.

 

 

대체 가능성

객체가 역할에 주어진 책임 이외에 다른 책임을 수행할 수도 있다.

증인 역할에 모자장수는 추가 책임으로 모자 판매를

요리사도 추가 책임으로 요리를 한다.

 

객체는 역할이 암시하는 책임보다 많은 책임을 가질 있다.

따라서 대부분의 경우 객체의 타입과 역할 사이에는 일반화/특수화(추상화/구체화) 관계가 성립한다.

 

역할의 대체 가능성은 행위 호환성을 의미한다.

행위 호환성은 동일한 책임의 수행을 의미한다.

 

 

객체의 모양을 결정하는 협력

흔한 오류

데이터를 저장하기 위해 객체가 존재한다는 선입견

데이터는 객체가 행동(책임) 수행하는 필요한 재료일 뿐이다.

 

객체지향이 클래스와 클래스 간의 관계를 표현하는 정적인 측면에 중점을 둔다는 오류

중요한 것은 협력에 참여하는 동적인 객체이다.

클래스는 단지 객체를 표현하고 생성하기 위한 프로그래밍 매커니즘이다.(실제로 클래스가 없는 객체지향 언어 자바스크립트)

 

데이터나 클래스 중심으로 애플리케이션을 설계하는 오류

협력이라는 문맥을 고려하지 않고 객체를 독립적으로 보면 안된다.

 

 

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

협력이라는 문맥 속에서 객체가 수행하게 책임(행동)결정

이후 필요한 데이터를 고민

데이터와 행동이 결정된 클래스 구현 방법 결정(책임 할당)

클래스와 데이터는 협력과 책임의 집합이 결정된 고려

 

 

객체지향 설계 기법

역할, 책임, 협력의 관점에서 애플리케이션 설계하는 유용한 가지 기법

 

책임 주도 설계(Responseibility-Driven Design) 방법

협력에 필요한 책임들을 식별, 적합한 객체에게 책임을 할당하는 방식으로 애플리케이션 설계

 

디자인 패턴(Design Pattern)

전문가들이 반복적으로 사용하는 해결 방법을 정의해 놓은 설계 템플릿의 모음

특정 문제를 해결하기 위해 이미 식별해 놓은 역할, 책임, 협력의 모음

베스트 프렉티스

 

테스트 주도 개발(Test-Driven Development)

테스트를 먼저 작성하고 테스트를 통과하는 구체적인 코드를 추가하면서 애플리케이션을 완성해가는 방식

 

책임-주도 설계

객체지향 시스템은 역할과 책임을 수행하는 자율적인 객체들의 공동체다.

 

레베카 워프스브록-책임주도설계 방법을 말한다.

 

시스템의 기능은 작은 규모의 책임으로 분할

책임은 책임을 수행할 적절한 객체에게 할당

이제 객체가 책임을 수행하는 도중 스스로 처리 못할 적절한 객체를 찾아 필요한 작업 요청(협력)

 

디자인 패턴

책임 주도 설계는 객체의 역할, 책임, 협력을 고안하기 위한 방법과 절차를 제시한다.

반면 디자인 패턴은 책임-주도 설계의 결과 표현한다.

모범이 되는 설계

 

앨리스터 코오번에 따르면 효과적으로 일하는 사람들의 가지 특징은 아무것도 없는 상태에서 작업을 시작하지 않고 이전의 훌륭한 결과물을 모방하고 약간의 수정을 거쳐 원하는 결과물을 만들어 낸다는 것이다.

패턴은 특정한 상황에서 설계를 돕기 위해 모방하고 수정할 있는 과거의 설계 경험이다.

 

디자인 패턴은 반복적으로 발생하는 문제와 문제에 대한 해법의 쌍으로 정의된다.

해결하려고하는 문제가 무엇인지 서술하고, 패턴을 적용할 있는 상황과 없는 상황을 함께 설명한다.

패턴은 반복해서 일어나는 특정한 상황에서 어떤 설계가 (why) 효과적인지에 대한 이유를 설명한다.

테스트-주도 개발

애자일 방법론의 종류인 XP 기본 프랙티스로 소개되며 주목받음

기본 흐름은 실패하는 테스트를 작성하거, 테스트를 통과하는 가장 간단한 코드를 작성한 ( 과정에서 중복은 허용된다) 리팩터링을 통해 중복을 제거하는 것이다.

테스트-주도 개발을 통해 '작동하는 깔끔한 코드' 얻을 있다.

 

테스트 주고 개발이 응집도 높고 결합도 낮은 클래스로 구성된 시스템을 개발할 있게 하는 최상의 프랙티스이지만 객체지향 초보에게는 테스트를 어떤 식으로 작성해야하는지 결정하는데 어렵다.

테스트-주도 개발은 다양한 설계 경험과 패턴에 대한 지식이 없는 사람들의 경우에는 온전한 혜택을 누리기가 어렵다.

객체지향에 대한 깊이 있는 지식을 요구한다.

객체지향과 인지 능력

인간은 직접적으로 지각할 있는 사물을 넘어 추상적인 사물까지도 객체로 인식할 있는 능력이 있다. 어제 주문내역과 오늘 주문내역을 구분하는 , 출금 계좌에서 동일한 입금 계좌로 동일한 금액을 이체하더라도 구분이 가능하다.

물리적인 실체는 존재하지 않더라도 인간이 쉽게 구분하고 하나의 단위로 인지할 있는 개념적인 객체의 일종이다.

 

복잡한 세상에서 인간은 단순한 객체들로 주변을 분해함으로써 세상을 이해하려고 노력한다.

, 객체란 인간이 분명하게 인지하고 구별할 있는 물리적인 또는 개념적인 경계를 지닌 어떤 이다.

 

객체지향 패러다임은 인간이 인지할 있는 다양한 객체들이 모여 현실 세계를 이루는 것처럼 소프트웨어의 세계 역시 인간이 인지할 있는 다양한 소프트웨어 객체들이 모여 이뤄져 있다는 믿음에서 출발한다.

객체지향 패더라임의 목적은 현실 세계를 모방하는 것이 아니라 현실 세계를 기반으로 새로운 세계를 창조하는 것이다. 따라서 현실 세계 객체와 소프트웨어 세계의 객체와는 전혀 다른 모습을 보이는 것이 일반적이다.

 

예로 현실세계 전등은 사람없이 껏다 킬수 없다. 소프트웨어 전등은 자동으로 가능하다.

 

객체, 그리고 이상한 나라

이상한 나라의 앨리스

앨리스 이야기로 예시를 든다. 이야기 내용을 요약하면,

작은 문을 통과하기 위해, 주변 음식을 먹으면서 몸집을 줄였다가 늘렸다 한다.

앨리스 객체

앞의 이야기는 앨리스가 겪고 있는 키의 변화에 초점을 맞추고 있다.

앨리스는 정원으로 가기 위해 자신의 상태 계속 변화시켰다.

이런 상태변화는 앨리스의 행동이다. 앨리스 행동에 따라 앨리스 상태가 변한다.

 

상태를 결정하는 것은 행동이지만 행동의 결과를 결정하는 것은 상태이다.

예를들어, 앨리스 130cm 여기에 케이크를 먹어서 150cm 커졌다. 그럼 원래 상태 130cm + 150cm

280cm 된다.

, 앨리스가 행동의 결과는 앨리스의 상태에 의존적이다.

어떤 행동의 성공 여부는 이전에 어떤 행동들이 발생했는지에 영향을 받는다는 사실도 중요하다

앨리스가 문을 성공적으로 통과하기 위해서는 문을 통과할 있을 정도로 충분히 몸을 작게 중여야 한다. 따라서 앨리스는 문을 통과하기 전에 먼저 키를 작게 줄이기 위해 안의 음료나 케이크를 먹어야 한다.

이것은 행동 간의 순서가 중요하다는 것을 의미한다. 문을 통과하는 행동이 성공하려면 음료나 케이크를 먹는 행동이 선행돼야만 한다.

 

 

객체, 그리고 소프트웨어 나라

물리적인 또는 개념적인 사물은 어떤 것이라도 객체가 있다.

인간의 인지 능력 안에서 개수를 있고, 다른 사물과 구분할 있으며, 생성 시점을 있고, 독립적인 하나의 단위로 인식할 있는 모든 사물은 객체다.

 

객체의 다양한 특성을 효과적으로 설명하기 위해선 객체를 상태(state), 행동(behavior), 식별자(identity) 지닌 실체로 보는 것이 가장 효과적이다.

 

책에서 객체를 다음과 같이 정의한다.

객체란 식별 가능한 개제 또는 사물이다. 객체는 자동차처럼 만질 수 있는 구체적인 사물일 수도 있고, 시간처럼 추상적인 개념일 수도 있다. 객체는 구별 가능한 식별자, 특징적인 행동, 변경 가능한 상태를 가진다. 소프트웨어 안에서 객체는 저장된 상태와 실행 가능한 코드를 통해 구현된다.

 

 

상태

상태가 필요한가

객체가 주변 환경과의 상호작용에 어떻게 반응하는가는 시점까지 객체에 어떤 일이 발생했느냐에 좌우된다.

예를들어 비행기를 이용하려면 탑승 전에 발권이 필수다.

자판기에 음료를 먹기위해서는 충분한 돈을 넣어야 한다.

 

공통점은 어떤 행동의 결과는 과거에 어떤 행동들이 일어났었느냐에 의존한다는 것이다.

 

일반적으로 과거에 발생한 행동이력을 통해 현재 발생한 행동의 결과를 판단하는 방식은 복잡하고 번거롭고 이해하기 어렵다.

행동과정과 결과를 단순하게 기술하기 위한 상태라는 개념을 고안했다.

비행기 탑승 가능 여부는 항공권의 발권 상태를 보고 예측할 있다.

자판기는 현재까지 투입된 금액의 상태를 기억한다.

 

상태를 이용하면 과거의 모든 행동이력을 설명하지 않고도 행동의 결과를 쉽게 예측하고 설명할 있다.

앨리스가 과거에 어떤 행동을 했었는지 모르더라도 앨리스의 키만 알면 문을 통과할 있는지 여부를 쉽게 판단할 있다.

앨리스 키와 문높이 두가지 상태만 알면 문을 통과하는 행동의 결과를 쉽게 예측할 있다.

 

 

상태와 프로퍼티

앨리스는 객체다. 앨리스의 키를 줄이거나 늘리기 위해 사용하는 음료, 케이크, 부채, 버섯 모두 객체다. 모두 뚜렷한 경계를 가지며 식별 가능하고 상태와 행동을 지니고 있다.

 

그러나 세상에 모든 것들이 객체인 것은 아니다. 앨리스의 '' 위치' 객체가 아니다. 음료의 '' 객체가 아니다. 문이 열렸는지 '여부' 객체가 아니다

, 숫자, 문자열, , 속도, 시간, 날짜, 참/거짓과 같은 단순한 값들은 객체가 아니다.

단순값들은 자체로 독립적인 의미를 가지기보다는 다른 객체의 특성을 표현하는데 사용된다.

 

때로는 단순한 값이 아니라 객체를 사용해 다른 객체의 상태를 표현해야 때가 있다.

앨리스가 음료를 들고 있는 상태를 표현하기 위해 /거짓이 아닌 음료 객체를 이용해 표현하는 것이다. 음료를 들고있나 없나는 음료객체와 연결됐나 안됐나로 구분한다.

결론적으로 모든 객체의 상태는 단순한 값과 객체의 조합으로 표현할 있다.

객체의 상태를 구성하는 모든 특징을 통틀어 객체의 프로퍼티(property)라고 한다.

앨리스 기준 ,위치,음료가 프로퍼티다.

일반적으로 프로퍼티는 변하지 않는 정적이다. 반면 프로퍼티의 값은 변할 있는 동적이다.

 

다른 시점에서 앨리스를 봤는데 음료와 연결이 없다. 음료를 버린 것으로 보인다.

시점에서 앨리스는 음료에 대한 상태를 모른다.

이처럼 객체와 객체 사이의 의미 있는 연결을 링크(link)라고 한다.

 

객체 사이 링크를 통해서만 요청을 주고 응답을 받을 있다.

, 링크를 통해서만 협력이 가능하다

 

객체 간의 선으로 표현되는 링크와 달리 객체를 구성하는 단순 값은 속성(attribute)이라고 한다.

따라서 앨리스의 키와 위치는 속성이다.

 

조합하면 프로퍼티는 단순 값인 속성과 객체와 연결을 가르키는 링크 조합이다.

 

이 책에서는 객체의 상태를 다음과 같이 정의하기로 한다.

상대는 특정 시점에 객체가 가지고 있는 정보의 집합으로 객체의 구조적 특징을 표현한다.

객체의 상태는 객체에 존재하는 정적인 프로퍼티와 동적인 프로퍼티 값으로 구성된다.

객체의 프로퍼티는 단순한 값과 다른 객체를 참조하는 링크로 구분할 수 있다.

 

객체는 자율적인 존재라는 것을 명심하라

객체지향의 세계에서 객체는 다른 객체의 상태에 직접적으로 접근할 수도, 상태를 변경할 수도 없다.

자율적인 객체는 스스로 자신의 상태를 책임져야 한다.

외부의 객체가 직접적으로 객체의 상태를 주무를 없다면 간접적으로 객체의 상태를 변경하거나 조회 있는 방법이 필요하다.

 

행동은 다른 객체로 하여금 간접적으로 객체의 상태를 변경하는 것을 가능하게 한다.

객체지향의 기본 사상은 상태와 상태를 조작하기 위한 행동을 하나의 단위로 묶는 것이라는 점을 기억하라

객체는 스스로의 행동에 의해서만 상태가 변경되는 것을 보장함으로써 객체의 자율성을 유지한다.

 

 

 

 

 

협력 속에 사는 객체

역할, 책임, 협력

실제로 협력에 참여하는 주체는 객체.

실행 중 인 어플리케이션을 보면 객체들간에 메시지를 주고받으면서 협력하는 것을 있다. 이렇듯 객체가 없으면 객체지향 세계 역시 아무런 의미가 없다. 객체지향이라 부르는 이유는 패러다임의 중심에 객체가 있기 때문이다.

 

객체는 애플리케이션의 기능을 구현하기 위해 존재한다. 작은 기능조차 객체 혼자 감당하기에는 버거울 정도로 복잡 거대하다. 때문에 객체는 다른 객체와의 협력을 통해 기능을 구현하게 된다.

따라서 협력이 얼마나 조화를 이루는지 결정하는 것은 객체다.

결국 협력의 품질을 결정하는 것은 객체의 품질이다.

 

협력 공동체의 일원으로 객체는 가지 덕문을 갖춰야 한다.

첫째, 객체는 충분히 협력적이어야 한다.

모든 것을 스스로 처리하려고 하는 전지전능한 객체는 내부적인 복잡도에 의해 자멸하고 만다

 

둘째, 객체가 충분히 자율적이어야 한다.

자기 스스로의 원칙에 따라 어떤 일을 하거나 자기 스스로를 통제하여 절제하는 것을 의미한다.

객체는 다른 객체에 명력에 복종하는 것이 아니라 요청에 응답할 뿐이다. 어떤방식으로 응답할지는 객체 스스로 판단하고 결정한다.

심지어 요청에 응할지 여부도 객체 스스로 결정할 있다.

 

객체 공동체에 속한 객체들은 공동의 목표를 달성하기 위해 협력에 참여하지만 스스로의 결정과 판단에 따라 행동하는 자율적인 존재.

 

 

상태와 행동을 함께 지닌 자율적인 객체

객체를 상태(state) 행동(behavior) 함께 지닌 실체라고 정의한다.

이 말은 객체가 협력에 참여하기 위해 어떤 행동을 한다면 행동을 하는 필요한 상태도 함께 지니고 있어야 한다는 것을 의미한다.

 

객체가 협력에 참여하는 과정 속에서 스스로 판단하고 스스로 결정하는 자율적인 존재로 남기 위해서는 필요한 행동과 상태를 함께 지니고 있어야 한다.

 

객체의 자율성은 객체의 내부와 외부를 명확하게 구분하는 것으로부터 나온다.

객체의 사적인 부분은 객체 스스로 관리하고 외부에서 일체 간섭할 없도록 차단해야 하며, 객체의 외부에서는 접근이 허락된 수단을 통해서만 객체와 의사소통해야 한다.

객체는 다른 객체가 무엇(What) 수행하는지는 있지만 어떻게(how) 수행하는지에 대해서는 없다.

 

커피를 주문하는 협력 과정에 참여한 손님과 캐시어, 바리스타는 외부의 간섭을 받지 않고 스스로 생각하고 스스로 판단하는 자율적인 존재였다.

객체의 관점에서 자율성이란 자신의 상태를 직접 관리하고 상태를 기반으로 스스로 판단하고 행동할 있음을 의미한다.

객체는 행동을 위해 필요한 상태를 포함하는 동시에(바리스타는 커피 제조 방법을 기억하고 있다) 특정한 행동을 수행하는 방법을 스스로 결정할 있어야 한다.(바리스타는 자신이 알고 있는 방법에 따라 커피를 제조한다)

따라서 객체는 상태와 행위를 하나의 단위로 묶은 자율적인 존재다.

 

과거 전통적인 개발 방법은 데이터와 프로세스를 엄격하게 구분한다

이에 반해 객체지향에서는 데이터와 프로세스를 객체라는 하나의 안에 함께 묶어 놓음으로써 객체의 자율성을 보장한다.

자율적인 객체로 구성된 공동체는 유지보수가 쉽고 재사용이 용이한 시스템을 구축할 있는 가능성을 제시한다.

 

 

 

협력과 메시지

커피를 주문하기 위해 협력하는 사람들은 자신의 책임을 다하기 위해 다른 사람들에게 도움을 요청한다.

다양한 요청 방법이 있을 것이다.

 

객체지향의 세계에서는 오직 가지 의사소통 수단만이 존재한다. 이를 메시지라고 한다.

객체가 다른 객체에게 요청하는 것을 메시지를 전송한다고 다른 객체로부터 요청을 받는 것을 메시지를 수신한다고 말한다.

결과적으로 객체는 협력을 위해 다른 객체에게 메시지를 전송하고 다른 객체로부터 메시지를 수신한다.

 

 

메서드와 자율성

객체는 다른 객체와 협력하기 위해 메시지를 전송한다.

수신자는 먼저 수신된 메시지를 이해할 있는지 여부를 판단한 미리 정해진 자신만의 방법에 따라 메시지를 처리한다. 이처럼 체가 수신된 메시지를 처리하는 방법을 메서드라고 부른다.

 

객체지향 프로그래밍 언어에서 메서드는 클래스 안에 포함된 함수 또는 프로시저를 통해 구현된다.

다른 프로그래밍 언어와 객체지향 프로그래밍 언어를 구분 짓는 핵심적인 특징 하나다.

 

메시지(요청) 메서드의 분리는 객체의 협력에 참여하는 객체들 간의 자율성을 증진시킨다.

커피를 주문하는 협력과정에서 커피 제조를 요청받은 바리스타는 커피머신, 수제 커피 등등 제조 방법을 자율적으로 선택할 있다.

 

객체지향에 대입하면 커피 주문이 요청, 커피 제작하는 방법은방법은 메서드다

커피 제조를 요청한 사람은 어떻게 커피를 제조하는지 구체적인 방법을 모른다.(자율성 보장)

 

외부의 요청이 무엇인지 표현하는 메시지와 요청을 처리하기 위한 구체적인 방법인 메서드를 분리하는 것은 객체의 자율성을 높이는 핵심 메커니즘이다. 이것은 캡슐화라는 개념과도 깊이 관련돼 있다.

 

 

 

 

객체지향의 본질

객체지향이란 시스템을 상호작용하는 자율적인 객체들의 공동체로 바라보고 객체를 이용해 시스템을 분할하는 방법

자율적인 객체란 상태와 행위를 함께 지니며 스스로 자기 자신을 책임지는 객체를 의미한다.

객체는 시스템의 행위를 구현하기 위해 다른 객체와 협력한다. 각 객체는 협력 내에서 정해진 역할을 수행하며 역할은 관련된 책임의 집합이다.

객체는 다른 객체와 협력하기 위해 메시지를 전송하고, 메시지를 수신한 객체는 메시지를 처리하는 데 적합한 메서드를 자율적으로 선택한다.

 

 

객체를 지향하라

클래스가 객체지향 프로그래밍 언어의 관점에서 매우 중요한 구성요소인 것은 분명하다

하지만 객체지향의 핵심을 이루는 중심 개념이라고 말하긴 무리가 있다.

자바스크립트 같은 프로토타입 기반의 객체지향 언어에서는 클래스가 존재하지 않으며 오직 객체만이 존재한다. 프로토타입 기반의 객체지향객체지향 언어에서는 상속 역시 클래스가 아닌 객체 간의 위임 메커니즘을 기반으로 한다.

지나치게 클래스를 강조하는 프로그래밍 언어적인 관점은 객체의 캡슐화를 저해하고 클래스를 서로 강하게 결합시킨다.

 

객체지향 설계의 관점을 코드를 담는 클래스의 관점에서 메시지를 주고받는 객체의 관점으로 변환해야 한다.

중요한 것은 어떤 클래스가 필요한가 가 아니라 어떤 객체들이 어떤 메시지를 주고받으며 협력하는 가다. 클래스는 객체들의 협력 관계를 코드로 옮기는 도구에 불과하다.

 

클래스의 구조와 메서드가 아니라 객체의 역할, 책임, 협력에 집중하라. 객체지향은 객체를 지향하는 것이지 클래스를 지향하는 것이 아니다.

 

+ Recent posts