kok202
오브젝트 부록

2020. 3. 22. 01:11[공부] 독서/오브젝트

부록 A 계약에 의한 설계

계약에 의한 설계를 이용하면 협력에 필요한 제약, 부수효과를 명시적으로 정의하고 문서화 할 수 있다. [535p]

사설) 자바의 경우 assert or Valid 어노테이션으로 계약에 의한 설계를 구현할 수 있다.

 

리스코프 치환 원칙은 계약에 의한 설계 원칙에서 정의한 계약 규칙과 가변성 규칙을 준수한다는 의미다. [571p]

 

계약 규칙 [547p]

  • 서브 타입은 더 강력한 사전 조건을 정의할 수 없다.
  • 서브 타입은 더 약한 사후 조건을 정의할 수 없다.
  • 슈퍼 타입의 불변성은 서브 타입에서도 반드시 지킨다.

 

자식 클래스가 계약 위반 코드를 작성하는 것을 막는 방법은 모든 인스턴스 변수의 가시성을 private 으로 만드는 것이다. [557p]

계약 규칙에서의 사전조건, 사후조건, 불변식 [540p]

1. 사전조건

  • 메소드가 호출 되기위해 만족해야하는 조건
  • 사전 조건이 만족되지 않으면 메서드가 실행되서는 안된다.
  • 사전 조건을 지키는 것은 클라이언트의 의무다.
  • (매개변수는 null 값이 오지 않는다.)

2. 사후조건

  • 메소드가 완료된 후 지켜야할 조건
  • 사후 조건을 지키는 것은 서버의 의무다.
  • (메소드는 null 을 반환하지 않는다.)

3. 불변식

  • 생성자 실행 후, 메소드가 실행 전, 실행 후 항상 보장되는 식
  • 메소드 실행하는 도중에는 만족시키지 않아도 무방하다. [556p]
  • (멤버 변수 a는 메소드 실행 전, 후라도 null 이 되질 않는다.)

 

 

가변성 규칙 [547p]

  • 서브 타입의 메소드 파라미터는 반공변성을 가진다.
  • 서브 타입의 리턴 타입은 공변성을 가진다.
  • 서브 타입은 슈퍼 타입이 발생시키는 예외와 다른 예외를 발생시키지 않는다.

 

공변성, 반공변성, 무공변성 [561p]

  • 공변성 :서브 타입이 슈퍼 타입 대신 사용될 수 있다.
  • 반공변성 : 슈퍼 타입이 서브 타입 대신 사용될 수 있다.
  • 무공변성 : 슈퍼 타입과 서브 타입이 아무런 관계도 없다. 

 

자바는 리턴 타입 공변성를 지원한다.

자바는 리턴 타입 반공변성을 지원하지 않는다.

자바는 파라미터 타입 공변성을 지원하지 않는다.

자바는 파라미터 타입 반공변성을 지원하지 않는다.

 

리턴 타입 공변성 : 자식 클래스가 메소드 오버라이딩 할 때 부모 클래스에서 선언한 반환 타입을 서브타입으로 지정할 수 있다. [565p]

파라미터 타입 반공변성 : 자식 클래스가 메소드 오버라이딩 할 때 부모 클래스에서 선언한 파라미터 타입을 슈퍼 타입으로 지정할 수 있다. [569p]

 

람다 표현식은 서브타입 메소드가 슈퍼 타입 메소드를 대체할 수 있다. [571p]

 

 

 

부록B 타입 계층의 구현

타입 계층이란 동일한 메시지에 대한 행동 호환성을 전제로한다. [573p]

클래스 상속을 사용하지 않고도 타입 계층을 구현할 수 있다.

인터페이스를 이용해 타입을 정의하고 클래스를 이용해 객체를 구현하라.  [580p]

가급적 추상 클래스를 상속 받거나 인터페이스를 구현하는 방법을 사용하라. [576p]

 

클래스

  • 객체의 내부상태와 오퍼레이션 구현 방법을 정의한다. [581p]
  • 타입에 속하는 객체들을 구현하기 위한 구현 메커니즘이다. [582p]

타입

  • 객체의 오퍼레이션 집합을 정의한다. [581p]
  • 동일한 퍼블릭 인터페이스를 가진 객체들의 범주다. [582p]

클래스와 타입을 구분하는 것은 중요하다.

클래스가 아니라 타입에 집중하라.

중요한 것은 객체가 외부에 제공하는 행동, 즉 타입을 중심으로 객체들의 계층을 설계하는 것이다.

구현을 공유하면서 결합도로 인한 부작용을 피하는 방법이 있는데, 바로 추상 클래스를 이용하는 것이다.

 

추상 클래스에서 구현한 메소드가 추상 메소드를 사용하고 자식 클래스에서 추상 메소드를 구현하는 방식은 좋은 설계다.

이 역시 또 다른 좋은 의존성 역전 원칙을 지킨 사례다.

 

설계가 상속 계층에 얽매이지 않는 타입 계층을 요구하면 인터페이스로 타입을 정의하라.

추상 클래스로 기본 구현을 제공해서 중복 코드를 없애라.

