ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 오브젝트 - 계약에 의한 설계
    Study 2024. 1. 24. 21:08
    • 6장에서 설명한 메시지와 인터페이스 원칙에 따라 의도를 드러내도록 인터페이스를 다듬고 명령과 쿼리를 분리했다고 하더라도 명령으로 인해 발생하는 부수 효과를 명확하게 표현하는 데는 한계가 있다
    • 여기서 말하고 싶은 것은 인터페이스만으로는 객체의 행동에 관한 다양한 관점을 전달하기 어렵다는 것이다
    • 우리에게 필요한 것은 명령에 부수 효과를 쉽고 명확하게 표현 할 수 있는 커뮤니케이션 수단이다. 이럴 때 필요한 것이 계약에 의한 설계이다
    • 계약에 의한 설계를 사용하면 협력에 필요한 다양한 제약과 부수 효과를 명시적으로 정의하고 문서와 할 수 있다
    • 클라이언트 개발자는 오퍼레이션의 구현을 살펴 보지 않더라도 객체 사용 법을 쉽게 이해할 수 있다
    • 계약은 실행 가능하기 때문에 구현 의 동기화돼 있는지 여부를 런타임에 검증할 수 있다

    01 협력과 계약

    부수효과를 명시적으로

    • 객체지향 핵심은 협력 안에서 객체들이 수행하는 행동이다
    • 인터페이스는 개체가 수신 할 수 있는 메시지는 정의할 수 있지만 객체 사이에 의사소통 방식은 명확하게 정리할 수 없다

    계약

    • 계약에 세부적인 내용은 상황에 따라 다르겠지만 일반적으로 다음과 같은 특성을 가진다
      • 각 계약 당사자는 계약으로부터 이익을 기대하고 이익을 위해 의무를 이행한다
      • 각 계약 당사자의 이과 의무는 계약서에 문서화된다
    • 여기서 눈여겨볼 부분은 한쪽에 음모가 반대쪽에 권리가 된다는 것이다
      https://wiki.python.org/moin/PythonDecoratorLibrary#Pre-.2FPost-Conditions

    02 계약에 의한 설계(Design By Contract, DBC)

    • 버트란드 마이어는 Eiffel 언어를 만들면서 사람들 사이의 계약의 차단 한 계약에 의한 설계 기법을 고안했다.
    • 계약에 의한 설계 개념은 "인터페이스에 대해 프로그램 밍 하라"는 원칙을 확장하는 것이다
    • 계약에 의한 설계를 이용하면 오퍼레이션의 시그니처를 구성하는 다양한 요소들을 이용해 협력에 참여하는 객체들이 지켜야 하는 제약 조건을 명시할 수 있다
    • 계약에 의한 설계를 구성하는 3가지 요소는 사전 조건, 사후 조건, 불변식이라고 부른다
      • 사전 조건(precondition): 메서드가 호출되기 위해 만족돼야 하는 조건. 사전 조건이 만족되지 않을 경우 메서드가 실행돼서는 안 된다. 사전 조건을 만족시키는 것은 클라이언트의 의무다.
      • 사후 조건(postcondition): 메소드가 실행된 후에 클라이언트에게 보장해야 하는 조건. 사전 조건을 만족시켰는데도 사후 조건을 만족시키지 못한 경우에는 클라이언트에게 예외를 던져야 한다. 사후 조건을 만족시키는 것은 서버의 의무이다.
      • 불변식(invariant): 항상 참이라고 보장되는 서버의 조건. 메서드가 실행되는 도중에 에는 불변 식을 만족시키지 못할 수 있지만 메서드를 실행하기 전이나 종료된 후에는 불변 식은 항상 참이어야 한다.

    사전조건

    • 사전 조건이란 메소드가 정상적으로 실행되기 위해 만족해야 하는 조건이다.
    • 사전 조건은 메서드의 전달 된 인자의 정합성을 체크하기 위해 사용된다.
    • 클라이언트가 사전 조건을 만족시키지 못할 경우 최대한 빨리 실패해서 클라이언트에게 버그가 있다는 사실을 알린다

    사후조건

    • 사후 조건은 메서드 실행 결과가 올바른지 검사하고 실행 후의 객체가 유효한 상태로 남아 있는지를 검증한다.
    • 일반적으로 사후조건은 다음과 같은 3가지 용도로 사용된다.
      • 인스턴스 변수의 상태가 올바른지를 서술
      • 메서드의 전달 된 파라미터 값이 올바르게 변경했는지를 서술
      • 변환 값이 올바른지를 서술
    • 다음과 같은 2가지 이유로 사전조건보다 사후 조건을 정리하는 것이 어려울 수 있다
      • 한 메서드 안에서 return 문이 여러 번 나올 경우
      • 실행 전과 실행의 값을 비교해야 하는 경우

    불변식

    • 사전조건과 사후조건은 각 메서드마다 달라지는데 반에 불변식은 인스턴스 생명 주기 전반에 걸쳐 지켜야 하는 규칙을 명세한다
    • 일반적으로 불변식은 객체의 내부 상태와 관련이 있다
    • 불변식은 다음과 같은 2가지 특성을 가진다
      • 불변식은 클래스의 모든 인스턴스가 생성된 후에 만족돼야 한다 이것은 클래스의 정의된 모든 생성자는 불변식을 준수해야 한다는 것을 의미한다.
      • 불변식은 클라이언트의 의해 호출 가능한 모든 메서드의 준수돼야 한다 메서드가 실행되는 중에는 객체의 상태가 불안정한 상태로 빠질 수 있기 때문에 불변 식을 만족 할 필요는 없지만 메서드 실행 전과 메서드 종료 후에는 항상 불변 식을 만족하는 상태가 유지돼야 한다.
    • 불변식은 클래스의 모든 메서드의 사전조건과 사후 조건에 추가되는 공통의 조건으로 생각할 수 있다
    • 불변식은 메서드가 실행 되기 전에 사전조건과 함께 실행되며 메서드가 실행되는 사후조건과 함께 실행된다.
      • 만약 불변식을 수작업으로 작성한다면 모든 메서드의 동일한 불변식을 추가해야 할 것이다
    • 불변식은 생성자 실행 후, 메서드 실행 전, 메소드 실행 후에 호출돼야 한다는 점을 기억하라.
      만약 직접 불변식을 코딩하고 관리 해야 한다면 모든 생성자의 마지막 위치와 메서드 시작 지점, 메서드 종료 지점에 불변식을 호출하도록 일일이 코드를 작성해야 한다

    03 계약에 의한 설계와 서브타이핑

    • 계약에 의한 설계는 클라이언트가 만족시켜야 하는 사전조건과 클라이언트의 관점에서 서버가 만족시켜야 하는 사후조건을 기술한다
    • 계약의 의한 설계와 리스코프 치환 원칙이 만나는 지점이 바로 이것이다
    • 리스코프 치환 원칙은 슈퍼타입의 인스턴스와 협력하는 클라이언트의 관점에서 서브타입의 인스턴스가 슈퍼타입을 대체하더라도 협력에 지장이 없어야 한다는 것을 의미한다. 따라서 다음과 같이 정리할 수 있다.
      • 서브타입이 리스코프 치환 원칙을 만족시키기 위해서는 클라이언트와 슈퍼타입 간에 체결된 계약을 준수해야 한다
    • 리스코프 치환 원칙의 규칙을 2가지 종류로 세분화할 수 있다
      • 첫 번째 규칙은 협력에 참여하는 객체에 대한 기대를 표현하는 계약 규칙
      • 두 번째 규칙은 교체 가능한 타입과 관련된 가변성 규칙이다
    • 계약 규칙(contract rules)은 슈퍼타입과 서브타입 사이의 사전조건, 사후조건, 불변식에 대해 서술할 수 있는 제약에 관한 규칙이다
      • 서브타입에 더 강력한 사전조건을 정의할 수 없다
      • 서브타입에 더 완화된 사후조건을 정의할 수 없다
      • 슈퍼타입의 불변식은 서브타입에서도 반드시 유지돼야 한다
    • 가변성 규칙(variance rules)은 파라미터와 리턴 타입의 변형과 관련된 규칙이다
      • 서브타입의 메서드 파라미터는 반공변성을 가져야 한다
      • 서브타입의 리턴 타입은 공변성을 가져야 한다
      • 서브타입은 슈퍼타입이 발생시키는 예외와 다른 타입의 예외를 발생시켜서는 안 된다
    • 대부분 객체지향 언어에서 공변성과 반공연성이 중요해지는 곳은 상속이 제네릭 프로그래밍과 만나는 지점이다
    반응형

    댓글

Designed by Tistory.