📜 제목으로 보기

  • 참고 유튜브 : 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. 객체망과 객체간 통신

image-20220204103714606

  • 객체지향 관련 책들이 많지는 않다.
    • 뻔한 얘기외에 구체적인 사례를 들어주는 책은 드물다.
  • 오브젝트 5장: 1234장을 정리
    • 객체설계시 좋은 요령
      • 지금까지의 theater코드에 요령 적용
        • 이 책은 알고있다고 가정하는게 너무 많다 -> 이해 안되는게 정상
        • 맨 뒤에서, 책이 참고하고 있는 책 6권이상이 나열되어있음.
          • 사전요구사항이 되게 큰 책이다.
    • 오브젝트 6장부터: 새로운 내용의 시작
  • 지금까지의 내용 정리해보기
    • 설계 이전에 중요한 것: 책임
      • 객체간의 책임(함수)을 주고받기 위해 메세지(객체 인자)를 사용
    • 그렇다면, 누구에게 책임? 메세지는 어떻게 사용? 이 설계의 목표다.
      • 이 책에서 설계: 코드를 대치하는 기술
        • 어차피 돌아가는 코드에 대해 향후 유지보수 등이 쉬워지는 코드를 설계한다
        • 구동하는 코드를 만드는 것X -> 구동 코드를 어떻게 배치할 것인가
    • 설계: 코드를 객체지향원리에 따라서 <책임>을 객체별로 나눠 배치
      • 설계요령: 코드를 나누는 요령: 역할책임모델
    • 객체 만드는 이유: 역할(책임=메소드의 집합, 인터페이스?)
      • 역할: 책임의 집합
        • 책임을 어떤 객체가 가져가야할 것인가부터 부터 이해해야
          • 어떤 객체에 그 코드를 할당해줄 것인가를 결정
          • 객체지향에 의해 적절한 책임을 객체에 할당하는데, 나눠가지려면 메세지를 주고 받아야한다.

객체간 통신

  • 객체가 책임을 나눠갖기 위해 메세지를 통해 주고받으니까 우리는 객체가 책임을 통해 통신하고 있는 네트워크를 생각해볼 수 있다.
    • 객체망(object network): 역할책임모델 기반으로, 객체간 코드분리가 잘되어있는 형태
      • 객체망에 소속되어있는 객체끼리 메세지를 주고 받음 -> 책임을 분담/분산해서 나눠가짐
  • 객체간 통신
    • 책에서는 다 안다고 가정하고, 메세지를 던지면 다 알아먹는다고 가정하고 있다. 하지만 잘 모른다.
    • 실제 객체간통신은 복잡한 문제다

image-20220204114749258

  • 객체 1개 가지고는 객체망(역할책임모델기반 객체간코드분리)을 형성할 수 없다
    • 일단 객체에 대해서 더 살펴보자.

image-20220204114940217

  • 객체는 **내부에 캡슐화를 이용해서 정보은닉한 상태로, 외부와는 메소드를 통해 소통하고 있다. **
    • 내부는 안보여준다.
    • 외부는 캡슐화된 메소드만 제공해준다.

