오브젝트 내용 요약

3장

협력: 다른 객체들에게 무엇인가를 ‘요청’하는 것 (도와주세요)

  • 협력에 필요함에 있어 다른 객체가 필요하다면 해당 객체를 사용한다. (screening.reserve(movie) )
    • 다른 객체를 파라미터로 받던지 등

책임: 협력에서(협력에 참여하기 위해) 객체가 하는 행동

  • 책임은 아는 것과 하는 것으로 분류한다
  • 책임을 능숙하게 할당하는 것에 따라 설계 품질이 달라진다.
  • 해당 도메인의 전문가에게 책임을 할당하는 것이 바람직하다.

역할: 협력 안에서 객체가 수행하는 책임들의 집합

  • 역할이 중요한 이유는 유연하고 재사용 가능한 협력을 얻을 수 있기 때문
  • 여러 할인 정책에 따라 영화 금액이 달라진다면, DiscountPolicy 라는 추상화된 역할에만 의존하는 것이다.
  • 협력에 참여하는 대상이 하나라면 객체, 여러 종류라면 역할로 설계를 하자.

객체에게 중요한 것은 행동이라는 사실을 기억하라. 역할이 중요한 이유는 동일한 협력을 수행하는 객체들을 추상화 할 수 있기 때문이다. 1

4장

객체지향 설계의 핵심은 역할, 책임, 협력이다. 2

역할, 책임, 협력 중에서 가장 중요한 것은 책임이다.

객체지향 설계란 올바른 객체에게 올바른 책임을 할당하면서 낮은 결합도와 높은 응집도를 가진 구조를 창조하는 활동이다. 3

결합도와 응집도를 합리적인 수준으로 유지하기 위해서는 객체의 상태가 아닌 행동에 초점을 두자.

변경될 가능성이 높은 부분을 구현이라고 부르고 상대적으로 안정적인 부분을 인터페이스라고 부른다는 사실을 기억하라. 4

캡슐화의 정도가 응집도와 결합도에 영향을 미친다. 5

데이터 중심의 설계는 캡슐화를 위반하고 객체의 내부 구현을 인터페이스의 일부로 만든다. 반면 책임 중심의 설계는 객체의 내부 구현을 안정적인 인터페이스를 뒤로 캡슐화한다. 6

캡슐화는 설계의 제1원리다. 객체는 스스로의 상태를 책임져야 하며 외부에서는 인터페이스에 정의된 메서드를 통해서만 상태에 접근할 수 있어야 한다. 7

객체는 단순한 데이터 제공자가 아니다. 객체 내부에 저장되는 데이터보다 객체가 협력에 참여하면서 수행할 책임을 정의하는 오퍼레이션이 더 중요하다. 8

데이터는 구현의 일부라는 사실을 명심하라. 데이터 주도 설계는 설계를 시작하는 처음부터 데이터에 관해 결정하돌고 강요하기 때문에 너무 이른 시기에 내부 구현에 초점을 맞추게 한다. 9

객체지향 애플리케이션을 구현한다는 것은 협력하는 객체들의 공동체를 구축한다는 것을 의미한다. 올바른 객체지향 설계의 무게 중심은 항상 객체의 내부가 아니라 외부에 맞춰져 있어야 한다. 10

한줄요약: 캡슐화를 잘 하자.

  • 데이터 중심이 아니라, 객체에게 적절한 책임을 할당하고 객체가 하는 일을 캡슐화하여 응집도를 높이고 결합도를 낮추자.

5장

  • 객체의 데이터가 아닌 책임, 메시지에 초점을 맞추자.
  • 정보 전문가에게 책임을 할당하자. 자기 자신이 모든 것을 수행할 수 없다면 다른 객체에게 협력을 요청하자.
  • 코드를 통해 변경의 이유를 파악할 수 있는 방법들이 있다. 11
    • 인스턴스 변수가 초기화 되는 시점을 살펴보라.
    • 메서드들이 인스턴스 변수를 사용하는 방식을 살펴보라.
    • 속성 그룹과 해당 그룹에 접근하는 메서드 글부을 기준으로 코드를 분리하라.

데이터 중심 설계로 인해 발생하는 문제점을 해결할 수 있는 가장 기본적인 방법은 데이터가 아닌 책임에 초점을 맞추는 것이다. 12

데이터 중심의 세계에서는 "이 객체가 포함해야 하는 데이터가 무엇인가"를 결정한 후에 "데이터를 처리하는 데 필요한 오퍼레이션은 무엇인가"를 결정한다. 반면 책임 중심의 설계에서는 "이 객체가 수행해야 하는 책임은 무엇인가"를 결정한 후에 "이 책임을 수행하는 데 필요한 데이터는 무엇인가"를 결정한다. 13

