일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 카카오 서류전형
- 백준12015
- 2629
- 기술면접
- 파이썬
- 2228
- Longest Increasing Subsequence
- 개발자 면접
- 카카오 인턴십
- 백준11053
- 알고리즘
- 가장긴증가하는 부분수열
- 백준12738
- 카카오 면접
- 단어수학
- 정상회담2
- Python
- 최장증가수열
- LIS 알고리즘
- 2482
- 카카오 자기소개서
- 인턴십 면접
- 백준
- 구간나누기
- 1670
- LIS
- 카카오 인턴
- 카카오
- DP
- 여름인턴십
- Today
- Total
프로그래밍에 대한 고찰 및 생각
[2][오브젝트] - 객체지향 프로그래밍 본문
오브젝트의 두번째 챕터인 '객체지향 프로그래밍'에서는 '영화예매 시스템'을 기반으로 객체지향 패러다임에 대해 설명한다.
해당 시스템에 대해 간략하게 설명하면
- 하나의 예매(Reservation)에는 하나의 상영(Screening) 및 상영시간과 순서가 존재한다.
- 하나의 상영에는 하나의 영화(Movie)가 존재하고, 하나의 영화에는 요금과 할인 정책이 존재한다.
- 할인 정책은 특정 금액을 할인해주는 정책(Amount DiscountPolicy)과 특정 비율을 할인해주는 정책(Percent DiscountPolicy)이 존재하며, 할인 조건으로는 상영순서에 따른 조건(Sequence Condition)과 상영기간에 따른 조건(Period)가 존재한다.
01. 객체지향 패러다임으로의 전환
클래스가 아닌 객체에 초점을 맞출 것. 어떤 클래스가 필요한지를 고민하기 전에 어떤 객체들이 필요한지 고민하자.
객체를 독립적인 존재가 아니라 기능을 구현하기 위해 협력하는 공동체의 일원으로 보자
02. 구현 은닉(Implementation hiding)
클래스를 설계할 때 필요한 부분만 공개하고 나머지는 마음대로 접근할 수 없도록 방지하여 내부를 구현하는 것을 구현 은닉 이라고 한다.
클래스를 구현하는 사람은 인터페이스를 유지한채 내부를 마음대로 변경할 수 있고 (자유로운 구현 가능)
클래스를 사용하는 사람은 내부 구현을 무시한 채 인터페이스만 알고 있어도 클래스를 사용할 수 있다 (알아야할 지식의 양 감소)
03. Money Type
본 책에서는 영화 예매 시스템의 금액을 구현할 때 Money 라는 클래스를 만들어 사용했다.
보통 금액을 구현할 때 Integer 또는 long 타입을 떠올렸는데 새로운 클래스를 만들어서 사용하는 것이 인상깊었다.
이를 통해 다음 두가지의 이점을 얻을 수 있었다.
1. 해당 변수가 금액을 의미한다는 것을 더 명시적으로 전달할 수 있다.
2. 금액과 관련된 로직이 다른 곳에 중복되어 구현되는 것을 방지할 수 있다.
비록 한가지 인스턴스 변수만 포함한 클래스더라도 이러한 설계가 설계의 명확성과 유연성을 높여주었다.
04. 코드의 의존성, 실행 시점의 의존성
DiscountPolicy class가 Abstract class로 구현되어 있을 때, 코드의 의존성과 실행 시점의 의존성이 달라질 수 있다.
Movie에서 DiscountPolicy 인스턴스를 넣어주기 전에는 Amount DiscountPolicy를 의존할지, Percent DiscountPolicy를 의존할지 알 수 없다.
실제로 둘 중 어떤 인스턴스를 넣는지 확인하기 전까지 알 수 없다는 의미이다. 이 두 시점의 의존성이 달라질수록 코드를 이해하기 어려워진다.
설계가 유연해지면, 코드를 이해하고 디버깅하기 어려워지고
유연성을 억제하면 코드를 이해하고 디버깅하기 쉬워지지만, 재사용성과 확장 가능성이 낮아진다.
즉 각각의 방법이 장단점이 존재하며 Trade Off가 존재한다는 것이다.
요즘 개발을 하면서 가장 많이 느끼고 있는 부분이다. 어떤 것을 결정할 때 항상 장점만 있는 선택은 그리 많지 않았다. 한쪽을 추구하면 다른 한쪽을 포기해야하는 상황이 많았다.
05. 상속, 인터페이스 + 다형성 with 할인 정책
부모의 인터페이스를 자식이 상속받으면 자식은 부모의 모든 인터페이스를 사용할 수 있다.
나는 지금까지 인터페이스를 대할 때 중복으로 사용되는 인스턴스 변수나 메서드를 줄이기 위해 사용했던 것 같다. 이 책에서는 대부분의 사람들이 이와같이 생각하고 있다는 것을 정확히 짚어주었다. (뜨금)
이 책에서는 조금 다른 시각으로 인터페이스를 바라본다. 인터페이스는 객체가 이해할 수 있는 메시지의 목록을 정의하는 것이고, 자식 클래스는 부모 클래스가 수신할 수 있는 모든 메시지를 수신할 수 있다.
public class Movie{
...
public Money calculateMovieFee(Screening screening) {
return fee.minus(discountPolicy.calculateDiscountAmount(screening));
}
}
그래서 Movie 에서 할인 가격을 계산할 때 실제로 해당 객체가 Amount DiscountPolicy인지, Percent DiscountPolicy인지 중요하지 않다. 그저 calculateDiscountAmount()라는 메세지를 수신할 수 있기만 하면 그만이다.
이처럼 자식 클래스가 부모 클래스를 대신하는 것을 업캐스팅(Upcasting) 이라고 한다.
그리고 calculateDisCountAmount() 는 메세지이다.
실제로 실행되는 메소드는 실제로 연결된 객체의 클래스가 Amount냐 Percent냐에 따라 Override 된 함수에 따라 달라질 것이다.
이처럼 동일한 메세지를 전송하지만, 메세지를 수신하는 수신하는 객체의 클래스가 무엇이냐에 따라 달라지는 것을 다형성이라고 한다.
Interface vs abstract class
예제들을 보다보니 이 둘의 차이가 궁금해졌다. 사실 interface는 자주 사용해서 익숙했는데 abstract 는 자주 사용하지 않아 익숙하지 않았고, 막상 둘을 비교하니 아주 비슷해보였다.
정의부터 살펴보자.
abstract class : 하나 이상의 추상 메소드(abstract method)가 포함된 클래스.
interface : 오로지 추상메소드와 상수만을 가짐.
* 여기서 추상 메소드란 내부 구현이 되어있지 않아 상속받는 클래스에서 해당 추상 메소드를 재정의 해야하는 메소드를 말한다.
이렇게보면 추상 클래스가 인터페이스를 포함하는 개념같아 보인다. 그렇다. 추상 클래스가 인터페이스를 대체할 수 있다. 그러나 둘은 사용의도에 따라 사용처가 달라진다.
일단 둘의 공통점을 살펴보면 둘다 추상 메소드를 가진다는 점이고, 차이점은 추상 클래스는 추상 메소드가 아닌 일반 메소드도 가질 수 있다는 것이다.
즉 상속받을 클래스들이 일부는 내부 구현이 동일한 메소드를 가져야한다면 추상 메소드를 사용하면 좋을 것이고, 상속받을 클래스들이 모두 다른 내부 구현을 가져야한다면 인터페이스가 적절할 것이다.
그렇다면 위의 내용대로 추상 클래스가 인터페이스를 완벽히 대체하는데 인터페이스는 필요없는 것이 아닌가?
추상 클래스의 단점은 상속받을 때 복수의 추상 클래스를 상속받을 수 없다는 점이다. 그에 반해 인터페이스를 여러 인터페이스를 상속받을 수 있다.
06. 마치며
이번 장에서부터 본격적인 객체지향 설계에 대한 내용들이 많이 나왔던 것 같다. 다형성, 인터페이스, 추상 클래스, 구현 은닉, 상속 등 한번 쯤은 들어왔고 자주 사용하던 것들이지만 해당 내용에 대해 깊게 고민해본 적은 없었던 것 같다. 그래서 하나하나 찾아보는데 시간이 많이 소요가 되어서 이번 챕터를 공부하는데 꽤나 오랜시간이 걸렸던 것 같다.
이 책의 필자가 어떤 생각으로 코드를 설계했는지 의도를 100% 정복하지는 못한 것 같고 다만 어느정도 느낌을 받은 정도에 그쳤던 것 같다. 객체지향 쉽지않다.. 그래도 책을 읽어가면서 실제로 개발하다가 들었던 생각들을 필자가 언급해줄 때마다 그래도 조금씩 객체지향과 가까워지고 있지 않나 하는 생각이 든다.
아무래도 이 책은 한번 읽고 나중에 또 읽어야할 것 같다.
'책 > 오브젝트' 카테고리의 다른 글
[1][오브젝트] - 객체, 설계 (0) | 2022.01.08 |
---|---|
[0][오브젝트] - 시작 (0) | 2022.01.08 |