image-20220204115103261

  • 객체는 2개이상이다.

    • 서로 내장을 까지 않는 객체끼리는 public interface(껍데기)를 통해 메세지를 주고 받는다.

      image-20220204115202073

    • 하지만, 현실세계 객체는 위와 다르게 생겼다. 역할과 책임이 서로 틀리기 때문

      • 객체의 책임수행해야할 업무
      • 객체의 역할객체가 당면한 어떠한 측면
        • 가정에서는 아빠, 회사에서는 사장
        • 책임(업무)를 수행하되, 소속공간, 바라보는 측면에 따라 역할이 달라진다.
  • 객체의 본질은 은닉화한 데이터를 자기만 컨트롤 가능하지만, public한 interface로 외부에 [책임]으로써 노출

    • 집안(역할1)에서 돈(은닉화 데이터)을 나(객체1)만 가지고 있으면, 집에서 나만 돈 쓴다(역할1)
    • 회사(역할2)돈(은닉화 데이터)을 나(객체1)만 가지고 있으면, 회사에서 나만 돈 쓴다(역할2)
  • 은닉화 데이터를 기준으로 -> 책임 =외부에 노출한 public interface가 정해진다.

    • BUT, 데이터는 측면(역할)을 반영하진 않는다.

    • 측면 =역할 = 객체를 둘러싸고 있는 인터페이스들이다.

      image-20220204115805806

      • 현실세계 객체는 위처럼 생겼다
        • 내부는 캡슐화 -> 데이터 은닉화
        • 외부에 보여주는 것은 역할=측면(A사장, B아빠, C남자)에 따라 외부노출되는 메소드는 다른 형태
          • 책임: 돈을 준다
          • 역할 -> 바깥으로 나가는 측면에 따라 여러가지로
            • A: 급여 지급
            • B: 용돈 지급
            • C: 술값 지급
          • <역할참여=측면에따라> 책임(메소드)는 다양하게 나타난다
    • 메소드 자체는 객체내 은닉화된 데이터에 의해서만 나올 수 있다.

      • 데이터에 따라, 객체가 가지는 메소드는 정해져있다. ** **그러나 다른 측면(역할)에 따라 여러가지를 구현해줄 수 있다.
  • 은닉화 데이터(돈)에 따라 책임(업무, 메소드)는 정해지는데

    • 역할에 따라 = 측면에 따라 -> 여러 인터페이스가 구현되는 것은 class implements 사장, 아빠, 남자를 통해 여러가지를 구현한다.
      • **각 역할에 따라 메소드는 다른 방식으로 각각 구현된다. **
    • 해당 데이터는 나만 가지고 있으므로, 무조건 내가 구현해야한다. 역할에 따라 다르게 구현한다.
      • 현실세계 객체는 데이터 때문에 -> 다양한 측면의 메소드를 가지는게 정상
        • 책임(메소드)은, 각각 역할에 따라 1개씩 가진다.
          • 모든 역할을 가지고 1개의 책임(메소드)만 가지는 것은 불가능. 각각 책임이 만들어진다.
  • 현실세계 객체(나)는, 다양한 역할(사장, 아빠, 남자)을 가지며, 그 역할에 따라 각각의 책임(급여지급, 용돈지급, 술값지급)을 수행한다.

    • 요점: 나라는 객체가 -> 사장만 impl하거나 아빠만 impl할순 없다 -> 여러역할을 다 imple해서 -> 역할에 따른 여러 책임을 수행한다

image-20220204121000002

  • 객체간 통신이 어려운 이유: 객체망내 **다른 객체도 똑같이 중**이다. 역할에>
    • 나 = 은닉화데이터에 따라 사장, 아빠 impl 구현 중.
    • 옆사람 = 은닉화데이터에 따라 사원, 아들 impl하여 구현중.

image-20220204121114130

  • 객체간으로 볼 때, 2 객체의 추상층(추상레이어)입장에서 볼 수 있다.
    • 색깔별로 같은 병행 interface를 갖고 있다.
      • 인터페이스 수준에서는 색깔별로 같은 놈으로 보인다.
    • but 통신은 서로를 바라보는 측면(역할)에 의해 객체간 통신이 성립한다.
      • 역할의 형태(바라보는 측면, 관점)에 따라 통신함
        • 파란색 -> 파란색을 바라보는 관점뿐만 아니라
        • 파란색 -> 갈색을 바라보는 관점으로 따로 또 통신할 수 있다.

