본문 바로가기

공부기록/객체지향

오브젝트 2장 - 객체지향 설계

영화 예매 시스템으로 예시( 충분히 복잡하다고 생각하자)

내부와 외부를 구분해야하는 이유( 멤버변수를 pirvate으로 선언하는 이유)

→ 객체에게 자율성을 주기 위해서( 남이 못건드리게 하기 위해서)

내부에서만 접근 가능한 것 = 구현

외부에서 접근 가능한 public = 인터페이스

프로그래머의 역할을 클래스 작성자와 클라이언트 프로그래머로 구분하는 것이 유용

→ 클래스 작성자는 새로운 데이터 타입을 추가하고, 클라이언트 프로그래머는 클래스 작성자가 추가한 데이터 타입을 사용

클래스 작성자는 클라이언트 프로그래머에게 필요한 부분만 공개하고 나머지는 꽁꽁 숨겨야 한다.

Money 클래스, 돈과 관련된 일을 처리해줌. long과 같은 것을 쓸수도 있었겠지만, 도메인의 의미를 풍부하게 해줌

협력의 관점에서 어떤 객체가 필요한지를 결정하고, 객체들의 공통 상태와 행위를 구현하기 위해 클래스를 작성

메서드와 메서지의 구분 = 다형성

→ 메시지는 수신받는 객체에 따라 다르게 처리될 수 있음

할인을 위한 협력

Movie 영화의 가격, 영화의 정보들

할인 정책

할인 조건

얘내끼리 서로 협력

부모 클래스에 기본적인 알고리즘의 구현을 구현하고 중간에 필요한 처리를 자식 클래스에게 위임하는 디자인 패턴을 템플릿 메서드 패턴

코드의 의존성과 실행시점의 코드의 의존성은 다를 수 있음

클래스의 의존성과 객체사이의 의존성이 다를 수 있음

객체지향 설계가 가지는 특징은 코드의 의존성과 실행 시점의 의존성이 다르다는 것

다르면 다를수록 코드를 이해하기 어려워진다는 것 →

다르면 다를수록 더 유연해지고 확장가능해짐

→ 설계가 트레이드오프의 산물이라는 사실

코드가 유연해질 수록→ 코드를 이해하고 디버깅하기 점점 더 어려워짐

유연성을 억제하ㄴ면, 코드를 이해하고 디버깅하기는 쉬워지지만 재사용성과 확장 가능성은 낮아진다.

유연성과 가독성 사이에서 고민해야한다.

어려우면서도 매력적인 이유

실행시점에 어떻게 구현클래스의 의존성으로 바뀔 수 있을까?

상속으로 부모 클래스와 다른 부분만을 추가해서 새로운 클래스를 쉽고 빠르게 만드는 방법을

차이에 의한 프로그래밍이라고 부른다.

상속의 가치

기존: 부모 클래스의 모든 메서드나 인터스턴스 변수를 재사용

→ 모든 인터페이스를 자식이 물려받을 수 있음

→ 자식 클래스는 부모 클래스의 모든 메시지를 수신할 수 있다.

특정 메시지만 이해할 수 있으면 상관없음

→ 상속으로 해당 메시지를 이해할 수있음을 알 수있음

자식 클래스가 부모 클래스를 대신하는 것을 업캐스팅(너무 당연한 이야기 아닌가?)

다형성

메시지와 메서드는 다른개념

메시지를 전송한다 → 실행되는 메서드는 연결된 객체의 클래스가 무엇인가에 따라 달라진다.

같은 메시지를 전송해도 실제로 어떤 메서드가 실행될 것인지는 메시지를 수신하는 객체의 클래스가 무엇이냐에 따라 달라지고, 이것을 다형성이라고 한다.

프로그램의 컴파일 시간 의존성과 실행 시간 의존성이 다를 수 있다는 사실을 기반으로 한다. → 모두 같은 메시지를 이해할 수 있어야하고, 다형적인 협력에 참여할 수 있는 이유는 동일한 인터페이스를 물려받았기 때문

실행 시점에 결정한다는 공통점 → 지연 바인딩, 또는 동적 바인딩이라고 한다.

전통적인 함수 호출처럼 실행될 함수나 프로시저를 결정하는 것을 초기 바인딩 또는 정적 바인딩이라고 부른다.

지연 바인딩을 사용하기 때문에 괜찮!

상위의 협력 흐름 → 디자인 패턴이나 프레임워크 모두 추상화를 이용해 상위정책을 정의하는 객체지향의 메커니즘( 스프링에서 보았듯이 확실히..)

컨텍스트 독립성? → 특정한 구현 클래스에 묶이지 않아서 변경할 수 있는.. 프레임워크와 같은 유연한 설계가 필수적인 분야에서 그 진가를 발휘한다.

유연성이 필요한 곳에 추상화를 사용하라(당연한 이야기)

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

구현과 관련된 모든 것들이 트레이드 오프 될 수 있다

아주 사소한 결정이라도 트레이드오프를 통해 얻어진 결론과 그렇지 않은 결론 사이의 차이는 크다.

상속이 좋긴 하지만 컴포지션이 더 좋음

상속 : 캡슐화 위반, 설계를 유연하지 못하게 만듬

옵션을 수십개 만들수 있겠지만, 상속으로 하려면..?

캡슐화 위반 → 부모의 내부 구조를 알고 있어야함

유연성 저하: 부모 클래스 변경시 → 자식 클래스도 함께 변경될 수 있음

상속 → 부모 클래스와 자식 클래스 사이의 관계를 컴파일 시점에 결정

컴포지션 → 런타임에 결정!! ( 이거 어디서 많이본..)

→ 상속이 가지는 두 가지 문제점을 모두 해결

의존하는 인스턴스를 쉽게 교체할 수 있음. 느슨한 결합

상속과 합성을 함께 사용해야 한다.

다형성을 위해 인터페이스를 재사용하는 경우에는 상속을 사용할 수 밖에 없음

객체지향에서 가장 중요한 것은 객체 사이의 상호작용