Skip to content

[오브젝트] Chap5 책임 할당하기

jullea edited this page Jan 12, 2020 · 2 revisions

<목차>

1. Q&A

2. 선배들이 언급하고 넘어간 부분

3. 선배들이 중요하다고 언급한 부분

4. chap5 정리

1. Q&A

기억에 의존해서, 대화를 재구성한거라 완벽하지 않습니다..ㅠ

(1) p.136 5문단 2줄 내용

Q1. (질문자) “협력에 참여하는 객체들의 책임이 어느 정도 정리될 때까지는 객체의 내부 상태에 대해 관심을 가지지 않는 것이다.”가 정확하게 무슨 뜻인지를 잘 이해가 안 간다.

A1.(답변자1) 클래스 설계할 때, 필드 (필자는 ‘필드’ = ‘데이터’라고 알아들음.) 를 먼저 고민하지 말고, 객체가 객체와 어떻게 소통하는지를 먼저 고민해봐라 라는 뜻인 것 같다.

Q2.(질문자) 메시지를 받을 객체의 속성을 어느 정도까지 생각해야 할지를 잘 모르겠다. (저번주에 p.83에서 대해서 질문이 나온 것처럼)

A2-1.(답변자1) 적당히...?

(적당히가 젤 어려워용..)

A2-2.(답변자2) 적합한 객체에게 적당한 책임을 할당한 후, 어느 정도 책임 할당이 정리 되고나서, 이 후, 구현을 할 때 그때그때 상태를 추가하는 것을 의미하는 것이 아닐까 생각한다. 즉, 미리 그 객체의 상태(필자는 상태 = ‘데이터’라고 알아들음)를 잡고 나서 책임을 할당하는 것이 아니라, 책임을 할당한 후, 속성을 추가하라는 것을 의미하는 것이 아닐까라고 생각한다.

(질문자). 그 부분(A2-2)에 대해서는 알고 있는 것이고 맞다고 생각한다. 제가 질문하려고 한 것은 그것이 아닌데, 제가 정확히 모르는 부분에 대해서 정리를 해서 물어보는 게 지금은 어려우니, 다시 한 번 공부해보겠다..

A3. (답변자3) 질문자(발표자)가 어떤 것을 정확하게 이해가 안 가는 것인지 모르겠지만, 내가 너의 질문에 대해 답변을 하자면... ‘도메인을 나누는 기준이 무엇이냐’에 대한 답변과 같을 것 같다. 우리가 직관적으로 movie 객체가 기본적으로 가져야 하는 속성들이 ‘영화제목’ ‘상영시간’ 등 임을 아는 것처럼 우리는 현실에 존재하는 문제를 해결해 나아가는 것이다. 즉, 이 문제에 대한 어느 정도 잘 잡혀진 요구명세가 있다는 것이다. 이를 잘 설계하여 도메인을 구성해주는 사람이 도메인 전문가이다. 따라서 도메인을 나누는 기준은 문제에 대해 주어진 요구명세에 의해서 모호함은 잘 없을 것이다.

(맞는 말이지만.. 왜 답변으로 나온 건지 필자는 잘 모르겠습니당...)

(필자의 끄적끄적)

필자는, 스터디 도중에 말을 하지는 않았지만, 질문에 대해 생각해보고 덧붙이자면,,, 여기서 말하는 ‘객체의 내부 상태’라는 것은,

  1. 답변자1,2가 말한 데이터도 될 수 있으며,
  2. 메서드(책임의 코드 구현) 안의 내부구현을 뜻할 수도 있다고 생각했다.

예를 들어, p.147의 2번째 코드의 Movie 클래스의 calculateMovieFee 메서드를 보자, 이 메서드는 screening으로부터 movie가 ‘가격을 계산하라’라는 도움을 요청받아서 도움을 응답하는 메서드(가격을 계산하는 책임의 구현)이다. p.147쪽에서 적혀있듯이 오브젝트 글쓴이는 movie에게 가격을 계산하는 메서드의 이름(+ 파라미터, 리턴형)만을 적어두었지, 그 내부에서 실제로 어떤식으로 계산을 하는지는 이후에 정의를 한다. 즉, 이 ‘어떤 식으로 계산하는지’가 객체의 내부상태를 말하는 것이 아닐까라는 생각을 하였다.. (맞는지는 모르겠습니당...).

(2) (p.158~159 에 나오는) 다형성 패턴과 변경 보호 패턴

Q1. 다형성 패턴으로 객체에게 책임을 할당한다면, 캡슐화가 되는 것 아닌가. 그렇게 된다면 변경보호 패턴도 자동적으로 성립이 되는 것인가?