하지만 이런 복잡성이 필요하지 않다면 타입을 정의하기 위해서 둘 중 하나만 사용하라.[587p]

 

어떤 새가 오리처럼 걷고 오리처럼 헤엄치며 오리처럼 꽥꽥 소리를 낸다면 나는 이 새를 오리라고 부를 것이다. - 제임스 윗콤 릴리

덕 테스트(= 덕 타이핑) : 어떤 대상의 행동이 오리와 같다면 그것을 오리라는 타입으로 취급해도 무방하다. [588p]

덕 타이핑은 클래스나 인터페이스에 대한 의존성을 메시지에 대한 의존성으로 대체한다.[591p]

덕 타이핑을 사용하면 유연성을 얻는 대신 코드의 안전성을 약화시킬 수 있다. [593p]

 

자바에서는 구현을 포함하는 인터페이스를 정의하기 위해 정적 메소드를 사용하는 법과 디폴트 메소드를 사용하는 법을 제공한다. [600p]

자바에서는 믹스인을 구현하기 위해 디폴트 메소드를 사용할 수 있다.

자바 8의 디폴트 메소드는 인터페이스에 메소드의 기본 구현을 추가하는 것을 허용한다. [597p]

단 디폴트 메소드를 사용하는 경우 디폴트 메소드에서 사용하는 메소드는 public 메소드가 되어야한다. 

이는 외부에 노출할 피룡가 없는 불필요한 퍼블릭 인터페이스를 만드는 결과를 내고 캡슐화를 약화시킨다. [598p]

디폴트 메소드는 인터페이스를 추상 클래스의 역할을 대체하기 위해서 만들어진게 아니다. 그러므로 한계가 명확하다. 

리스코프 치환 원칙을 만족시키지 않는다면 올바른 타입 계층을 구현한 것이 아니다.[600p]

 

 

 

부록 C 동적인 협력, 정적인 코드

객체는 동적이고 프로그램은 정적이다.

프로그래머는 객체 지향 프로그램을 위해 두가지 모델을 마음속에 그려야한다.

  1. 동적 모델 : 객체와 협력
  2. 정적 모델 : 타입과 관계 [601p]

정적 모델보다 동적 모델에의해 설계는 주도 되어야한다.

정적 모델을 설계하는 이유는 단지 행동과 변경을 적절하게 수용할 수 있는 코드 구조를 찾는 것이어야 한다. [604]

 

수정이 용이한 코드란 응집도가 높고 결합도가 낮으며 단순해서 이해하기 쉬운 코드다.

유연한 코드란 동일한 코드를 이용해 다양한 컨텍스트에서 동작 가능한 협력을 만들 수 있는 코드다. [602p]

 

도메인 모델을 작성하는 것은 목표가 아니라 출발점이다.

도메인 안의 개념이 제공하는 틀에 맞춰서 소프트웨어를 구축하기 시작하면 불행이 시작된다.

코드의 구조를 이끄는 것은 도메인 안에 정립된 개념의 분류 체계가 아니라 객체들의 협력이다. [606p]

분석 모델, 설계 모델, 구현 모델 이런 구분이 있긴한데 이를 명확히 구분하는 것은 오히려 소프트웨어 품질에 악영향을 미친다. 

객체 지향 패러다임의 가장 큰 장점 중 하나는 전체 개발 주기동안 동일한 설계 기법과 모델링 방법을 사용할 수 있다는 것이다. [614p]

분석과 설계가 별개의 활동이라는 생각을 버려라. 

모든 단계에 걸쳐 행동과 변경에 초점을 맞춰라. [615p]

 

 

 

자바에서의 공변성 & 반공변성

---

interface Message{
    public String print();
}

class PostItMessage implements Message{
    private String message;

    @Override
    public String print() {
        return message;
    }
}

---

interface Super{
    Message createNewMessage();
    PostItMessage createNewPostItMessage();
    void printMessage(Message message);
    void printPostItMessage(PostItMessage message);
}

class Sub extends Super{
    // 오버라이딩 성공
    // 리턴 타입 공변성을 지원한다.
    @Override
    public PostItMessage createNewMessage() {
        return new PostItMessage();
    }

    // 오버라이딩 실패
    // 리턴 타입 반공변성을 지원하지 않는다.
    @Override
    public Message createNewPostItMessage() {
        return new PostItMessage();
    }

    // 오버라이딩 실패
    // 파라미터 공변성을 지원하지 않는다.
    @Override
    public void PostItMessage(PostItMessage postItMessage){
        System.out.println(postItMessage.print());
    }

    // 오버라이딩 실패
    // 파라미터 반공변성을 지원하지 않는다.
    @Override
    public void printPostItMessage(Message message){
        System.out.println(message.print());
    }
}

사설) 무조건 책을 사서 예제와 함께 보시는걸 추천드립니다.

'[공부] 독서 > 오브젝트' 카테고리의 다른 글

오브젝트 13 ~ 15  (0) 2020.03.19
오브젝트 09 ~ 12  (0) 2020.03.18
오브젝트 05 ~ 08  (0) 2020.03.16
오브젝트 01 ~ 04  (0) 2020.03.15