본문 바로가기

책/Python Clean code

계약에 의한 디자인

반응형

 

클린 콛흐

 

소프트웨어는 사용자가 만들어서 직접 사용하기도 하지만
다른 레이어 나 컴포넌트 에서 호출하는 경우도 있다 이런 경우 이들 간 교류를 어떻게 해야하는지 고민해보자

 

 

 

컴포넌트는 기능을 숨겨 캡슐화 하고 함수를 사용할 클라이언트에게는 API 를 노출해야한다

컴포넌트의 함수, 클래스. 메서드는 특별한 유의사항에 따라 동작해야 하며, 그렇지 않을 경우 코드가 깨지게 된다

반대로 코드를 호출하는 클라이언트는 특정 형태의 응답이나 실패를 기대하고
해당 형태와 다른 응답을 받는 경우
함수 호출에 실패하게 되고 부가적인 결함을 생기는 경우도 있음
 

 

 

물론 API를 디자인할 때 예상되는 입출력과 부작용을 문서화해야함
그러나 문서화가 런타임 시의 소프트웨어의 동작까지 강제할 수는 없다

이렇게 코드가 정상적으로 동작하기 위해 필요한 것과

클라이언트가 반환 받게 될 형태는 모두 디자인에 포함이 되어야함 여기서 계약(contract)이라는 개념이 생김

 

 

Design by Contract

  • 관계자가 기대하는바를 암묵적으로 코드에 삽입하는대신 양측이 동의하는 계약을 먼저 한 다음
    • 계약을 어겼을 경우 명시적으로 왜 계속할 수 없는지 예외를 발생시키라는뜻

*여기서 말하는 계약은 소프트웨어 컴포넌트 간의 통신 중에 반드시 지켜져야 할 몇 가지 규칙을 강제하는것

계약은 주로 사전 조건과 사후조건을 명시하지만 때로는 불변식 과 부작용을 기술함

사전조건

  • 코드가 실행되기 전에 체크해야 하는 것들
  • 함수가 진행되기 전에 처리되어야 하는 모든 조건을 체크
    • ex) database, file, 이전에 호출된 다른 메서드 검사 등
    • 이러한 작업은 호출자에게 부과된 임무사후조건
  • 사전조건과 반대로 여기서는 함수 반환값의 유효성 검사 수행
  • 사후 조건 검증은 호출자가 이 컴포넌트에서 기대한 것을 제대로 받았는지 확인하기 위해 수행

불변식

  • 떄로는 함수의 docstring에 불변식에 대해 문서화하는 것이 좋다
    • 불변식은 함수가 실행되는 동안에 일정하게 유지되는 것으로
    • 함수의 로직에 문제가 없는지 확인하기 위한것부작용
  • 선택적으로 코드의 부작용을 주석으로 써놓음

이상적으로 이 모든 것들을 소프트 웨어 컴포넌트 예약서의 일부로 문서화를 해야하지만
처음 2개인 사전조건과 사후조건만 저수준 레벨에서 강제함

 

이렇게 계약에 의한 디자인을 하는 이유가 오류를 쉽게 찾을 수 있어서 하는것

  • 사전조건 또는 사후조건 검증에 실패할 경우 오류를 쉽게 찾아서 수정할 수 있음
  • 더 중요한 것은 잘못된 가정 하에 코드의 핵심 부분이 실행되는 것을 방지하기 위해서
    • 이렇게 하면 어떤 부분에 실패 했다는 에러를 발생시키는데서 그치는 것이 아닌
      • 책임의 한계를 명확히 하는데 도움이 됨
  • 사전 조건은 클라이언트와 관련이 있음
    • 사전에 약속한 조건을 준수해야함
    • 사전 조건은 런타임 중에 확인할 수 있는것이 포인트
    • 사전 조건에 맞지 않는다면 실행하지 말아야함 조건에 맞지 않는데 실행하는 것이 이치에 맞지 않음
  • 사후 조건은 컴포넌트와 관련이 있음
    • 컴포넌트는 클라이언트가 확인하고 강제할 수 있는 값을 보장해야함
  • 디자인 원칙을 구현하는 가장 좋은 방법은 메서드, 함수 ,클래스에 제어 메커니즘을 추가하고
    • 실패할 경우 RuntimeError or ValueError를 발생 시키는 것일 것이다
    • 올바른 예외 타입이 무엇인지는 application 특정에 따라 달라질 수 있다
    • 이러한 예는 너무 일반적인 예시여서 포괄적이고
문제를 정확히 특정하기 어려우면 사용자 정의 예외를 만드는 것 도 좋음
DRF Custom Exception, FastAPI Custom Exception

 

또한 코드를 가능한 한 격리된 상태로 유지하는 것이 좋다 

반응형