A1. 다형성 패턴이 충분조건. 변경보호패턴이 필요조건이다. 즉, 다형성 패턴이 변경보호 패턴보다 더 큰 개념(?)이라고 생각하면 된다.

필요충분조건에 대한 개념은 구글링 해보세용ㅎㅅㅎ

(3) p.145 CREATOR 패턴 (박스 안의 내용)

Q1. ‘B가 A 객체를 기록한다.’라는 뜻이 정확히 이해가 안 간다.

A1. B가 A를 실제로 생성하는 것.을 뜻하는 것으로 이해하였다.

Q2. ‘B가 A 객체를 긴밀하게 사용한다’라는 뜻은 무엇인가?

A2. 로직을 사용하는 데에 있어서 B가 A를 어떻게든 사용하는 것!을 뜻한다. (파라미터로 사용하든..) 즉, 둘 사이에 결합도가 있다는 것을 의미한다!

(4) p.158

Q. 다형성 패턴은, 추상화를 통해 그 목적을 이룬다. 이렇게 비슷한 행동을 하는 패턴을 4가지 생각해보면 무엇이 생각나는가? (‘GoF의 디자인 패턴’ 스터디에서 배웠던 것입니다)

A. template패턴, factory 패턴, 책임 사슬 패턴, facade 패턴

저는 이전 스터디 안해서 몰라용.. 직접 찾아보세요! 저도 따로 공부해야겠네용ㅠㅠ

(5) p.145 2문단 2~3줄 내용

2문단 2~3줄 내용 : 협력과 책임이 제대로 동작하는지 확인할 수 있는 유일한 방법은 코드를 작성하고 실행해 보는 것뿐이다.
Q1. 다른 이야기이지만, ‘면접에서 white box test code와 black box test code 중 어떤 것을 사용할 것이냐’라는 질문에 어떻게 답변하실 건가요? (대학원 면접 질문)

A1-1. 왜 둘 중 하나만 선택해야는가? 현업에서는 둘 다 짜보지만, 무엇을 짤 것인지는 상황에 따라 다를 것이다. 어떤 상황에서는 구현을 test하는 것이 중요할 때가 있다. 그 때는 그에 맞게 test code를 짜야 한다.

A1-2. (답변자2) 대학원 면접 질문이라는 상황을 고려했을 때는, 내가 생각했을 때 이 질문의 의도는 학부생의 전공 지식 판단을 위한 것이라고 생각하기 때문에, black box test 라고 답할 것이다. (왜냐하면 그나마 이론적인 개념 성립이 잘 되었다고 면접관들이 생각할 것이기 때문이다.) 하지만 현업에서 무엇을 선택할 것인지는 상황에 따라 다를 것이므로 지금 정확히 무엇을 선택할 것이다라고 말할 수 없다.

!간단 용어 정리 Time!

(저처럼 white box test/ black box test를 모르는 사람들을 위해... 답변자1, 답변자2 께서 설명해주신 개념을 정리해보겠슴당.. 제가 이해한 걸 바탕으로 한 것이므로 정확하지 않을 수 있습니다... 자세한 내용은 구글링 해보시는 걸 추천드립니다..하하)

  • white box test – 안(내부 구현)에까지 알고 있는 가정하에 test code를 짜는 것
    • 단점 : 코드의 내부구현이 달라지면 test code도 달라져야 함
  • black box test – 인터페이스만 test 해보는 code를 짜는 것 (integrated test)
    • ex) 1을 입력했을 때 어떤 내부 구현에 의해서 결과적으로 13이 나오는 코드를 짰다고 가정하자!
      • white box test : 1에서 13이 나오는 동안의 그 내부에서 일어나는 과정들(안에서 무슨 값으로 바뀌었는지)을 알아야 함.
      • black box test : test했을 때, 1 -> 13 나오는 것만 확인하면 됨.

2. 선배들이 언급하고 넘어간 부분

  • Refactoring(p.166 참고)을 위해서, test code가 있는 것이 좋다! 하지만,,, test code가 오류 없이 잘 작동된다고 해서 너무 맹신하지는 말 것!

3. 선배들이 중요하다고 언급한 부분

(1) p.165 그림 5.9의 수정된 도메인이 매우 중요하다! 박스부분을 꼭읽어볼 것!

  • 코드의 구조가 도메인의 구조에 대한 새로운 통찰력을 제공한다!!!
  • p. 163 그림 5.7과 비교해서 p.165 그림 5.9에서 달라진 점이 무엇인지 바로 알겠는가? -> 바로 할인정책이 영화와 다른 도메인으로 분리되어서 표현되었다는 것인데, 이것이 왜 이렇게 분리되었는지를 이해하는 것이 중요하다!