중요한 것은 설계를 시작하는 것이지 도메인 개념들을 완벽하게 정리하는 것이 아니다. 도메인 개념을 정리하는 데 너무 많은 시간을 들이지 말고 빠르게 설계와 구현을 진행하라. 14

객체는 자신의 상태를 스스로 처리하는 자율적인 존재여야 한다. (…중략) 객체에게 책임을 할당하는 첫 번째 원칙을 책임을 수행할 정보를 알고 있는 객체에게 책임을 할당하는 것이다. GRASP에서는 이를 INFORMATION EXPERT 패턴이라고 부른다. 15

코드를 통해 변경의 이유를 파악할 수 있는 첫 번째 방법은 인스턴스 변수가 초기화되는 시점을 살펴보는 것이다. 응집도가 높은 클래스는 인스턴스를 생성할 때 모든 속성을 함께 초기화한다. 반면 응집도가 낮은 클래스는 객체의 속성 중 일부만 초기화하고 일부는 초기화되지 않은 상태로 남겨진다.

코드를 통해 변경의 이유를 파악할 수 있는 두 번째 방법은 메서드들이 인스턴스 변수를 사용하는 방식을 살펴보는 것이다. 16

다음은 타입을 분리하지 않았을 때의 예제를 간소화한 코드이다. 17

class Movie {
	List<PerioidCondition> periodConditions;
	List<SequenceCondition> sequenceConditions;
	
	private boolean isDiscoutable(Screening screening) {
		return this.periodConditions.stream()
			.anyMatch(c -> c.isSatisfiedBy(screening)
			|| this.sequenceConditions.stream()
			.anyMatch(c -> c.isSatisfiedBy(screening)
	}
}

사실 Movie 입장에서는 PerioidCondition과 SequenceCondition이 아무 차이가 없다.

새로운 Condition이 추가된다면? 새로운 List를 필드에 추가할 것인가?

할인 조건이 추가되었는데 Movie 클래스의 코드가 수정된다면 응집도가 낮은 설계라고 볼 수 있다.

PerioidCondition과 SequenceCondition을 하나의 Condition으로 추상화하자.

class Movie {
	List<Condition> conditions;
	
	private boolean isDiscoutable(Screening screening) {
		return this.conditions.stream()
			.anyMatch(c -> c.isSatisfiedBy(screening);
}

객체의 타입에 따라 변하는 로직이 있을 때 변하는 로직을 담당할 책임을 어떻게 할당해야 하는가? 타입을 명시적으로 정의하고 각 타입에 다형적으로 행동하는 책임을 할당하라. 18

책임 주도 설계 방법에 익숙하지 않다면 일단 데이터 중심으로 구현한 후 이를 리팩터링하더도 유사한 결과를 얻을 수 있다는 것이다. 처음부터 책임 주도 설계 방법을 따르는 것보다 동작하는 코드를 작성한 후에 리팩터링하는 것이 더 훌륭한 결과물을 낳을 수도 있다. 19

6장- 메시지와 인터페이스

  • 메시지란 무엇인가
  • 메시지와 인터페이스가 왜 중요한가
  • 메시지와 인터페이스는 무슨 관계인가

메시지란 객체가 협력할 때 유일하게 주고 받을 수 있는 의사소통 수단을 의미한다.

객체는 인터페이스를 통해 메시지를 서로 주고받는다.

의도를 드러내는 인터페이스

메서드의 이름을 짓는 두 번째 방법은 '어떻게'가 아니라 '무엇'을 하는지를 드러내는 것이다. 20

원칙의 함정

잊지 말아야 하는 사실을 설계가 트레이드오프의 산물이라는 것이다. (…중략) 원칙이 현재 상황에 부적합하다고 판단된다면 과감하게 원칙을 무시하라. 원칙을 아는 것보다 더 중요한 것은 언제 원칙이 유용하고 언제 유용하지 않은지를 판단할 수 있는 능력을 기르는 것이다. 21

명령-쿼리 분리 원칙

  • 프로시저와 함수는 각각 부수효과를 일으키는 것, 값을 연산해 반환하는 것.
  • 명령을 프로시저, 쿼리를 함수로 표현
  • 명령과 쿼리가 뒤섞으면 실행 결과를 예측하기 어려울 수 있다.

페이지

  1. p94 ↩

  2. p97 ↩

  3. p97 ↩

  4. p109 ↩

  5. p112 ↩

  6. p113 ↩

  7. p117 ↩

  8. p119 ↩

  9. p131 ↩

  10. p132 ↩

  11. p152 ↩

  12. p133 ↩

  13. p134 ↩

  14. p138 ↩

  15. p139 ↩

  16. p152 ↩

  17. p154 ↩

  18. p158 ↩

  19. p174 ↩

  20. p188 ↩

  21. p198 ↩