image-20220204133630243

  • 객체1개에서 각 인터페이스별로 책임과권한을 따로따로 가지고 있으며 책임과권한을 가진 인터페이스를 모두 다 합한 것이 객체가 된다.
    • 아빠 -> 아들에게 용돈주는 책임
    • 사장 -> 사원에게 급여를 주는 책임
      • 책임(과 권한)을 -> 인터페이스 Level별로 나눠서 가지고 있다.
        • 객체 = 떡진 덩어리가 아니라, [관점별]로 다르게 [구현]한 것들을 [Type(형)]으로 분리해서 인식한 것

image-20220204134020597

  • 각각의 **다양한 측면(관점)에 따라 책임과권한을 구현한 모든 인터페이스를 ** 한꺼번에>
    • 책임에는, 합당한 권한을 가져야 수행가능
      • 아는게 있어야, 뭘 한다
    • 다 합친 게 역할 -> 물주

image-20220204134221271

  • **객체간통신은 아름답게 [서로 스펙을 알고서 주로 받는게 아니다] **
    • 각각 여러가지의 책임별 인터페이스를 가지면서 역할을 수행하는 객체들끼리
      • 객체1의 일부 책임 -> 객체2의 다른 형태의 책임을 가리키면서 걔와 통신을하는 복잡한 과정이다.
    • 처음부터 파란색의 인터페이스는 -> 상대를 갈색으로 바라보고 메세지를 날릴 준비를 한다.
      • 아름답게 아빠(책임A)와 아들(책임a)의 통신이 아니라 아빠(책임A)가 사원(책임b)에게 급여줄 생각을 하고 있다는 말이다.
        • 이게 실제 세계의 통신이다. 그룹끼리 묵어서 통신하지 않는다.
    • 실제 객체간통신에 쓰려고 개발해도, 다각도적인 측면에서 복잡한 경우의수가 생기는 이유이다.
      • 객체 설계시, 절대 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장의 모순이 해결된다.

통신망의 구성

image-20220204140422832

  • 객체가 2개가 아니라 4개 이상을 보자.
    • 실제 객체는 어떤일 하기위해 누구에게 도움받았고, 서로 도움을 합체해 다른애들에게 도움을 요청한다.
    • 2장 theater도 마찬가지다. screening에게 부탁했더니 movie에게 부탁 -> policy -> condition에게 부탁하고 있다.
  • 동시에 2군데에서 부탁하고, 도착한 부탁 2개가 있으면 내부에서 변환하여 -> 1개로 다시 부탁할 수 있다. image-20220204140557470 image-20220204140627020
    • 합체+대기+병합조건 등이 일어나면서 비동기인 경우도 많아서 복잡하다.
      • 객체통신은 비동기도 포함해서, 다양한 형들이 다양한 형들과 대화하는 복잡한 망으로 되어있다.
  • 이 책을 보는 이유
    • 스프링에 있는 controller, service만 주구장창 짜는게 아니라 구성하는 파워를 기르기 위함이다.(이 통신망을 짜기 위함)
    • 비즈니스 도메인 -> 코드로 변역하여 통신망을 짜는 힘
      • 도메인: 해결해야하는 문제
      • 협력하는 객체의 망 + 메시지로 연결할 수 있느냐
        • 코드를 분산시킨 그릇들 = 객체들을 만들고
        • 메세지로 연결할 수 있느냐

image-20220204141012415

  • 두 메세지망의 차이점은?
    • 왼쪽: 비선형구조 / 오른쪽: 선형구조 (or 순환구조)
      • 일반적으로 순환 통신망 -> 잘못된 구조
        • 3개 밖에 없어서 파악했는데, 일반적으로는 파악할 수 없다.
        • 설계의 원칙을 지켜서 순환구조를 만들지말자.
    • 양방향 화살표, 서로 알고 있는 구조가 없어야한다.
      • 설계의 목적: 의존성을 제거할 수 없다 -> 단방향화(simplex) 시켜야한다.
        • 설계 = 코드 대치의 목표 -> 의존성을 단방향화 시키는데 있다.
      • if 조건부을 제거하는 방법? 없다
        • 관련된 의존성을 제거할 방법도 없다 ex> 하나카드랑 같이 일하는데, 하나카드 화살표를 제거할 방법 없다.
        • 도메인에서 원하는 것들만큼 화살표가 나가야한다. 제거할 방법 없다.
        • 우리가 해야할 것은 순환 참조만 일어나지 않게 하는 것이다.
          • 직접 순환 뿐만 아니라, 돌다가 오는 것도 막아야한다.

