OBJECT 06 객체간통신(코드스핏츠)
object 책을 강의한 코드스핏츠 유튜브 요약
📜 제목으로 보기
- 참고 유튜브 : https://www.youtube.com/watch?v=navJTjZlUGk
- 정리본: https://github.com/LenKIM/object-book
- 코드: https://github.com/eternity-oop/object
- 책(목차) : https://wikibook.co.kr/object/
ch6. 객체망과 객체간 통신
- 객체지향 관련 책들이 많지는 않다.
- 뻔한 얘기외에 구체적인 사례를 들어주는 책은 드물다.
- 오브젝트 5장: 1234장을 정리
-
객체설계시 좋은 요령
-
지금까지의 theater코드에 요령 적용
- 이 책은 알고있다고 가정하는게 너무 많다 -> 이해 안되는게 정상
- 맨 뒤에서, 책이 참고하고 있는 책 6권이상이 나열되어있음.
- 사전요구사항이 되게 큰 책이다.
-
지금까지의 theater코드에 요령 적용
- 오브젝트 6장부터: 새로운 내용의 시작
-
객체설계시 좋은 요령
-
지금까지의 내용 정리해보기
- 설계 이전에 중요한 것: 책임
- 객체간의
책임(함수)
을 주고받기 위해메세지(객체 인자)
를 사용
- 객체간의
- 그렇다면,
누구에게
책임? 메세지는어떻게
사용? 이 설계의 목표다.- 이 책에서 설계: 코드를 대치하는 기술
- 어차피 돌아가는 코드에 대해 향후 유지보수 등이 쉬워지는 코드를 설계한다
- 구동하는 코드를 만드는 것X -> 구동 코드를 어떻게 배치할 것인가
- 이 책에서 설계: 코드를 대치하는 기술
-
설계
: 코드를객체지향원리에 따라서 <책임>을 객체별로 나눠
배치- 설계요령: 코드를 나누는
요령: 역할책임모델
- 설계요령: 코드를 나누는
-
객체 만드는 이유: 역할(책임=메소드의 집합, 인터페이스?)
-
역할: 책임의 집합
-
책임을 어떤 객체가 가져가야할 것인가부터 부터 이해해야
- 어떤 객체에 그 코드를 할당해줄 것인가를 결정
- 객체지향에 의해 적절한 책임을 객체에 할당하는데, 나눠가지려면 메세지를 주고 받아야한다.
-
책임을 어떤 객체가 가져가야할 것인가부터 부터 이해해야
-
역할: 책임의 집합
- 설계 이전에 중요한 것: 책임
객체간 통신
- 객체가 책임을 나눠갖기 위해 메세지를 통해 주고받으니까
우리는 객체가 책임을 통해 통신하고 있는 네트워크를 생각해볼 수 있다.
-
객체망(object network)
: 역할책임모델 기반으로, 객체간 코드분리가 잘되어있는 형태-
객체망에 소속되어있는 객체끼리
메세지를 주고 받음 -> 책임을 분담/분산해서 나눠가짐
-
-
- 객체간 통신
- 책에서는 다 안다고 가정하고, 메세지를 던지면 다 알아먹는다고 가정하고 있다. 하지만 잘 모른다.
- 실제 객체간통신은 복잡한 문제다
- 객체 1개 가지고는 객체망(역할책임모델기반 객체간코드분리)을 형성할 수 없다
- 일단 객체에 대해서 더 살펴보자.
- 객체는 **내부에
캡슐화
를 이용해서정보은닉
한 상태로, 외부와는메소드를 통해 소통
하고 있다. **- 내부는 안보여준다.
- 외부는 캡슐화된 메소드만 제공해준다.
-
객체는 2개이상이다.
-
서로 내장을 까지 않는 객체끼리는
public interface(껍데기)
를 통해메세지
를 주고 받는다. -
하지만,
현실세계 객체
는 위와 다르게 생겼다.역할과 책임이 서로 틀리기 때문
- 객체의 책임은
수행해야할 업무
- 객체의 역할은
객체가 당면한 어떠한 측면
- 가정에서는 아빠, 회사에서는 사장
- 책임(업무)를 수행하되, 소속공간, 바라보는 측면에 따라
역할
이 달라진다.
- 객체의 책임은
-
-
객체의 본질은
은닉화한 데이터를 자기만 컨트롤 가능
하지만,public한 interface로 외부에 [책임]으로써 노출
- 집안(역할1)에서 돈(은닉화 데이터)을 나(객체1)만 가지고 있으면, 집에서 나만 돈 쓴다(역할1)
- 회사(역할2)돈(은닉화 데이터)을 나(객체1)만 가지고 있으면, 회사에서 나만 돈 쓴다(역할2)
-
은닉화 데이터
를 기준으로 ->책임
=외부에 노출한 public interface
가 정해진다.-
BUT, 데이터는 측면(역할)을 반영하진 않는다.
-
측면
=역할
=객체를 둘러싸고 있는 인터페이스들
이다.- 현실세계 객체는 위처럼 생겼다
- 내부는 캡슐화 -> 데이터 은닉화
-
외부에 보여주는 것은
역할=측면(A사장, B아빠, C남자)
에 따라외부노출되는 메소드는 다른 형태
- 책임: 돈을 준다
- 역할 -> 바깥으로 나가는 측면에 따라 여러가지로
- A: 급여 지급
- B: 용돈 지급
- C: 술값 지급
- <역할참여=측면에따라> 책임(메소드)는 다양하게 나타난다
- 현실세계 객체는 위처럼 생겼다
-
메소드 자체는 객체내 은닉화된 데이터에 의해서만 나올 수 있다.
데이터에 따라, 객체가 가지는 메소드
는 정해져있다. ** **그러나다른 측면(역할)에 따라 여러가지를 구현
해줄 수 있다.
-
-
은닉화 데이터(돈)에 따라 책임(업무, 메소드)는 정해지는데
-
역할에 따라 = 측면에 따라 -> 여러 인터페이스가 구현되는 것은 class
implements 사장, 아빠, 남자
를 통해 여러가지를 구현한다.- **
각 역할에 따라 메소드는 다른 방식으로 각각 구현
된다. **
- **
- 해당 데이터는 나만 가지고 있으므로, 무조건 내가 구현해야한다. 역할에 따라 다르게 구현한다.
-
현실세계 객체는 데이터 때문에 -> 다양한 측면의 메소드를 가지는게 정상
-
책임(메소드)은, 각각 역할에 따라 1개씩 가진다.
- 모든 역할을 가지고 1개의 책임(메소드)만 가지는 것은 불가능. 각각 책임이 만들어진다.
-
책임(메소드)은, 각각 역할에 따라 1개씩 가진다.
-
현실세계 객체는 데이터 때문에 -> 다양한 측면의 메소드를 가지는게 정상
-
역할에 따라 = 측면에 따라 -> 여러 인터페이스가 구현되는 것은 class
-
현실세계 객체(나)는, 다양한 역할(사장, 아빠, 남자)을 가지며, 그 역할에 따라 각각의 책임(급여지급, 용돈지급, 술값지급)을 수행한다.
요점: 나라는 객체가 -> 사장만 impl하거나 아빠만 impl할순 없다 -> 여러역할을 다 imple해서 -> 역할에 따른 여러 책임을 수행한다
- 객체간 통신이 어려운 이유: 객체망내 **다른 객체도 똑같이 중**이다.
역할에>
- 나 = 은닉화데이터에 따라 사장, 아빠 impl 구현 중.
- 옆사람 = 은닉화데이터에 따라 사원, 아들 impl하여 구현중.
- 객체간으로 볼 때, 2 객체의
추상층(추상레이어)
입장에서 볼 수 있다.- 색깔별로 같은 병행 interface를 갖고 있다.
- 인터페이스 수준에서는 색깔별로 같은 놈으로 보인다.
-
but 통신은
서로를 바라보는 측면(역할)에 의해 객체간 통신
이 성립한다.-
역할의 형태(바라보는 측면, 관점)에 따라 통신함
- 파란색 -> 파란색을 바라보는 관점뿐만 아니라
- 파란색 -> 갈색을 바라보는 관점으로 따로 또 통신할 수 있다.
-
역할의 형태(바라보는 측면, 관점)에 따라 통신함
- 색깔별로 같은 병행 interface를 갖고 있다.
-
객체1개에서
각 인터페이스별로 책임과권한
을 따로따로 가지고 있으며책임과권한을 가진 인터페이스를 모두 다 합한 것이 객체
가 된다.- 아빠 -> 아들에게 용돈주는 책임
- 사장 -> 사원에게 급여를 주는 책임
-
각
책임(과 권한)
을 ->인터페이스 Level별로 나눠서
가지고 있다.- 객체 = 떡진 덩어리가 아니라,
[관점별]로 다르게 [구현]
한 것들을 [Type(형)]으로 분리해서 인식한 것
- 객체 = 떡진 덩어리가 아니라,
-
각
- 각각의 **다양한 측면(관점)에 따라
책임과권한
을 구현한 모든 인터페이스를 ** 한꺼번에>- 책임에는, 합당한 권한을 가져야 수행가능
- 아는게 있어야, 뭘 한다
- 다 합친 게 역할 -> 물주
- 책임에는, 합당한 권한을 가져야 수행가능
- **
객체간통신
은 아름답게 [서로 스펙을 알고서 주로 받는게 아니다] **- 각각 여러가지의
책임별 인터페이스
를 가지면서역할
을 수행하는 객체들끼리- 객체1의
일부 책임
-> 객체2의다른 형태의 책임
을 가리키면서 걔와 통신을하는 복잡한 과정이다.
- 객체1의
- 처음부터 파란색의 인터페이스는 -> 상대를 갈색으로 바라보고 메세지를 날릴 준비를 한다.
-
아름답게 아빠(책임A)와 아들(책임a)의 통신이 아니라
아빠(책임A)가 사원(책임b)에게 급여줄 생각
을 하고 있다는 말이다.- 이게 실제 세계의 통신이다. 그룹끼리 묵어서 통신하지 않는다.
-
아름답게 아빠(책임A)와 아들(책임a)의 통신이 아니라
- 실제 객체간통신에 쓰려고 개발해도, 다각도적인 측면에서 복잡한 경우의수가 생기는 이유이다.
- 객체 설계시, 절대 1개인터페이스-1개메소드를 가진 class를 만들 순 없다.
- 왜냐면 그 은닉화된 데이터 -> 발현된 책임들이 정해져서 나오기 때문
- 예제에 나온
Screening
을 예를 들면- 정보를 아는 것 때문에(은닉화된 데이터) -> 어쩔 수 없이 reserve예약도 받게 되었음
- 원래 상영 = 극장에서 영화시작시간을 알고 있는 책임만 있을 뿐인데
- 왜 예약이라는 책임(메소드)를 떠맡았느냐? 상영 지 혼자만 아는 정보이므로 어쩔 수 없이
- Screening
- 인터페이스A: screening 정보의 책임과 권한
- 인터페이스B: reserve()의 책임과 권한
- 형식으로 생긴 것으로 생각해볼 수 있다.
-
실제로는 책임 -> reservator interface를 impl해서 메소드reserve()를 구현해야한다.
- 원래는 명시적으로 만들어서, Type으로 만들어야한다.
- 즉, interface로 만들고 -> class가 impl해서 메소드 구현
- Screening implements
reservator
로 구현한 뒤?- 클라이언트:
reservator(screening).reserve()로 예약
해야한다.?? 이렇게 하면 모순점이 발생안한다.
- 클라이언트:
-
screening이 예약을 하는 모순점이 사라지고, screening impl reservator를 하면 -> reservator가 .reserve()를 하게 되고, Type(형)으로 이해가 된다.
- 책 2장의 모순이 해결된다.
- 원래는 명시적으로 만들어서, Type으로 만들어야한다.
- 각각 여러가지의
통신망의 구성
- 객체가 2개가 아니라 4개 이상을 보자.
- 실제 객체는 어떤일 하기위해 누구에게 도움받았고, 서로 도움을 합체해 다른애들에게 도움을 요청한다.
- 2장 theater도 마찬가지다. screening에게 부탁했더니 movie에게 부탁 -> policy -> condition에게 부탁하고 있다.
- 동시에 2군데에서 부탁하고, 도착한 부탁 2개가 있으면 내부에서 변환하여 -> 1개로 다시 부탁할 수 있다.
-
합체+대기+병합조건 등이 일어나면서 비동기인 경우도 많아서 복잡하다.
- 객체통신은 비동기도 포함해서, 다양한 형들이 다양한 형들과 대화하는 복잡한 망으로 되어있다.
-
합체+대기+병합조건 등이 일어나면서 비동기인 경우도 많아서 복잡하다.
- 이 책을 보는 이유
- 스프링에 있는 controller, service만 주구장창 짜는게 아니라 구성하는 파워를 기르기 위함이다.(이 통신망을 짜기 위함)
- 비즈니스 도메인 -> 코드로 변역하여 통신망을 짜는 힘
- 도메인: 해결해야하는 문제
-
협력하는 객체의 망 + 메시지로 연결할 수 있느냐
- 코드를 분산시킨 그릇들 = 객체들을 만들고
- 메세지로 연결할 수 있느냐
- 두 메세지망의 차이점은?
-
왼쪽: 비선형구조 / 오른쪽: 선형구조 (or 순환구조)
-
일반적으로 순환 통신망 -> 잘못된 구조
- 3개 밖에 없어서 파악했는데, 일반적으로는 파악할 수 없다.
- 설계의 원칙을 지켜서 순환구조를 만들지말자.
-
일반적으로 순환 통신망 -> 잘못된 구조
-
양방향 화살표, 서로 알고 있는 구조가 없어야한다.
-
설계의 목적:
의존성
을 제거할 수 없다 ->단방향화(simplex)
시켜야한다.- 설계 = 코드 대치의 목표 -> 의존성을 단방향화 시키는데 있다.
-
if 조건부을 제거하는 방법? 없다
- 관련된 의존성을 제거할 방법도 없다 ex> 하나카드랑 같이 일하는데, 하나카드 화살표를 제거할 방법 없다.
- 도메인에서 원하는 것들만큼 화살표가 나가야한다. 제거할 방법 없다.
-
우리가 해야할 것은 순환 참조만 일어나지 않게 하는 것이다.
- 직접 순환 뿐만 아니라, 돌다가 오는 것도 막아야한다.
-
설계의 목적:
-
왼쪽: 비선형구조 / 오른쪽: 선형구조 (or 순환구조)
객체설계 난점
- 목표를 알았다. 순환참조를 안한다고 해도 객체설계에 난점들이 많다.
인터페이스의 그룹화
-
인터페이스: 특정 책임을 나타내는 것
- 제일 좋은 인터페이스 : 아무 메소드도 없는 것
- 2번째 좋은 인터페이스 : 메소드 1개 있는 것
- 안좋은 인터페이스 : 메소드 2개이상 있는 것
- 기본적으로 인터페이스 = 메소드 1개만 가진다고 가정하자. 인터페이스를 왜 만들었을 까?
-
인터페이스
는 합당한책임
을추상화
한 것-
책임은 어디서?
도메인
에서 나왔다.-
도메인은
여러 측면
을 가지고 있다.- 사업자, 이용자, 에이전시 각각의 측면을 가지고 있다.
-
도메인은
-
책임은 어디서?
- 즉,
여러 측면
의도메인
에 따라 ->책임
이 관점에 따라여러가지
->추상화한 인터페이스
도여러가지
-
도메인A관점(사업자) 측면에서 -> 여러 책임 -> 추상화한 여러 인터페이스 ABCD
- 도메인B관점(이용자) 측면에서 -> … -> 여러 인터페이스 abcd
- 같은 객체인데, 도메인에 따라 인터페이스도 여러개 추출
- 도메인B관점(이용자) 측면에서 -> … -> 여러 인터페이스 abcd
-
도메인이외에, 추가적인 관점들에 따라 -> 여러 인터페이스들이 마구마구 나온다.
- Player라는 객체를 만든다. 어떻게 바라볼 것이냐에 따라서
- 움직이는 로직관점: 유저직접 / AI / 랜덤으로 / 히스토리기반 으로의 인터페이스들
- 컨트롤러 관점: 조이스틱 / 키보드 / 마우스 으로의 인터페이스들
- …
- …
- 수많은 인터페이스가 많은 관점으로 양산
- 왜? 우리는 책임(메소드)를 추상화하고 싶으니까
- 그 책임이라는 것은 관점이나 도메인에 소속되어있기 때문에 -> 관점에 따라 수많은 책임 도출 -> 추상화하고 싶어서 인터페이스도 수많은 것이 도출
- 왜? 우리는 책임(메소드)를 추상화하고 싶으니까
- Player라는 객체를 만든다. 어떻게 바라볼 것이냐에 따라서
-
내가 사장or아빠인 것처럼, 1개의 객체는
-
은닉화된 데이터 -> 수용해야하는 관점이 많고 -> 그만큼 인터페이스를 부여해야한다.
-
또한 객체마다 수용or소속되어있는 관점이 다르다.
- 어떤 객체는 B인터페이스만 -> 도메인A관점에만 사용됨
- 어떤 객체는 D, 라 ->A관점, 모델링관점 2관점으로 사용됨
-
-
각 객체들은
소속된 관점
마다다양한 인터페이스를 <부분적으로> 가지고 있다
- 각 객체들은 따로 존재하는게 아니라 망을 구성하고 있으니
- 서로 다른 관점끼리 통신하기도 하지만
- 같은 관점내에서 통신하기도 하고
- 순환참조를 하고 있는 것도 있다.
- 책만 보면, 이런 설계를 할 수 도 있다.
-
여러관점을 수용한 객체망
<->인터페이스 그룹화
된 표가 상호작용을 하고 있다.- 객체망 구성후 -> 모순점 or 잘못된 인터페이스 발견 -> 인터페이스그룹화된 표를 다시 다 고쳐줘야한다.