-
이번 장을 읽으면서 궁금했던 거
-
오리 타입과 모듈의 차이
- 오리 타입과 모듈 모두 다형성을 구현하는 방법
- 오리 타입 : 객체가 어떤 클래스를 상속하거나 인터페이스를 구현하지 않더라도 해당 객체가 필요한 메서드나 속성을 가지고 있으면 그 객체를 해당 클래스나 인터페이스의 인스턴스로 간주하는 방식
- 모듈 : 클래스의 일부 기능을 재사용하기 위한 코드 조각.
- 오리 타입은 객체의 행동에 대한 유연한 처리를 위해 사용되며, 모듈은 재사용과 추상화를 위한 일반적인 매커님즘
-
상속과 모듈의 차이
- 다중 상속 가능 여부 -> 클래스는 다중 상속이 불가함.
- 상속과 결합도 -> 모듈은 상속과 비교해서 상대적으로 느슨한 결합을 갖고 있음.
-
용도
- 클래스 상속은 객체의 타입 계층을 만드는데 사용된다.
- 모듈은 코드를 재사용하거나 관련 있는 기능을 묶어서 관리할 때 사용
-
- 같은 역할을 수행하는 객체가 행동을 공유해야 할 때 루비의 모듈을 사용할 수 있다.
- 클래스가 모듈을 include하면 이 모듈 속의 메서드들은 상속을 통해 얻은 메서드들과 동일한 메서드 탐색 경로 속에 들어가게 된다. -> 모듈을 이용하는 코딩 기술과 상속을 이용하는 코딩 기술이 비슷함.
- 이 장에서는 숨겨진 역할을 찾아내고 그 행동을 여러 수행자들이 고유할 수 있도록 해주는 코드를 작성
역할
-
역할
- 연관이 없는 객체들이 공유하는 공통의 행동
-
역할 찾기
-
오리 타입은 하나의 역할이다. -> 5장의 Preparer은 Preparable 역할을 수행하는 오리 타입
- Preparer 처럼 행동하려면 Preparable 인터페이스만 공유하면 된다.
- 메서드 시그니처를 공유할 뿐 코드를 공유하지 않는다.
-
책임 찾기
- 주어진 요구사항에서 객체들이 충족해야 하는 조건을 찾는다.
-
요구사항을 만족하기 위해서 어떤 것이 어떤 책임을 가져야 하는지 찾는다.
- 여행 스케줄 짜기 요구사항
- Schedule은 대상이 어떤 일정을 소화햐야 하는지 알고 있어야 하고, 대상을 전체 일정에 추가하거나 제거해야 하는 책임을 지고 있다. (초반 단계)
-
책임을 찾고 안티패턴으로 구현해보기 -> 안티패턴에서 불필요한 의존성을 찾아 없애기
- Schedule 클래스에서 각 클래스의 이름으로 구체적인 값을 확인하고 있음 -> 어떤 메시지를 전송해야 할지 알기 위해 클래스를 체크하는 안티 패턴
- target으로 들어오는 대상들이 Schedulable 메시지를 처리할 수 있도록 리팩터링 해야한다.
- 특정 클래스 이름을 명시하지 않고 메시지를 target에 보내는 것으로 표현하면 된다. Schedule은 target의 클래스에 전혀 관심이 없고 그저 target이 특정한 메시지에 반응할 수 있기를 바랄 뿐이다. 이러한 메시지 기반의 관점은 클래스 속으로 투과해 들어가서 그 속에 숨겨진 역할을 끄집어 낸다.
-
중간 객체 없애기
- 객체가 자기 스스로를 표현할 수 있게 하기
-
Schedule 객체는 제3 객체
- 시작객체가 Schedule을 알아야 한다고 강제하는 것이고 Schedule에 의존하게 만든다.
- 시작 객체에서 target에 해당하는 객체에 바로 scheduable 메시지 전달로 리팩터링
-
구제적인 코드 작성
- 코드가 무엇을 해야 하는지, 그리고 코드를 어디에 두어야 하는지 결정해야 한다. 두 가지 결정을 분리해서 다룰 것
- 무엇을 해야 하는지 -> 166p Bicycle 클래스
- 어디에 두어야 하는지 -> 167p Schedulable 모듈
-
-
상속인 것과 상속처럼 행동하는 것의 차이
- 클래스 상속을 사용하는 것과 모듈을 사용하는 것
-
모듈을 사용하는 것이 고전적 상속의 엄밀한 정의에 부합하지는 않는다.
- 하지만 코드를 어떻게 작성해야 하는지 그리고 메시지가 어떻게 처리되는지를 보면 상속과 비슷하게 처리된다. (메서드 탐색 경로)
- 이 두 코딩 기술이 모두 자동화된 메시지 전달에 기반하고 있기 때문에 비슷하게 느껴짐.
상속 받을 수 있는 코드 작성하기
-
안티패턴 발견
- type이나 category와 같은 이름을 가진 변수가 있고 이 변수를 가지고 어떤 메시지를 전송할 지 결정하는 안티 패턴
- 객체의 클래스를 확인하고 어떤 메시지를 전송할지 판단하는 안티 패턴
- 이 두 안티패턴은 새로운 클래스나 수신자를 만들 때마다 코드를 수정해야 한다.
-
추상화된 코드는 모두 사용할 것
- 모든 하위 클래스가 아니라 몇몇 하위클래스에게만 적용되는 코드가 상위 클래스에 포함되어 있으면 안된다.
- 하위 클래스가 상속받은 메서드를 재정의해서 '나는 이런것을 하지 않습니다.' 라고 말하고 있다면 사실은 나는 이런 것이 아닙니다 라고 말하는 것과 별반 다르지 않다.
-
리스코프 치환 법칙
- 대체 가능성 : 객체들이 우리가 예측할 수 있게 행동할 때만 보장된다.
- 타입 시스템이 정상적으로 작동하려면 상위타입은 자신의 하위타입으로 치환될 수 있어야 한다.
- 템플릿 메서드와 훅 메서드 사용 -> 6장 참고
-
상속 관계 낮게 만들기
- 훅 메서드의 한계
- 높이가 낮고 너비가 좁은 구조는 이해하기가 쉽다.
- 높은 상속 관계의 문제는 메시지 탐색 경로가 매우 길다.
- 대부분의 프로그래머들은 구조의 가장 윗단과 가장 아랫단에만 익숙하는 점.