오브젝트

기록의 습작·2023년 4월 2일
0

최근에 조영호님의 객체지향의 사실과 오해라는 책을 너무 재미있게 읽어서 그 다음으로 읽을 책을 찾아보고 있었는데, 조영호님의 오브젝트라는 책을 주변에서 너무너무 추천해주길래 궁금해서 바로 구매해버렸다..!

책을 읽고 중요한 개념들만 간단히 정리해보려고 한다.


  1. 실행중에 제대로 동작하더라도, 변경이 용이해야 하고, 이해하기 쉬워야 한다.

    • 변경이 용이하지 못하면 한 객체의 수정이 다른 객체의 수정으로 영향을 끼치게 되어 코드가 일시에 흔들리게 된다는 것 (최소한의 의존성, 낮은 결합도)
    • 이해하기 쉬워야 한다는 것은 우리의 예상에서 크게 벗어나지 않아야 한다는 것과 한 메소드가 많은 세부사항을 다루고 있으면 부담이 된다는 것
  1. 객체를 자율적인 존재로 만들자.

    • 자신의 일은 자신이 하자. (자신의 데이터를 책임진다.)
    • 다른 객체의 세부사항을 굳이 알 필요 없다. (캡슐화)
      즉, 다른 객체의 인터페이스에만 의존하며, 구현을 알 필요가 없다.
  1. 외부 간섭을 최대한 배제하고, 메시지를 통해 협력하자.

    • 데이터와 프로세스가 동일한 모듈 내부에 위치해야 한다.
  2. 어느정도 트레이드오프의 시점이 존재한다.

    • 훌륭한 설계는 적절한 트레이드오프의 결과물이다.
  1. 객체지향 패러다임의 핵심 -> 역할, 책임, 협력
    • 객체지향의 본질은 협력하는 객체들의 공동체 창조
    • 어떤 협력이 필요하고 협력을 위해 어떤 역할과 책임이 필요한지 고민하지 않은 채 구현에 초점을 맞춘다면, 변경하기 어렵고 유연하지 못한 코드를 낳는다.
    • 협력 : 애플리케이션 기능을 구현하기 위해 수행되는 상호작용
    • 책임 : 객체가 협력에 참여하기 위해 수행하는 로직
    • 역할 : 협력 안에서 수행하는 책임들이 모여 객체가 수행하는 역할을 구성
  1. 협력
    • 객체지향 세계에서 기능을 구현할 수 있는 방법이다.
    • 객체 사이의 메시지 전송을 통해 협력을 한다. (즉, 한 객체가 다른 객체에게 무엇인가를 요청하는 것이다.)
    • 객체는 다른 객체의 내부 구현에 직접 접근할 수 없기 때문에 오직 메시지 전송을 통해서만 요청할 수 있다.
    • 메시지를 수신한 객체는 메서드를 실행해 요청에 응답한다.
    • 외부 객체는 오직 메시지만 전송하고, 메시지를 어떻게 처리할지는 수신한 객체가 자율적으로 결정한다.
    • 자신이 할 수 없는 일을 외부 객체에게 위임하면, 전체적인 자율성을 향상시킨다.
    • 객체의 상태와 행동을 결정하는 것은 객체가 참여하는 협력이다.
      • 협력을 통해 결정된 행동으로 상태를 결정한다. (협력이 제일 상위)
    • 협력이 설계를 위한 책임 결정 문맥을 제공한다. (ex. 영화 예매 협력에서의 Movie 객체)
  1. 책임
    • 협력에 참여하기 위해 객체가 수행하는 행동 (응집도 있는 행위의 집합)
    • '아는 것' + '하는 것'
      • 아는 것 : 사적인 정보, 관련된 객체, 자신이 유도하거나 계산할 수 있는 것 등
      • 하는 것 : 객체 생성 및 계산 수행, 다른 객체의 행동 시작, 다른 객체의 활동 제어 등
    • 책임은 협력안에서 객체의 외부 인터페이스와 내부 속성을 결정한다.
    • 적절한 협력은 적절한 책임을 제공하고, 적절한 책임은 적절한 객체에게 할당된다.
    • 객체에게 얼마나 적절한 책임을 할당하냐가 설계 전체 품질을 결정한다. (책임 주도 설계)
    • 책임 할당 시 고려해야하는 요소
      • 메시지가 객체를 결정 : 책임을 할당할 메시지를 먼저 식별하고 메시지를 처리할 객체를 선택한다. 이렇게 하는 이유는 다음과 같다.
        • 최소한의 인터페이스를 가지게 된다. (꼭 필요한 크기의 인터페이스)
        • 추상 인터페이스를 가질 수 있게 된다. (객체의 인터페이스는 무엇을 하는지 표현해야 하지만 어떻게 수행하는지 노출해선 안된다. 메시지는 외부 객체가 요청하는 무언가를 의미하기 때문에 메시지를 먼저 식별하면 무엇을 수행할지 초점을 맞추는 인터페이스를 얻을 수 있다.
      • 행동이 상태를 결정 : 객체가 협력에 적합한지 결정하는 것은 객체의 상태가 아닌 행동이다. 따라서 상태에 초점을 맞추면 안된다. 협력이 객체의 행동을 결정하고, 행동이 상태를 결정하며, 그 행동이 책임이 된다.
  1. 역할
    • 객체가 어떤 특정한 협력 안에서 수행하는 책임의 집합
    • 역할을 통해 유연하고 재사용 가능한 협력을 얻을 수 있다. (추상화)
    • 일반적으로 추상클래스와 인터페이스를 사용하여 역할을 정의한다.

오늘은 조영호님의 오브젝트 2장 객체지향 프로그래밍을 읽고 배운점을 정리해보려고 한다.

  1. 클래스의 내부와 외부를 구분하자.
    • 경계의 명확성이 객체의 자율성을 보장
    • 프로그래머에게 구현의 자유를 제공
  1. 객체지향의 핵심은 객체를 자율적인 존재로 만드는 것이다.
    • 스스로 상태를 관리하고, 판단하고, 행동하는 공동체를 구성하는 것
    • 외부의 간섭을 최소화
    • 객체 스스로 최선의 방법을 결정해야 한다.
    • 인터페이스와 구현의 분리
    • 내부 구현 은닉
    • 변경에 대한 혼란을 최소화 시킬 수 있다.
  1. 하나의 인스턴스 변수만 포함하더라도 명시적인 개념을 표현하기 위해 객체를 생성해도 좋다.
    • 명시적이고 분명할 뿐만 아니라, 전체적인 설계의 명확성과 유연성을 높인다.
  1. 협력의 관점에서 어떤 객체가 필요한지 결정하고, 공통 상태와 행위를 구현하기 위해 클래스를 작성한다.
  1. 메시지 전송과 수신을 통해 객체는 다른 객체와 상호작용한다.
    • 객체는 메서드를 통해 자신만의 방법으로 메시지를 처리한다.
  1. 상속과 다형성을 통해 코드를 유연하게 만들 수 있다.
    • 설계가 유연해질수록 코드를 이해하고 디벙깅하기는 점점 더 어려워진다.
    • 유연성을 억제할 수록 재사용성과 확장 가능성은 낮아진다.
    • 다형성은 컴파일 시간 의존성과 실행 시간 의존성을 다르게 만들 수 있다.
    • 상속이 오로지 코드의 재사용을 위해서 사용된다면, 변경에 취약한 코드를 낳게 할 확률이 높다.
    • 내부 구현을 공유할 필요가 없고 순수 인터페이스만 공유해야 한다면, 추상 클래스가 아닌 인터페이스를 사용하면 된다.
  1. 추상화
    • 추상화 계층만 따로 떼어 놓고 보면 요구사항의 정책을 높은 수준에서 서술할 수 있다.
    • 즉, 세부 내용은 무시한 채 쉽고 간단하게 표현할 수 있다. (표현 수준을 조정)
    • 기존 구조를 수정하지 않고도 새로운 기능을 쉽게 추가 및 확장할 수 있어 설계가 더욱 유연해진다.
  1. 책임의 위치를 결정하기 위해 조건문을 쓰는 것은 좋지 않다. (예외 케이스를 최소화하고 일관성을 유지하자.)
  1. 상속과 합성을 적절하게 함께 사용하자
    • 상속은 캡슐화를 위반하고, 설계를 유연하지 못하게 한다.
      • 캡슐화 위반 : 부모 클래스의 내부 구조를 잘 알고 있어야 한다. 왜냐하면 부모 클래스를 기반으로 자식 클래스의 코드를 구현해야 하기 때문이다. 자식 클래스에서 super를 이용해 부모 클래스의 메소드를 호출하는 상황이라면 부모 클래스의 구현은 자식 클래스에게 노출되어 캡슐화가 약해지고, 자식 클래스와 부모 클래스는 강하게 결합되어 부모 클래스를 변경할 때 자식 클래스도 함께 변경될 가능성이 높아진다.
      • 유연하지 않은 설계 : 실행 시점에 객체의 종류를 변경하는 것이 불가능하다.
    • 합성은 이러한 상속의 두가지 문제점을 모두 해결한다.
    • 그렇다고 상속을 쓰지말라는 것이 아니다! 함께 사용하면 된다!
      • 변경에 대한 유연함과 코드의 재사용 + 다형성을 통한 인터페이스 재사용이 가능해진다.
profile
GyUL의 Backend 개발일기

0개의 댓글