본문 바로가기
Develop/Java

역할, 책임, 협력 관점으로 객체지향 살펴보기

by 연로그 2021. 1. 15.
반응형

객체

: 상태, 행동, 식별자를 지닌 실체

상태: 특정 시점에 객체가 가진 정보의 집합. 객체의 구조적 특징을 표현.

행동: 외부의 요청에 응답하기 위해 동작하고 반응하는 활동. 

- 코딩을 할 때 상태가 아닌 '행동'에 초점을 맞추는 것이 좋다. 행동이 상태를 결정한다.

 

값은 불변 상태이지만 객체는 가변 상태이다. 행동을 통해 상태를 변경한다.

  ( ex: 이상한 나라의 앨리스에서 앨리스는 '케이크를 먹음'으로서 '키'라는 상태가 작아진다. )

 

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

  또한 객체에게 할당되는 책임이 자율적이어야 한다. 지나치게 추상적이거나 지나치게 구체적인 책임은 문제가 된다.

- 책임이 자율적일 수록 적절하게 추상화되며, 응집도가 높아지고, 결합도가 낮아지며, 캡슐화가 증진되고 인터페이스와 구현이 명확히 분리되며, 설계의 유연성재사용성이 증가된다.

 

 

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

  ( 한 역할에 대해 다른 객체가 맡을 수 있으므로.

   ex: 판사라는 직책에는 A라는 사람이 될 수 있고 B라는 사람이 될 수도 있다.

        A는 판사라는 직책에 대한 책임 외에도 A라는 책임을 수행할 수도 있다.)

- 역할의 대체 가능성은 행위 호환성을 의미하고, 행위 호환성은 동일한 책임의 수행을 의미한다.

 

- 올바른 객체를 설계하기 위해서는 정적인 것보다 동적인 것에 초점을 둬야 한다.

  협력이라는 문맥에서 객체가 수행할 책임(행동)을 결정한 후, 행동을 수행하는 데 필요한 데이터를 결정해야 한다.

  결과적으로 클래스와 데이터는 협력과 책임의 집합이 결정된 후에 나타나게 된다.

 

- 훌륭한 객체: 구현을 모른 채 인터페이스만 알면 쉽게 상호작용할 수 있는 객체

 

객체지향

객체지향에서 중요한 것은 역할, 책임, 협력을 구분하는 것이다.

역할: 협력 안에서 특정 객체가 차지하는 책임이나 임무. (=특정한 책임을 암시)

책임: 객체에 의해 정의되는 응집도 있는 행위의 집합.

협력: request와 response를 통해 다른 객체와 협력.

 

 예를 들어, 손님이라는 역할은, 카페에서 캐셔에게 커피를 주문한다.

캐셔는 커피가 준비됐다는 사실을 손님에게 알리는 책임을 성실히 수행한다.

이제 손님은 제조된 커피를 받아 회사로 돌아간다는 책임을 수행한다.

커피를 받아 들고 엘리베이터를 타고 나면 커피 주문이라고 불리는 협력이 마무리 된다.

 


기본적인 용어들

메소드

: 객체가 수신된 메시지를 처리하는 방법

- 메시지와 메소드의 분리는 객체의 협력에 참여하는 객체 간 자율성 ↑

  ( ex: 커피 제조 요청 == 메시지, 커피 제조하는 구체적 방법 == 메소드 )

 

캡슐화

- 객체는 상태를 캡슐 안에 감춰두고 행동만 노출한다. (행동은 외부에서 객체에 접근할 수 있는 유일한 방법)

- 캡슐화로 인해 객체의 자율성이 높아지고 협력은 유연하고 간결해진다.

 

식별자

: 객체를 서로 구별할 수 있는 특정한 프로퍼티

- 모든 객체는 식별자를 가진다. (=객체가 아닌 단순한 값은 식별자를 가지지 않는다.)

- 값은 식별자를 가지지 않아 상태를 이용한 동등성 검사를 통해 두 인스턴스를 비교

- 객체는 상태가 변경될 수 있어 식별자를 이용한 동일성 검사를 통해 두 인스턴스를 비교

 

개념 (타입)

: 객체에 적용할 수 있는 아이디어나 관념

- 특정 객체가 어떤 그룹에 속할 것인지 결정하는 것

 

- 심볼; symbol : 개념을 가리키는 간략한 이름/명칭

- 내연; intension : 개념의 완전한 정의. 객체가 개념에 속하는지 여부

- 외연; extension : 개념에 속하는 모든 객체의 집합

 

 예를 들어, 이상한 나라의 앨리스에서는 여러 인물이 등장한다.

장미를 칠하던 정원사, 왕, 왕비, 그들의 병사 등은 몸이 종이처럼 되어있고, 모두 트럼프에 포함된다. 

여기서 정원사, 왕, 왕비, 병사는 외연이고 몸이 종이처럼 되어있다는 내연, 트럼프는 심볼이다.

 

- 객체를 적절한 개념에 따라 분류한 애플리케이션은 유지보수가 용이하고 변경에 유연하게 대처할 수 있다.

 

- 동적 분류: 객체가 자신의 타입을 변경할 수 있는 경우

- 정적 분류: 객체가 자신의 타입을 변경할 수 없는 경우

 

일반화/특수화

- 일반화/특수화 관계를 결정하는 것은 객체 상태를 표현하는 데이터가 아닌 행동이다.

- 특수한 타입은 일반적인 타입에 비해 더 많은 행동을 가진다. 일반적인 타입이 할 수 있는 행동을 동일하게 수행할 수도 있어야 한다.