(2) 코드 짤 때, 몬스터 메서드(p.168 참고)를 짜고 있는 것은 아닌지 생각하면서 코드를 작성하라! (처음에는 몬스터 메서드가 아니었을 수 있지만 기능들이 이것저것이 추가되면서 몬스터 메서드로 변할 수도 있으므로)

(3) ‘메소드의 길이’와 ‘그 메서드의 이름의 표현력’ (메서드의 이름과 메서드 몸체의 의미적 차이)에 대해서 생각해보는 것이 매애애애우 중요하다!

  • p.168의 Fowler99a가 말한 파란 글씨의 내용을 매우 유념해라! 이 내용을 계속해서 반복하여 강조하는 책이 ‘Clean Code'이다. 이것도 나중에 읽어봐라.

4. Chap5. 정리

00 들어가기 전 (p.133)

4장(설계품질과 트레이드오프)에 대한 정리

  • 데이터 중심의 접근법을 취할 경우 직면하게 되는 다양한 문제점들을 살펴봄.
  • 이러한 문제점을 해결할 수 있는 가장 기본적인 방법은 책임에 초점을 맞추는 것임.

01. 책임 주도 설계를 향해 (p.134)

데이터보다 행동을 먼저 결정하라

  • “이 객체가 수행해야 하는 책임이 무엇인가”를 결정한 후에, “이 책임을 수행하는 데 필요한 데이터는 무엇인가”에 대해서 결정하라.

(이 이유는 3,4장에서 보았듯이, 높은 응집도, 낮은 결합도를 위해 책임을 데이터보다 먼저 결정하는 것임)

협력이라는 문맥 안에서 책임을 결정하라

  • 협력에 적합한 책임이란 메시지 수신자가 아니라, 메시지 전송자에게 적합한 책임을 의미한다.
  • 메시지가 객체를 선택하게 해야 한다. 메시지를 수신하기로 결정된 객체는 메시지를 처리할 ‘책임’을 할당 받게 되는 것.

--> 이를 통해 캡슐화의 원리를 지킨다! : 왜냐하면 메시지 송신자는 메시지 수신자에 대한 어떠한 가정도 할 수 없기 때문.

책임 주도 설계

  • 3장에서 설명한 책임 주도 설계의 흐름을 나열하고 있다.

    (1~5로 책에 잘 설명해주고 있음. 직접 찾아보길 바람.)

  • 책임 주도 설계의 핵심 : 책임을 결정한 후에 책임을 수행할 객체를 결정하는 것이다. 그리고 협력에 참여하는 개체들의 책임이 어느정도 정리될 때까지는 객체의 내부 상태에 대해 관심을 가지지 않는 것이다.

02. 책임 할당을 위한 GRASP 패턴 (p.137)

  • GRASP란? : 객체에게 책임을 할당할 때 지침으로 삼을 수 있는 원칙들의 집합을 패턴 형식으로 정리한 것

도메인 개념에서 출발하기

  • 어떤 책임을 할당해야 할 때 가장 먼저 고민해야하는 것이 도메인 개념이다.
  • 하지만, 설계를 시작하는 단계에서는 개념들의 의미와, 관계가 정확하거나 완벽할 필요는 없다.
  • 중요한 것은 설계를 시작하는 것이지 도메인 개념들을 완벽하게 정리하는 것이 아니다!

그렇지만 유의해야할 점은 도메인 모델은 도메인을 개념적으로 표현한 것이지만 그 안에 포함된 개념과 관계는 구현의 기반이 돼야 한다는 것이다.

정보 전문가에게 책임을 할당하라.

  • 정보 전문가 패턴이란? : 책임을 수행할 정보를 알고 있는 객체에게 책임을 할당하는 것.
  • 책임을 수행하는 객체가 정보를 ‘알고’ 있다고 해서 **그 정보를 ‘저장’할 필요는 없다. **객체는 해당 정보를 제공할 수 있는 다른 객체를 알고 있거나 필요한 정보를 계산해서 제공할 수도 있다. (발표자가 중요하다고 생각한 부분)
    • (예시) screening이 ‘예매하라’라는 메시지를 완료하기 위해, 예매 가격을 계산하는 작업이 필요함.

      • 이 예매 가격을 계산하는 작업을 movie에게 할당하는 것이 가장 합당하다!

      • 왜냐하면, 영화가격을 계산하는 데 필요한 정보를 알고 있는 전문가는 movie이기 때문.

정보 전문가 패턴 뿐만 아니라, + 다른 패턴들도 고려하면 더욱더 자율성 높은 객체들로 구성된 협력 공동체를 구축할 수 있다.

