LSP:리스코프 치환 원칙

바바라 리스코프의 하위 타입(subtype) 정의

여기에서 필요한 것은 다음과 같은 치환(substitution) 원칙이다. S 타입의 객체 o1 각각에 대응하는 T 타입 객체 o2가 있고, T 타입을 이용해서 정의한 모든 프로그램 P에서 o2의 자리에 o1을 치환하더라도 P의 행위가 변하지 않는다면, S는 T의 하위 타입이다.

LSP 준수 예시 - 상속을 사용하도록 가이드라인하기

이미지 출처 : https://wedonttalknemore.tistory.com/16?category=967824

  • 이 설계가 LSP를 준수하는 이유
    • Billing 애플리케이션의 행위가 License 하위 타입 중 무엇을 사용하는지에 전혀 의존하지 않음.
    • 이들 하위 타입은 모두 License 타입을 치환할 수 있다.

LSP 위반 예시 - 정사각형/직사각형 문제

이미지 출처 : https://wedonttalknemore.tistory.com/16?category=967824

  • Square는 Rectangle의 하위 타입으로 적합하지 않다.

    • Rectangle의 높이와 너비는 서로 독립적으로 변경될 수 있는 반면, Square의 높이와 너비는 반드시 함께 변경되기 때문.

    • User는 대화하고 있는 상대가 Rectangle이라고 생각하므로 혼동이 생길 수 있다.

      Rectangle r = ...
      r.setW(5);
      r.setH(2);
      assert(r.area() == 10);
    • ... 코드에서 Square를 생성한다면 assert문은 실패하게 된다.

      • 정사각형의 길이는 같기 때문. (넓이가 25가 될수도 있고, 4가 될 수도 있다.)
  • 해결책

    • if 문 등을 이용해서 Rectangle이 실제로는 Square인지를 검사하는 메커니즘을 User에 추가한다. → User의 행위가 사용하는 타입에 의존하게 되므로 결국 타입을 서로 치환할 수 없게 된다.

LSP와 아키텍처

  • 객체지향 초창기에 LSP는 상속을 사용하도록 가이드하는 방법 정도로 간주되었음.
  • 시간이 지나면서 LSP는 인터페이스와 구현체에도 적용되는 더 광범위한 소프트웨어 설계 원칙으로 변모.
    • 인터페이스는 다양한 형태로 나타남.
      • 자바 - 인터페이스 하나와 이를 구현하는 여러 개의 클래스로 구성
      • 루비 - 동일한 메서드 시그니처를 공유하는 여러 개의 클래스로 구성
  • 아키텍처 관점에서 LSP를 이해하는 최선의 방법은 이 원칙을 어겼을 때 시스템 아키텍처에서 무슨 일이 일어나는지 관찰하는 것이다. (무슨 말일까..)

좋은 웹페이지 즐겨찾기