LSP: 리스코프 치환 원칙

  • 1988년 바바라 리스코프(Barbara Liskov)는 하위 타입(subtype)을 아래와 같이 정의
    • 필요한 것은 치환(substitution) 원칙
    • S 타입의 객체 o1, T 타입 객체 o2
    • T 타입을 이용해서 정의한 프로그램 P에서 o2에 o1을 치환하더라도 P의 행위가 변하지 않는다면, S는 T의 하위 타입

상속을 사용하도록 가이드하기

  • LicensePersonalLicenseBusinessLicense라는 하위 타입이 존재
  • 이 설계는 LSP를 준수
    • Billing 애플리테이션의 행위가 License하위 타입 중 무엇을 사용하는지에 전혀 의존하지 않기 때문에

정사각형/직사각형 문제

  • LSP를 위반하는 전형적인 문제로는 정사각형/직사각형 문제가 있음
    • SquareRectangle의 하위 타입으로 적합하지 않음
      • Rectangle은 높이와 너비가 독립적으로 변경될 수 있지만 Square는 함께 변경됨

LSP와 아키텍처

  • 객체 지향의 초창기에는 위 처럼 상속을 사용해서 가이드함
  • 시간이 지나면서 인퍼에이스와 구현체에도 적용되는 광범위한 소프트웨어 설계 원칙으로 변모함

LSP 위배 사례

  • 다양한 택시 파견 서비스를 통합하는 애플리케이션을 만들고 있다고 가정
  • 고객은 어느 택시업체인지 신경쓰지 않고 가장 적합한 택시를 찾음
  • 택시 파견 REST의 URI가 운전기사 데이터베이스에 저장되어있다고 가정
  • 시스템이 고객에게 알맞은 기사를 선택하면, 해당 기사의 레코드의 URI를 호출해 고객 위치로 파견
    • 레코드에는 taxi.com/driver/Bob으로 존재
    • 이를 purpecab.com/driver/Bob/pickupAddress/{address}/pickupTime/{time}/destination/{destination} 과 같이 구성해서 호출
    • 즉 모든 택시 업체들은 위와 같은 포맷을 준수해야함
    • 이때 새로운 업체(가장 큰 택시업체)가 들어왔는데 위 포맷을 준수하지않음
      • /destnation/dest로 사용
    • 조건문으로 업체를 보고 해당업체만 별도로 처리?
      • 회사도메인 하드코딩필요
      • 이해할 수 없는 온갖 종류의 에러 발생 여지를 만듬
    • 실력 있는 아키텍트는 이런식으로 구성하지 않음
  • 아키텍트는 버그로 부터 시스템을 격리해야함
  • URI를 키로 사용하는 설정용 데이터베이스 구성
URL Dispatch Format
new-taxi.com /pickupAddress/%s/pickupTime/%s/dest/%s
* /pickupAddress/%s/pickupTime/%s/destination/%s
  • 그 외 위 관련 로직에 복잡한 매커니즘을 추가 해야할 수 있음

결론

  • LSP는 아키텍처 수준까지 확장 가능, 반드시 확장해야함
  • 치환 가능성을 조금이라도 위배하면 시스템 아키텍처가 오염
    • 별도의 메커니즘을 추가해야 할 수 있음