07 함께 모으기

Byung Seon Kang·2022년 7월 19일

코드와 모델을 밀접하게 연관시키는 것은 코드에 의미를 부여하고 모델을 적절하게 한다.
-Eric Evans

  • 마틴 파울러는 객체지향 설계안에 존재하는 세 가지 상호 연관된 관점을 소개.
  1. 개념관점(Conceptual Perspective)
    이 관점에서 설계는 도메인 안에 존재하는 개념과 개념들 사이의 관계를 표현.
    이 관점은 사용자가 도메인을 바라보는 관점을 반영한다.

    실제 도메인의 규칙과 제약을 최대한 유사하게 반영하는 것이 핵심

  2. 명세관점(Specification Perspective)
    개발자의 영역인 소프트웨어로 초점이 옮겨진다.
    객체들의 책임, 즉 인터페이스를 바라보게 된다('무엇'을 할 수 있는가)

    인터페이스와 구현을 분리해라.
    구현이 아니라 인터페이스에 대해 프로그래밍하라

  3. 구현관점(Implementation Perspective)
    실제 작업을 수행하는 코드와 연관되어 있음.
    객체들이 책임을 수행하는 데 필요한 동작하는 코드를 작성하는 것(어떻게)

위 순서는 소프트웨어의 개발 순서와는 연관이 없다.
동일한 클래스를 세 가지 다른 방향에서 바라보는 것을 의미한다.

클래스를 설계할때는 결국 개념, 인터페이스, 구현을 함께 드러내야 하며 코드안에서 세 가지 관점을 쉽게 식별할 수 있도록 깔끔하게 분리해야 한다.

1. 도메인 모델 생성

1) 객체들로 구성된 세상으로 바라보기

  • 커피 전문점을 객체들로 구성된 세상으로 바라봐보자.
    손님 객체
    메뉴판 객체
    메뉴항목 객체
    아메리카노, 카푸치노, 카라멜 마키아또, 에스프레스 객체
    바리스타 객체

2) 타입 생성

  • 손님 타입, 메뉴 항목 타입, 바리스타 타입, 커피 타입으로 나눈다.

3) 타입간 관계 체크

  • 연관(association)
    ex)메뉴 항목이 메뉴판에 포함됨
  • 합성(composition)
    손님은 메뉴판 타입을 알고 있어야 원하는 커피를 선택할 수 있음.

2. 설계하고 구현하기

커피 주문을 위한 협력 찾기

  • 객체지향 설계의 첫 번째 목표는 훌륭한 객체를 설계하는 것이 아니라 훌륭한 협력을 설계하는 점이라는 것을 잊어선 안됨.
  • communication diagram을 통해 메시지의 방향과 주고받는 데이터를 더 보기 쉽게 표현할 수 있다고 함.
  • 이 다이어그램을 가지고 협력에 필요한 객체의 종류와 책임, 주고받아야 하는 메시지에 대한 대략적인 윤곽이 잡힘.

인터페이스 정리하기

  • 위의 작업을 통해 얻어낸 것은 객체들의 인터페이스.
  • 객체들을 포괄하는 타입을 정의한 후 식별된 오퍼레이션을 타입의 인터페이스에 추가하기.

구현하기

  • 클래스의 인터페이스를 식별했으므로 이제 오퍼레이션을 수행하는 방법을 메서드로 구현
  • 이때 구현 도중 객체의 인터페이스가 변경될 수 있다는 점에 주의

    구현하지 않고 머릿속으로만 구상한 설계는 코드 구현 단계에서 대부분 변경됨.
    협력을 구상하는 단계에 너무 오랜 시간을 쏟지 말고 최대한 빨리 코드를 구현해서 설계에 이상이 없는지, 설계가 구현 가능한지를 판단해야 한다.

  • 인터페이스를 구성하는 오퍼레이션들을 구현 단계에서야 식별하는 것은 문제가 되지 않음.
    -> 인터페이스를 통해 실제로 상호작용을 해보지 않은 채 인터페이스의 모습을 정확하게 예측하는 것은 불가능에 가까우므로.
  • 설계를 간단히 끝내고 최대한 빨리 구현에 돌입해야 함.
    머릿속에 객체의 협력 구조가 번뜩이기 시작한다면 그대로 코드를 구현하기 시작하라.
    설계가 그려지지 않는다면 고민하지 말고 실제로 코드를 작성해가면서 협력의 전체적인 밑그림을 그려보라.

3. 코드와 세 가지 관점

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

  • 개념 관점, 명세 관점, 구현 관점에서 각기 다른 사항들을 설명해줘야 함.

개념관점

  • 개념관점에서 코드를 바라보면 클래스가 보임
    클래스들을 자세히 살펴보면 도메인을 구성하는 중요한 개념과 관계를 반영한다는 사실을 잘 알 수 있음.
  • 클래스가 도메인 개념 특성을 최대한 수용하면 변경 관리가 쉽고 유지보수성을 향상시킬 수 있게 됨.
    커피 제조 과정을 변경해야 한다면 어디를 수정해야 할까?
    바리스타 클래스에서 수정하면 될 것이라 유추가 가능하다.

명세관점

  • 클래스의 인터페이스를 바라본다.
    객체의 인터페이스는 수정하기 어렵다는 사실을 명심할 것.
    최대한 변화에 안정적인 인터페이스를 만들기 위해서는 인터페이스를 통해 구현과 관련된 세부사항이 드러나지 않게 해야 함.

구현관점

  • 클래스의 내부 구현을 바라봄.
    클래스의 메서드와 속성은 구현에 속하며 공용 인터페이스의 일부가 아님.
  • 즉, 메서드의 구현과 속성의 변경은 원칙적으로 외부의 객체에게 영향을 미쳐서는 안된다는 것.

개념 관점, 명세 관점, 구현 관점은 동일한 코드를 바라보는 서로다른 관점이다. 개발자는 세가지 관점을 모두 포함하면서도 각 관점에 대응되는 요소를 명확하고 깔끔하게 드러내야 한다.

도메인 개념을 참조하는 이유

  • 메세지를 수신할 객체를 선택한느 방법은 도메인 개념 중에서 가장 적절한 것을 선택하는 것이다.
  • 소프트웨어는 항상 변하고 설계는 변경을 위해 존재한다.인터페이스와 구현을 분리하는 이유는 변경이 발생했을 때 코드를 좀 더 수월하게 수정하길 간절히 원하기 때문.

인터페이스와 구현을 분리하라.

  • 인터페이스와 구현을 분리해야 함.
  • 명세 관점과 구현 관점이 뒤섞이면 절대 안됨.
  • 마틴 파울러는 개념적인 관점과 명세 관점 사이는 그렇게 중요하지 않은 경우가 많지만 명세 관점과 구현 관점을 분리하는 것은 매우 중요하다고 주장
profile
왜 필요한지 질문하기

0개의 댓글