- 일반적인 타입을 슈퍼 타입, 좀 더 특수한 타입을 서브 타입이라고 한다.

  슈퍼타입 ◁ㅡ 서브 타입으로 표현할 수 있다.

 

 예를 들어, 이상한 나라의 앨리스에는 트럼프 인간과 평범한 인간(앨리스)이 등장한다.

트럼프 인간과 평범한 인간은 모두 '납작 엎드리거나', '뒤집어질 수 있다'.

여기서 트럼프 인간은 '걸을 때마다 몸을 종이처럼 펄럭일 수 있다'는 행동이 가능하다.

 

동적/정적 모델

- 스냅샷: 객체가 특정 시점에 구체적으로 어떤 상태를 가지는지

         (UML에서 객체 다이어그램이라고도 불린다.)

- 동적 모델: 실제로 객체가 움직이는 동안 상태가 어떻게 변하고 어떻게 행동하는지 포착하는 것

- 정적 모델: 객체가 가질 수 있는 모든 상태와 모든 행동을 시간에 독립적으로 표현한 것 (=타입 모델)

 

클래스

!= 타입

- 타입을 구현할 수 있는 여러 구현 메커니즘 중 하나

 

다형성

: 서로 다른 유형의 객체가 동일한 메시지에 대해 서로 다르게 반응하는 것

- 서로 다른 객체들이 다형성을 만족시킨다 == 객체들이 동일한 책임을 공유한다

 

- 송신자와 수신자 간의 객체 타입에 대한 결합도를 메시지에 대한 결합도로 낮춤으로써 달성한다.

(ex: 판사가 증인에게 '증언하라'라는 메시지를 보냈다. 판사는 증인이 A인지 B인지 C인지 알 필요가 없다. '증인' 역할을 수행할 수 있다면 누구라도 상관 없다. 판사에게 영향을 주지 않고 메시지를 수신할 객체의 타입을 자유롭게 추가할 수 있는 것이다. )

 

인터페이스

: 객체가 다른 객체와 협력하기 위한 접점

- 객체가 어떤 메시지를 수신할 수 있는지가 객체가 제공하는 인터페이스의 모양을 빚는다.

- 객체의 공용 인터페이스와 구현을 분리하라는 것은 객체의 외부와 내부를 분리하라는 것과 같다. 객체의 내/외부를 분리함으로써 객체지향의 힘은 더 강해진다. (공용 인터페이스 == 객체의 외부, 구현 == 객체의 내부)

 


객체지향 설계

: 애플리케이션의 기능을 구현하기 위한 협력 관계를 고안하고, 협력에 필요한 역할과 책임을 식별한 후, 이를 수행할 수 있는 적절한 객체를 식별해내가는 과정

 

책임-주도 설계

: 협력에 필요한 책임들을 식별하고 적합한 객체에게 책임을 할당

- 객체의 역할, 책임, 협력을 고안하기 위한 방법, 절차를 제시한다.

- 애플리케이션을 개발할 때 어떤 방식으로 사고하고 무엇을 기반으로 의사결정을 내리는지 잘 보여준다.

- 시스템의 책임을 더 작은 규모의 책임으로 분할해 객체에게 할당. 객체가 책임을 수행하는 중, 스스로 처리할 수 없는 기능이 필요할 경우 협력자를 찾아 해당 협력자에게 책임을 할당함으로써 객체들의 협력 공동체가 구축한다.

- 어떤 행위가 필요한지 먼저 결정한 후, 이 행위를 수행할 객체 결정하는 것이 핵심 (What/Who 사이클)

 

디자인 패턴

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

- 책임-주도 설계의 결과를 표현한다.

- GOF의 디자인 패턴이 가장 유명하다.

- 공통으로 사용할 수 있는 역할, 책임, 협력의 템플릿

 

테스트-주도 개발

: 테스트를 먼저 작성하고 테스트를 통과하는 구체적 코드를 추가하며 애플리케이션 완성

- 중요한 포인트는 테스트가 아닌 설계를 위한 개발이라는 것이다. 구체적 코드를 작성하며 역할, 책임, 협력을 식별하고 적합한지 피드백을 받는 것이다.

- 테스트 작성 -> 테스트 통과하는 간단한 코드 -> 리팩토링

- 응집도 높고 결합도 낮은 클래스로 구성된 시스템을 개발하는데 최상. 하지만 경험 미숙자들에게는 테스트를 어떤 식으로 작성해야 하는지 결정하는 데 어려움을 겪는다.


객체지향 내의 관점

개념 관점

- 설계: 도메인 안의 개념과 개념들간 관계 표현

- 도메인: 사용자들이 관심 가진 특정 분야/주제

- 소프트웨어: 도메인에 존재하는 문제를 해결하기 위해 개발

- 사용자가 도메인을 바라보는 관점 반영 (실제 도메인 규칙과 제약을 최대한 유사하게 반영)

 

명세 관점

- 소프트웨어 내의 객체들의 책임(인터페이스)에 초점

 

구현 관점

- 객체의 책임을 어떻게 수행할 것인가에 초점을 맞추며 인터페이스 구현에 필요한 속성, 메소드를 클래스에 추가

 

 

좋은 코드는 세 가지 관점을 모두 제공해야 한다.

 


참고: 객체지향의 사실과 오해 / 조영호

 

챕터 6-객체 지도에 관해서는 이해가 잘 안돼서 정리에서 빼두었다.

실무 경험을 쌓고 다시 읽을 때 쯔음엔 이해가 잘 되었으면 좋겠다.

반응형