--> 이것이 바로 Low Coupling, High Cohesion 패턴이다.

높은 응집도와 낮은 결합도

  • Low Coupling 패턴이란? : 설계의 전체적인 결합도가 낮게 유지되도록 책임을 할당하라.

  • High Cohesion 패턴이란? : 높은 응집도를 유지할 수 있게 책임을 할당하라.

    • (예시) 오브젝트 글쓴이는 두 개의 패턴의 예시로, DiscountCondition과 협력하는 객체가 Screening이 아닌 Movie인 이유에 대해서 설명을 하고 있다.

      • low coupling 패턴 관점) Screening이 DiscountCondition과 협력할 경우, 그 둘 사이의 새로운 결합도가 추가됨 (BAD!)
      • High Cohesion 패턴 관점) Screening이 서로 다른 이유로 변경되는 책임(1. 예매 생성 관련 책임. 2. 예매 계산 관련된 일부 책임)을 가지므로 응집도가 낮아짐 (BAD!)

창조자에게 객체 생성 책임을 할당하라.

  • Creator 패턴이란? : 객체를 생성할 책임을 어떤 객체에게 할당할지에 대한 지침을 제공함.

현재까지의 책임분배는 대략적인 스케치에 불과하다! 협력과 책임이 제대로 동작하는지 확인할 수 있는 유일한 방법은 코드를 작성하고 실행해 보는 것 뿐이다.

03. 구현을 통한 검증 (p.146)

  • (p.146~p.151) : 실제로 클래스들의 내부 구현을 작성하는 부분이 단계별로 적혀있다.

    (이에 대한 부분은 필자가 정리하기가 난해하므로 직접 오브젝트 책을 읽어보길 바란다..ㅎㅎ)

  • 코드를 작성할 때, 중요한 점은 (p.147) ‘메시지는 수신자가 아닌 송신자의 의도를 표현해야한다.’는 것이다

DiscountCondition 개선

  • (p.146~p.151)에서 구현된 코드는 가장 큰 문제점 : 변경에 취약한 클래스를 포함.
  • <DiscountCondition의 변경 이유>
    1. 새로운 할인 조건 추가 -> if~else 구문 수정해야 함.
    2. 순번 조건을 판단하는 로직 변경
    3. 기간 조건을 판단하는 로직 변경

---> 해결방법 : 변경의 이유에 따라 클래스를 분리해라!.

  • <분리하는 방법>
    1. 인스턴스 변수가 초기화되는 시점을 살펴보고, 함께 초기화되는 속성을 기준으로 코드를 분리
    2. 메서드들이 인스턴스 변수를 사용하는 방식을 살펴보고 속성그룹과 해당 그룹에 접근하는 메서드 그룹을 기준으로 코드를 분리

타입 분리하기

  • DiscountCondition의 타입을 SequenceCondition, PeriodCondition 두 개의 클래스로 분리.
  • 문제점 : Movie의 인스턴스가 위의 두 개의 다른 클래스의 인스턴스 모두와 협력할 수 있어야 한다.
    • 결합도가 높아짐. (BAD!)
    • 새로운 할인 조건 추가하기 어려워짐! (BAD!)

다형성을 통해 분리하기

  • 다형성 패턴이란? : 객체의 타입에 따라 변하는 행동이 있다면 타입을 분리하고 변화하는 행동을 각 타입의 책임으로 할당하라는 것
  • (예시) SequenceCondition, PeriodCondition은 ‘할인 가능여부를 판단’하는 동일한 책임을 수행하고 있기 때문에, 역할을 사용하여 객체의 구체적인 타입을 추상화한다.
  • 즉, DiscountCondition이라는 인터페이스를 통해 역할을 구현하여, Movie가 구체적인 클래스를 알지 못한 채, 오직 역할에 대해서만 결합되도록 의존성을 제한한다.

변경으로부터 보호하기

  • 변경 보호 패턴이란? : 변경을 캡슐화하도록 책임을 할당한다.

Movie 클래스 개선하기 (p.159~163)

앞에서 나온 패턴의 개념을 통해, 오브젝트 글쓴이는 Movie 클래스를 개선하고 있다. 자세한 내용은 책을 참고할 것.

04.책임 주도 설계의 대안

코드 개선하는 과정은 (p.167~174) 직접 보세요..ㅎㅎ^^

  • 최대한 빠르게 목적한 기능을 수행하는 코드를 작성한 후, 코드 상에 명확하게 드러나는 책임을 올바른 위치로 이동시킨다.

  • 즉, ‘리팩터링’하는 것 : 겉으로 보이는 동작을 바꾸지 않은 채 내부 구조를 변경하는 것.

Clone this wiki locally