객체지향의 사실과 오해 with 우테코 프리코스

설탕·2023년 1월 10일
0
post-thumbnail

이 글은 객체지향의 사실과 오해 (조영호 지음) 책 내용 일부를 정리한 글입니다. 우아한테크코스 프리코스 피드백 중 관련 있는 내용을 함께 정리했습니다.

2장. 이상한 나라의 객체

  • 객체는 상태를 가지며 상태는 변경 가능하다.
  • 객체의 상태를 변경시키는 것은 객체의 행동이다.
    • 행동의 결과는 상태에 의존적이며 상태를 이용해 서술할 수 있다.
    • 행동의 순서가 실행 결과에 영향을 미친다.
  • 객체는 어떤 상태에 있더라도 유일하게 식별 가능하다.

상태행동

  • 부수 효과(side effect): 객체의 행동에 의해 객체의 상태가 변경된다.
  • 객체의 행동은 상태에 영향을 받는다.

행동이 서술해야 하는 부수 효과(side effect)

  • 객체 자신의 상태 변경
  • 행동 내에서 협력하는 다른 객체에 대한 메시지 전송

캡슐화

객체는 상태를 캡슐 안에 감춰둔 채 외부로 노출하지 않는다.
객체가 외부에 노출하는 것은 행동뿐이며, 외부에서 객체에 접근할 수 있는 유일한 방법 역시 행동뿐이다.

🚀 객체의 상태 접근을 제한하라

필드는 private class 필드로 구현한다. 객체의 상태를 외부에서 직접 접근하는 방식을 최소화한다.

class WinningLotto {
   #lotto
   #bonusNumber
   
   constructor(lotto, bonusNumber) {
       this.#lotto = lotto
       this.#bonusNumber = bonusNumber
   }
}

식별자

  • 동일성(identical): 두 객체의 상태가 다르더라도 식별자가 같다면 두 객체를 같은 객체로 판단할 수 있다.
  • 식별자: 어떤 객체를 다른 객체와 구분하는 데 사용하는 객체의 프로퍼티
  • 식별자를 지닌 객체 = 참조 객체(reference object) = entity

객체 간의 메시지를 통한 협력

  • 링크(link): 객체와 객체 사이의 의미 있는 연결
  • 객체의 링크를 통해서만 메시지를 주고받을 수 있다.

객체는 자율적인 존재

객체의 행동을 유발하는 것은 외부로 전달된 메시지지만 객체의 상태를 변경할지 여부는 객체 스스로 결정한다.

🚀 객체는 객체스럽게

Lotto 클래스는 numbers를 상태 값으로 가진다. 그런데 이 객체는 로직에 대한 구현은 하나도 없고, numbers에 대한 getter 메서드만을 가진다.

class Lotto {
  #numbers;
 
  constructor(numbers) {
    this.#numbers = numbers;
  }
 
  getNumbers() {
    return this.#numbers;
  }
}
 
class LottoGame {
  play() {
    const lotto = new Lotto(...);
                            
    // 숫자가 포함되어 있는지 확인한다.
    lotto.getNumbers().contains(number)
 
    // 당첨 번호와 몇 개가 일치하는지 확인한다.
    lotto.getNumbers().stream()...
  }
}

Lotto에서 데이터를 꺼내지(get) 말고 메시지를 던지도록 구조를 바꿔 데이터를 가지는 객체가 일하도록 한다.

class Lotto {
  #numbers;
  
  constructor(numbers) {
    this.#numbers = numbers;
  }

  contains(number) {
    // 숫자가 포함되어 있는지 확인한다.
    return ...
  }
 
  matchCount(other) {
    // 당첨 번호와 몇 개가 일치하는지 확인한다.
    return ...
  }
}
 
class LottoGame {
  play() {
    const lotto = new Lotto(...);

    lotto.contains(number);
    lotto.matchCount(...);
  }
}

참고: getter를 사용하는 대신 객체에 메시지를 보내자

객체지향 설계

행동상태를 결정한다.”

  1. 애플리케이션에 필요한 협력을 생각한다.
  2. 협력에 참여하는 데 필요한 행동을 생각한다.
  3. 행동을 수행할 객체를 선택한다.

🚀 적용: 다리 건너기 게임의 객체지향 설계

아래는 우테코 프리코스 미션으로 내가 구현한 다리 건너기 게임의 구조도이다.

각각의 객체에서 필드는 상태, 메서드는 행동이며 객체 간 메시지를 주고받으며 협력한다. MVC 패턴으로 구조화하고자 했다.

6장. 객체 지도

기능 vs 구조

요구사항 변경에 대비하기 위해서는 자주 변경되는 기능이 아닌 안정적인 구조를 중심으로 설계해야 한다.

How?

객체의 구조에 집중하고 기능이 객체의 구조를 따르게 만든다. 시스템 기능은 더 작은 책임으로 분할되고 적절한 객체에게 분배되기 때문에 기능이 변경되더라도 객체 간의 구조는 그대로 유지된다.

  • 구조: 사용자나 이해관계자들이 도메인에 관해 생각하는 개념과 개념들 간의 관계
    • 도메인 모델링
  • 기능: 사용자의 목표를 만족시키기 위해 책임을 수행하는 시스템의 행위
    • 유스케이스 모델링

안정적인 구조: 도메인 모델

  • 도메인: 사용자가 프로그램을 사용하는 대상 분야
  • 도메인 모델: 사용자가 프로그램을 사용하는 대상 영역에 관한 지식을 선택적으로 단순화하고 의식적으로 구조화한 형태
  • 도메인 모델이란…
    • 사용자들이 도메인을 바라보는 관점 (사용자 모델)
    • 설계자가 시스템의 구조를 바라보는 관점 (디자인 모델)
    • 소프트웨어 안에 구현된 코드의 모습 그 자체 (시스템 이미지)

불안정한 기능: 유스케이스(Use Case)

  • 유스케이스: 사용자의 목표를 달성하기 위해 사용자와 시스템 간에 이뤄지는 상호작용의 흐름을 텍스트로 정리한 것
  • 유스케이스의 가치는 사용자들의 목표를 중심으로 시스템의 기능적 요구사항들을 이야기 형식으로 묶을 수 있다는 점 - 단순히 기능을 나열하는 기능 목록과는 다름
  • 유스케이스는 UI와 관련된 세부 정보 또는 내부 설계와 관련된 정보를 포함하지 않는다.

책임-주도 설계

  • 사용자의 관점에서 시스템의 기능을 명시(유스케이스)하고
  • 사용자와 설계자가 공유하는 안정적인 구조(도메인 모델)를 기반으로
  • 기능책임으로 변환한다.
profile
공부 기록

0개의 댓글