해당 챕터에서는 영화 예매라는 예제를 초점으로 이야기를 이어가고 있다.
하나씩 살펴보자
요구 사항
해당 예제는 다음과 같이 요구사항을 구분지었다.
- 영화
- 영화에 대한 기본정보
- 상영
- 실제로 관객들이 영화를 관람하는 사건
우리가 CGV등 각각의 영화를 예매할 때 해당 영화의 정보, 각 CGV별 할인정책이 다름을 알 수 있다.
위 예제를 사건으로 이야기 해보자면 큰 카테고리 두가지를 두고 그 밑의 ( 할인정책, 할인조건 ) 등을 생각해볼 수 있을것이다.
여기서 나는 아! 큰 상위 모듈을 기반으로 하위를 차례대로 생각하는구나 다른말로 마인드 맵이 떠올랐다.
객체지향 프로그래밍을 향해
- 객체지향은 객체를 지향한다.
우리는 객체지향 프로그램을 작성할때 어떤 클래스가 필요한지 고민한다. 하지만 이는 객체지향의 본질과는 거리가 멀다.
진정한 객체지향은, 말 그대로 객체를 지향하는 것이다.
여기서의 핵심은 클래스가 아닌 객체에 초점을 맞추는 것인데 이를 위해서는 두 가지에 집중해야 한다.
- 어떤 클래스가 필요한지를 고민하기 전에 어떤 객체들이 필요한지 고민하라
- 객체를 독립적인 존재가 아닌, 기능을 구현하기 위해 협력하는 공동체의 일원으로 봐야한다.
소프트 웨어는 사용자가 원하는 어떤 문제를 해결하기 위해 만들어지는데,
이 때 이야기하는 사용자가 프로그램을 사용하는 분야를 도메인으로 이야기 하여 설계할 수 있다.
위 설계처럼 각각의 도메인들을 기반으로 객체 와 이를 받쳐줄 수 있는 클래스로 매끄럽게 연결이 가능하다.
클래스 구현하기
- 클래스의 경계를 구분하라!
나는 다음과 같이 이부분이 핵심이라고 생각이 들었다.
클래스는 내부와 외부로 구분되며 훌륭한 클래스를 설계하기 위한 핵심은 어떤 부분을 외부에 공개하고 어떤 부분을 감출지 결정하는 것이다.
즉, 외부에서는 해당 객체의 속성에 직접 접근을 할 수없도록 막고, 메서드를 통해 해당 내부를 변경할 수 있도록 구분을 지어놓아야 한다.
왜 구분지어야 할까?
이유는 경계의 명확성이 객체의 자율성을 보장하기 때문이고, 프로그래머에게 구현의 자유를 주기 때문이다.
자율적인 객체
- 객체가 상태(state) 와 행동 (behavior)을 통해 가지는 복합적인 존재
- 객체가 스스로 판단하고 행동하는 자율적인 존재
이처럼 데이터와 기능을 객체 내부로 함께 묶는 것을 캡슐화라고 한다.
객체지향의 핵심은 스스로 상태를 관리하고, 판단하고, 행동하는 자율적인 객체들의 공동체를 구성하는 것으로 이야기할 수 있다.
나는 이부분에서, 최대한 객체 스스로가 해결할 수 있는일은 객체에게 시키고
서비스 로직내에서는 그에 대한 결과만 주도록 하는 TDA (Tell Don't Ask) 가 생각이 났었다. (캡슐화 게시물에 해당내용이 있어요! )
프로그래머의 자유
- 클래스 작성자 (class creater )
- 새로운 데이터 타입을 프로그램에 추가한다.
- 클라이언트 프로그래머에게 필요한 부분만 공개하고, 나머지는 보여주지 않는다.
- 클라이언트 프로그래머 ( client programmer )
- 클래스 작성자가 추가한 데이터 타입을 사용한다.
- 필요한 클래스들을 엮어서 애플리케이션을 빠르고 안정적으로 구축한다.
클라이언트 프로그래머가 숨겨 놓은 부분에 마음대로 접근할 수 없도록 방지함으로써 클라이언트 프로그래머에 대한 영향을 걱정하지 않고도 내부 구현을 마음대로 변경할 수 있는데 이를 구현 은닉 (implementation hiding) 이라고 한다.
여기까지의 내용을 살펴보았을 때
- 각 클래스별 확실한 경계를 놓는다는 점
- 접근제어를 통해 변경으로 인한 혼란 최소화
이 두가지의 내용을 이야기 하고 있음을 다시한번 알 수 있었다.
협력
- 각각의 객체중 협력이 필요한 객체가 어떤건지를 파악해야한다.
- 객체들의 공통 상태와 행위를 구현하기 위해 클래스를 작성한다.
위와 같이, 어떠한 객체가 협력이 필요한지를 파악한 후, 클래스를 작성함이 중요함을 알았다.
상속 , 다형성 , 추상화
해당 책을 읽으며 핵심이라고 생각되는 이 세가지를 묶어보았다.
상속
- 객체지향에서 코드를 재사용하기 위해 가장 널리 사용되는 방법
- 클래스 사이의 관계를 설정하는 것만으로 기존 클래스가 가지고 있는 모든 속성과 행동을 새로운 클래스에 포함 시킬 수 있다.
- 기존 클래스를 기반으로 새로운 클래스를 쉽고 빠르게 추가할 수있는 간편한 방법 제공
- 이처럼 , 부모 클래스와 다른 부분만을 추가해 새로운 클래스를 쉽고 빠르게 만드는 방법을 차이에 의한 프로그래밍이라고 한다.
다형성
- 어떠한 메서드가 실행될 것인지 메시지를 수신하는 객체의 클래스에 따라 다양하게 달라진다.
- 메시지에 응답하기 위해 실행될 메서드를 컴파일 시점이 아닌 실행 시점에 결정한다.
- 지연 바인딩 ( Lazy binding )
- 동적 바인딩 ( dynamic binding )
- 초기 바인딩 (early binding )
- 정적 바인딩 (static binding )
상속 vs 다형성
상속을 사용하기 위해서는 부모 클래스에 대한 정보를 알고 있어야한다 즉, 부모 클래스에 의존성이 크다는 점이라고 보았다.
이는, 다음과 같은 문제점을 이야기한다.
- 캡슐화를 위배한다.
- 설계가 유연하지 않다.
당연한 이야기이다. 다음과 같이 강하게 결합되어 있다면, 이후, 변경이 어려워진다는 단점은 당연히 가질것이다.
위는, 인터페이스를 이용한 추상화 계층이다.
추상화는 상속과 다르게, 부모 클래스를 호출하지 않기에, 변경이 유연한 설계가 가능해진다.
이전, 상속을 통한 구현 이후 코드 컨펌을 받았을 때 해당 이야기를 들었고 설명을 들었었다.
이후, 해당 챕터를 보며 다시한번 확실하게 와 닿았다.
내기준에서 해당 부분의 결론을 한번 지어보려고한다.
결론
- 유연한 설계를 해야한다.
- 상속 < 추상화
- 느슨한 결합
- 적절한 협력을 식별하고 협력에 필요한 역할을 정의한 후, 역할을 수행할 수 있는 적절한 객체에게 적절한 책임 할당
'BOOK' 카테고리의 다른 글
[BOOK : 3장] 역할, 책임, 협력 (2) | 2022.10.27 |
---|---|
[BOOK : 클린코드 1장] 깨끗한 코드 (0) | 2022.10.23 |
[BOOK : 오브젝트 1장] 객체, 설계를 읽고 (0) | 2022.10.20 |
[OOP] 캡슐화 (0) | 2022.10.08 |
[OOP / 객체지향] 들어가며 (0) | 2022.09.19 |