본문 바로가기
IT Books Review/객체지향의 사실과 오해

[Book] 객체지향의 사실과 오해 - 최종편 (부록)

by happy coding! 2023. 4. 12.
반응형

추상화 기법

추상화는 도메인의 복잡성을 단순화하고 직관적인 멘탈 모델을 만드는 데 사용할 수 있는 가장 기본적인 인지 수단이다.
특성을 공유하는 객체들을 동일한 타입으로 분류하는 것은 객체지향 패러다임에서 사용하는 추상화 기법의 한 예다.

중요한 추상화 기법의 종류

  1. 분류와 인스턴스화
    • 분류는 객체의 구체적인 세부 사항을 숨기고 인스턴스 간에 공유하는 공통적인 특성을 기반으로 범주를 형성하는 과정
    • 분류의 역은 범주로부터 객체를 생성하는 인스턴스화 과정이다.
  2. 일반화와 특수화
    • 일반화는 범주 사이의 차이를 숨기고 범주 간에 공유하는 공통적인 특성을 강조
    • 일반화의 역을 특수화라고 한다.
  3. 집합과 분해
    • 집합은 부분과 관련된 세부 사항을 숨기고, 부분을 사용해서 전체를 형성하는 과정을 가리킨다.
    • 집합의 반대 과정은 전체를 부분으로 분리하는 분해 과정이다.

객체지향의 가장 큰 장점은 동일한 추상화 기법을 프로그램의 분석, 설계, 구현 단계에 걸쳐 일관성 있게 적용할 수 있다는 점이다.

개념과 범주

  • 개념이란 속성과 행위가 유사한 객체에 공통적으로 적용되는 관념이나 아이디어다.
  • 자동차 범주에 적용되는 개념은 '바퀴를 이용해 사람들을 한 장소에서 다른 장소로 운반하는 운송수단'이다.
  • 나무라는 범주에는 '푸른 잎과 갈색의 줄기를 가진 다년생 식물'이라는 개념을 적용할 수 있다.

타입

  • 수많은 개별적인 현상들 객체라고 하고 하나의 개념타입이라고 한다.
  • 객체지향의 세계에서 개념을 가리키는 표준 용어는 타입이다.
  • 분류란 객체들을 동일한 타입 또는 범주로 묶는 과정을 의미하므로 객체타입의 인스턴스라고 한다.

클래스

  • 객체지향 프로그래밍 언어를 이용해 타입을 구현하는 가장 보편적인 방법클래스를 이용하는 것이다.
    • 여기서 '타입을 구현한다'라고 표현한 이유는 클래스와 타입이 동일한 개념이 아니기 때문
  • 클래스는 타입을 구현하는 용도 외에도 코드를 재사용하는 용도로 사용되기도 한다.
    • 클래스 외에도 인스턴스를 생성할 수 없는 추상 클래스나 인터페이스를 이용해 타입을 구현할 수도 있다.
  • 클래스 기반의 객체지향 언어는 아리스토텔레스의 철학을 기반으로 한다.
    • 클래스는 객체가 공유하는 본질적인 속성을 정의한다.

서브 타입

  • 객체지향의 세계에서는 좀 더 일반적인 타입을 이용해 좀 더 세부적인 타입을 정의함으로써 타입 간의 계층 구조를 구축할 수 있다.
    • 어떤 타입이 다른 타입보다 일반적이라면 '슈퍼타입(supertype)'이라고 한다.
    • 어떤 타입이 다른 타입보다 좀 더 특수하다면 이 타입을 '서브타입(subtype)'이라고 한다.
    • 슈퍼타입은 서브타입의 일반화이고 서브타입은 슈퍼타입의 특수화다.

일반화와 특수화의 계층 구조에서 서브타입슈퍼타입이 가진 본질적인 속성과 함께 자신만의 추가 속성을 가진다.

  • 서브타입은 슈퍼타입의 본질적인 속성을 모두 포함하기 때문에 계층에 속하는 모든 서브타입들이 슈퍼타입의 속성을 공유한다.
  • 크레이그 라만은 어떤 타입이 다른 타입의 서브타입이 되기 위해서는 100% 규칙과 Is-a 규칙을 준수해야 한다고 말한다.
    • 100% 규칙: 슈퍼타입의 정의가 100% 서브타입에 적용돼야만 한다. 서브타입은 속성과 연관관계 면에서 슈퍼타입과 100% 일치해야 한다.
    • Is-a 규칙: 서브타입의 모든 인스턴스는 슈퍼타입 집합에 포함돼야 한다. 이는 대개 영어로 서브 타입은 슈퍼타입이다(subtype is supertype)라는 구문을 만듬으로써 테스트할 수 있다.

