오브젝트 2장 - 객체지향 프로그래밍

변은서·2022년 12월 18일
0

오브젝트

목록 보기
2/3

이번주부터 두 챕터씩 읽기로 했다.

영화 예매 시스템

영화 예매 시스템을 예시로 내용을 이어가고자 한다. 간단하지만 아주 크고 복잡한 시스템이라고 생각하고 진행해보자.

요구사항 살펴보기

영화는 영화의 기본 정보를 포함하고 상영은 관객이 영화를 관람하는 사건을 표현한다. 특정 조건을 만족하는 예매자는 요금을 할인받을 수 있다. 기간 조건과 순서 조건으로 나뉘는 할인 조건, 금액 할인 정책과 비율 할인 정책으로 나뉘는 할인 정책(할인 요금 결정)이 있다. 기간 조건은 해당 기간에 해당 영화를 예매했을 때 할인받을 수 있다는 조건이며 순서 조건은 해당 순서의 영화를 예매했을 때 할인받을 수 있다는 조건이다. 영화는 하나 이하의 할인 정책을 가질 수 있으며 할인 정책이 있을 경우 하나 이상의 할인 조건을 가질 수 있다.

객체지향 프로그래밍을 향해

협력, 객체, 클래스

어떤 클래스가 필요한지 고민하기 전에 어떤 객체들이 필요한지 고민하라. 객체를 독립적인 존재가 아니라 기능 구현을 위해 협력하는 공동체의 일원으로 보라.

도메인의 구조를 따르는 프로그램 구조

도메인이란 문제를 해결하기 위해 사용자가 프로그램을 사용하는 분야를 일컫는다. 객체치향 패러다임은 요구사항 분석 초기부터 프로그램 구현까지 객체라는 동일한 추상화 기법을 사용할 수 있어 강력하다.

클래스 구현하기

변수의 가시성은 private, 매서드의 가시성은 public이다. 객체는 상태와 행동을 함께 가지는 복합적인 존재이며 이는 스스로 판단하고 행동하는 자율적인 존재이다. 데이터와 기능을 객체 내부로 함께 묶는 것을 캡슐화라고 한다. 내부 접근을 통제하는 이유는 객체를 자율적인 존재로 만들기 위해서다. 외부에서 접근가능한 부분은 퍼블릭 인터페이스(public interface)라고 부르고 외부에서 접근 불가하며 내부에서만 접근 가능한 부분을 구현(implementation)이라 부른다. 일반적으로 객체의 상태는 숨기고 행동만 외부에 공개해야한다.

협력하는 객체들의 공동체

하나의 인스턴스 변수만 포함하더라도 개념을 명시적으로 표현하는 것은 전체적인 설계의 명확성과 유연성을 높이는 첫걸음이다.
객체는 다른 객체의 인터페이스에 공개된 행동을 수행하도록 요청할 수 있으며 객체는 자율적인 방법에 따라 요청을 처리한 후 응답한다. 객체가 다른 객체와 상호작용할 수 있는 유일한 방법은 메시지를 전송하는 것뿐이다. 수신된 메세지를 처리하기 위한 자신만의 방법을 메서드(method)라 부른다.

할인 요금 구하기

할인 요금 계산을 위한 협력 시작하기

책에서 제공된 코드를 보면 어떤 할인 정책을 사용하는지에 대한 내용이 Movie에 없다.

할인 정책과 할인 조건

금액 할인 조건과 비율 할인 조건은 할인 조건을 상속받는다. 할인 조건 인스턴스를 생성할 필요가 없기 때문에 추상클래스로 구현한다. 할인 금액을 요청하는 메서드는 자식 클래스에서 오버라이딩하여 구현한다. 부모 클래스에 기본적인 알고리즘의 흐름을 구현하고 중간에 필요한 처리를 자식 클래스에게 위임하는 디자인 패턴을 Template method pattern이라 부른다.

오버라이딩 vs 오버로딩

부모 클래스의 메서드를 자식 클래스에서 재정의하는 경우를 오버라이딩이라 부르며 같은 이름의 메서드를 매개변수 타입이나 개수를 달리하여 재정의하는 경우를 오버로딩이라 한다.

할인 정책 구성하기

생성자를 잘 설정함으로써 제약을 강제할 수 있다.

상속과 다형성

컴파일 시간 의존성과 실행 시간 의존성

책에 제공된 코드를 확인하면 무비에서 금액 할인 정책을 적용하는지, 비율 할인 정책을 적용하는지 판단하는 부분이 없다. 이는 상속과 다향성을 이용하여 해결한다. 클래스 사이의 의존성과 객체 사이의 의존성은 동일하지 않을 수 있다. 확장가능한 객체지향 설계가 가지는 특징은 코드의 의존성과 실행 시점의 의존성이 다르다는 것이다. 코드의 의존성과 실행 시점의 의존성이 다를수록 코드를 이해하기 어려워진다. 그러나 코드는 더 유연해지고 확장 가능해진다. 의존성의 양면성은 설계가 트레이드오프의 산물이라는 사실을 잘 보여준다. 항상 유연성과 가독성 사이에서 고민해야 한다.

차이에 의한 프로그래밍

새로운 클래스를 만들고자 하는데 기존의 클래스와 매우 흡사할 경우 사용하는 것이 상속이다. 코드를 재사용하기 위해 널리 사용되는 방법이다. 부모 클래스와 다른 부분만을 추가해서 새로운 클래스를 쉽고 빠르게 만드는 방법을 차이에 의한 프로그래밍(programming by difference)라 한다.

상속과 인터페이스

자식 클래스가 부모 클래스를 대신하는 것을 업캐스팅(upcasting) 이라고 부른다.

다형성

메세지에 응답하기 위해 실행될 메서드를 컴파일 시점이 아닌 실행시점에 결정하는 것을 지연 바인딩(lazy binding) 혹은 동적 바인딩(dynamic binding)이라 부른다.

추상화와 유연성

추상화의 힘

추상화를 사용하면 세부적인 내용을 무시한 채 상위 정책을 쉽고 간단하게 표현할 수 있다. 세부사항에 억눌리지 않고 상위 개념만으로도 도메인의 중요한 개념을 설명할 수 있게 한다. 디자인패턴이나 프레임위크 모두 추상화를 이용해 상위 정책을 정의하는 객체지향 매커니즘을 활용하고 있다.

유연한 설계

설계가 구체적인 상황에 결합되는 것을 방지하기 때문에 추상화가 유연한 설계를 가능하게 한다.

추상 클래스와 인터페이스 트레이드오프

작성하는 모든 코드에는 합당한 이유가 있어야 한다.

코드 재사용

상속보다 합성(composition)이 코드 재사용을 위한 더 좋은 방법이다. 합성은 다른 객체의 인스턴스를 자신의 인스턴스 변수로 포함해서 재사용하는 방법을 말한다.

상속

상속은 캡슐화를 위반하고 설계를 유연하지 못하게 만든다.

합성

인터페이스에 정의된 메시지를 통해서만 코드를 재사용하는 방법이다. 다형성을 위해 인터페이스를 재사용하는 경우에는 상속과 합성을 함께 조합해서 사용할 수밖에 없다.

정리

이번 장에서는 객체지향에서 다루는 상속, 인터페이스, 합성, 추상화 등에 대해 공부했다. 대부분 아는 내용이지만 영화, 할인 정책, 할인 조건 등 예시와 함께 한번 더 공부하는 기회가 되었다.

profile
은또

0개의 댓글