객체설계 난점

image-20220204142024113

  • 목표를 알았다. 순환참조를 안한다고 해도 객체설계에 난점들이 많다.
인터페이스의 그룹화
  • 인터페이스: 특정 책임을 나타내는 것
    • 제일 좋은 인터페이스 : 아무 메소드도 없는 것
    • 2번째 좋은 인터페이스 : 메소드 1개 있는 것
    • 안좋은 인터페이스 : 메소드 2개이상 있는 것
      • 기본적으로 인터페이스 = 메소드 1개만 가진다고 가정하자. 인터페이스를 왜 만들었을 까?
  • 인터페이스합당한 책임추상화한 것
    • 책임은 어디서? 도메인에서 나왔다.
      • 도메인은 여러 측면을 가지고 있다.
        • 사업자, 이용자, 에이전시 각각의 측면을 가지고 있다.
  • 즉, 여러 측면도메인에 따라 -> 책임이 관점에 따라 여러가지 -> 추상화한 인터페이스여러가지

image-20220204142608828

  • 도메인A관점(사업자) 측면에서 -> 여러 책임 -> 추상화한 여러 인터페이스 ABCD
    • 도메인B관점(이용자) 측면에서 -> … -> 여러 인터페이스 abcd
      • 같은 객체인데, 도메인에 따라 인터페이스도 여러개 추출

image-20220204142737185

  • 도메인이외에, 추가적인 관점들에 따라 -> 여러 인터페이스들이 마구마구 나온다.
    • Player라는 객체를 만든다. 어떻게 바라볼 것이냐에 따라서
      1. 움직이는 로직관점: 유저직접 / AI / 랜덤으로 / 히스토리기반 으로의 인터페이스들
      2. 컨트롤러 관점: 조이스틱 / 키보드 / 마우스 으로의 인터페이스들
    • 수많은 인터페이스가 많은 관점으로 양산
      • 왜? 우리는 책임(메소드)를 추상화하고 싶으니까
        • 그 책임이라는 것은 관점이나 도메인에 소속되어있기 때문에 -> 관점에 따라 수많은 책임 도출 -> 추상화하고 싶어서 인터페이스도 수많은 것이 도출
  • 내가 사장or아빠인 것처럼, 1개의 객체는

    • 은닉화된 데이터 -> 수용해야하는 관점이 많고 -> 그만큼 인터페이스를 부여해야한다.

    • 또한 객체마다 수용or소속되어있는 관점이 다르다.

      • 어떤 객체는 B인터페이스만 -> 도메인A관점에만 사용됨
      • 어떤 객체는 D, 라 ->A관점, 모델링관점 2관점으로 사용됨
  • 각 객체들은 소속된 관점마다 다양한 인터페이스를 <부분적으로> 가지고 있다

    image-20220204144930849

image-20220204145201844

  • 각 객체들은 따로 존재하는게 아니라 망을 구성하고 있으니
    • 서로 다른 관점끼리 통신하기도 하지만
    • 같은 관점내에서 통신하기도 하고 image-20220204145318775
    • 순환참조를 하고 있는 것도 있다.
      • 책만 보면, 이런 설계를 할 수 도 있다.
  • 여러관점을 수용한 객체망 <-> 인터페이스 그룹화된 표가 상호작용을 하고 있다.
    • 객체망 구성후 -> 모순점 or 잘못된 인터페이스 발견 -> 인터페이스그룹화된 표를 다시 다 고쳐줘야한다. image-20220204145447399