상속

  • 프로그래밍 언어를 이용해 일반화와 특수화 관계를 구현하는 가장 일반적인 방법클래스 간의 상속을 사용하는 것
  • 일반화의 원칙은 한 타입이 다른 타입의 서브 타입이 되기 위해서는 슈퍼타입에 순응해야 한다는 것이다.
  • 순응에는 구조적인 순응과 행위적인 순응의 두 가지 종류가 있다.
    • 구조적인 순응: 예를 들어 Person이 name이라는 속성을 가진다면 Person의 서브타입인 Employee 역시 name 이라는 속성을 가질 것이라고 기대할 수 있다.
    • 행위적인 순응: Person이 getAge()라는 메시지에 대한 응답으로 나이를 반환한다면 서브타입인 Employee 역시 getAge()라는 메시지에 대한 응답으로 나이를 반환해야 한다.

 

  • 상속의 또다른 용도는 코드 중복을 방지하고 공통 코드를 재사용하기 위한 언어적 메커니즘을 제공하는 것이다.
  • 만약 한 클래스가 다른 클래스를 상속한다면 상속하는 타입부모 클래스의 데이터와 메서드를 사용하고, 수정하고, 확장할 수 있다.
  • 여러 클래스로 구성된 상속 계층에서 수신된 메시지를 이해하는 기본적인 방법은 클래스 간의 위임(delegation)을 사용하는 것이다
    • 어떤 객체의 클래스가 수신된 메시지를 이해할 수 없다면 메시지를 클래스의 부모 클래스로 위임한다.
    • 만약 부모 클래스에서도 메시지를 이해할 수 없다면 자신의 부모 클래스로 다시 메시지를 위임한다.
    • 클래스 간의 위임 사슬은 계층 내의 어떤 클래스가 메시지를 처리하거나 최상위 부모 클래스에 위임할 때까지 계속된다.

합성관계

  • 상품 주문을 생각해보자.
    • 여러 상품을 한번에 주문할 수 있다.
    • 이때 각 상품을 몇 개 주문했는지를 가리켜 주문 항목이라고 한다.
    • 각 주문 항목은 주문과 독립적으로 존재할 수 없다. 주문 항목은 반드시 어떤 한 주문의 일부로 생성되기 때문에 주문의 일부여야 한다.
    • 객체와 객체 사이의 전체-부분 관계를 구현하기 위해서는 '합성 관계'를 사용한다.
  • 상품과 주문 항목 사이에도 관계가 존재하지만 상품은 주문 항목의 일부가 아니다.
    • 따라서 주문과 주문 항목 사이의 관계는 전체와 부분 간의 관계를 나타내는 합성 관계인데 비해
    • 주문 항목과 상품 간에는 단순한 물리적 통로가 존재한다는 사실만 나타낸다. 이를 연관관계라고 한다.
  • 합성 관계로 연결된 객체는 포함하는 객체가 제거될 때 내부에 포함된 객체도 함께 제거된다.
  • 합성 관계는 생명주기 측면에서 연관 관계보다 더 강하게 객체들을 결합한다.

 

패키지

  • 합성 관계를 이용해 커다란 객체 그룹을 단순화하더라도 클래스의 수가 많아지면 얽히고 설킨 클래스 간의 의존성을 관리하는 일은 악몽으로 변해 간다.
  • 소프트웨어는 물리적인 형체라는 것이 존재하지 않으므로 구조를 단순화하기 위해서는 서로 관련성이 높은 클래스 집합을 논리적인 단위로 통합해야 한다.
  • 소프트웨어의 전체적인 구조를 표현하기 위해 관련된 클래스 집합하나의 논리적인 단위로 묶는 구성 요소패키지(package) 또는 모듈(module)이라고 한다.
  • 패키지를 이용하면 시스템의 전체적인 구조를 이해하기 위해 한 번에 고려해야 하는 요소의 수를 줄일 수 있다.
  • 또한 개별 클래스가 아닌 클래스의 집합을 캡슐화함으로써 전체적인 복잡도를 낮출 수 있다.
  • 합성 관계가 내부에 포함된 객체들의 존재를 감춤으로써 내부 구조를 추상화하는 것처럼 패키지는 내부에 포함된 클래스들을 감춤으로써 시스템의 구조를 추상화한다.
반응형

댓글