SOLID 원칙

Jaeuk Oh·2021년 8월 7일
0

Java

목록 보기
4/6
post-thumbnail
  1. SOLID 원칙이란?
  • Robert Martin이 주창한 다섯가지 객체 설계 원칙을 지칭한다.

    • 소프트웨어 작업에서 개발자가 소스 코드를 읽기 쉽고 확장하기 쉽게 될 때까지 소프트웨어 소스 코드를 리팩터링하여 오류를 제거하기 위해 적용할 수 있는 지침이다

  • "Uncle Bob"이라고 불리고, 베스트셀러 '클린코드' 저자이기도 하다




  1. SRP(Single Responsiblity Principle, 단일 책임 원칙)
  • 모든 클래스는 단 하나의 책임만을 가지도록 설계해야한다

    • 클래스에 책임을 할당할 때, 당연히 그 책임을 수행해야하는 클래스에게 할당해야 한다
    • 즉 클래스가 변경되어야하는 이유가 무조건 하나만 되도록 설계해야 한다

  • SRP는 미래의 예측하지 못한 새로운 요구사항이나 변경에 대해서 가능한 영향을 받는 부분을 줄이는 것이다


  • SRP 관련 UML


  • 문제

    • 만약 한 클래스가 할 일을 여러 클래스가 나누어서 수행한다면 어떻게 될까?
    • 이런 경우에는 산탄총 수술(Shotgun Surgery) 현상이 발생한다
    • 즉 기능 하나를 고치려고 하나의 클래스를 수정하는게 아니라 다수의 클래스를 수정해야하는 파국이 올 수도 있다



  1. OCP(Open-Closed Principle, 개방-폐쇄 원칙)
  • 기존의 코드를 변경하지 않으면서 새로운 기능을 추가할 수 있도록 설계하는 원칙이다.


  • OCP는 단위테스트에서 중요한 역할을 한다

    • 만약 테스트 대상 클래스가 OCP를 만족하도록 설계하면 테스트를 수행하는 경우에는 테스트 환경을 제공하고, 실제 동작이 필요한 경우에는 실제 외부환경으로 대치하는 설계가 가능하다

  • OCP 관련 UML




  1. LSP(Liskov Substitution Principle, 리스코프 치환 원칙)
  • 일반화 관계는 상위 클래스(수퍼 클래스)가 제공하는 오퍼레이션과 하위 클래스(파생 클래스)에서 제공하는 오퍼레이션 간에는 행위적으로 일관성이 있어야한다는 원칙이다

    • 음식(수퍼 클래스)에 관한 서적에서 음식 대신 음식의 한 종류인 피자(파생 클래스)로 대체해도 서적의 의미는 바뀌지 않는다고 생각하면 편하다 (PIZZA 조아!)
    • Liskov 교수가 1987년에 제안한 설계원칙이며, 5가지 SOLID 원칙중에서 가장 이해하기 힘든 원칙이다

  • LSP 관련 UML

    • 수정중

  • 문제

    • 그렇다면 어떻게 해야 상위, 하위 클래스 간에 일관성이 있다고 생각할까?
    • 수퍼 클래스 오퍼레이션의 선조건을 PRE_SUPER, 후조건을 POST_SUPER 라고 하자
    • 파생 클래스 오퍼레이션의 선조건을 PRE_SUB, 후조건을 POST_SUB 라고 하자
    • 이 두 가지 조건을 만족하면 수퍼, 파생 클래스 간에 일관성이 있다고 한다
      • PRE_SUPER -> PRE_SUB
      • POST_SUB -> POST_SUPER

  • 만약에 수퍼 클래스와 파생 클래스 간에 재정의된 오퍼레이션이 없다면 LSP를 만족하는가?

    • 당연히 만족한다, LSP를 만족시키는 다양한 방법 중에 하나가 수퍼 클래스의 메소드를 재정의하지 않는 것
    • 만약 파생 클래스가 수퍼 클래스의 책임을 무시하거나 재정의하지 않고 확장만을 수행한다면 LSP를 만족할 수 있다
    • 추상과 구상의 관계가 잘 되어있다면 위배할 수 없는 원칙이다



  1. ISP(Interface Segregation Principle, 인터페이스 분리 원칙)
  • ISP는 클라이언트가 자신이 이용하지 않는 기능(메소드)에 영향받지 않아야 한다는 원칙이다.

    • 클라이언트 관점에서 바라보는 객체지향 설계 원칙이다.

    • 자신이 이용하지 않는 메소드에 의존하면 안 된다!


  • ISP를 따라 클래스를 설계할 때, 클래스는 자신이 사용하지 않는 인터페이스는 구현하지 말아야한다

    • 즉 어떤 클래스가 다른 클래스에 의존할 때, 가능한 최소한의 인터페이스만을 사용해서 구현해야한다



  1. DIP(Dependency Inversion Principle, 의존성 역전 법칙)
  • 의존 관계를 맺을 때, 변화하기 쉬운 것 보다 변화가 거의 없는 것에 의존하라는 원칙

    • 즉, 의존 관계 형성 시 추상적인 인터페이스나 클래스 등에 의존하라

  • 구체적인 클래스는 추상 클래스나 인터페이스에 의존하고, 그 반대는 안 되는 설계


  • DIP 설계는 의존성 주입(Dependency Injection)의 기반이 된다 (Spring 생각이 난다면 쉽다)

    • 의존성 주입으로 외부 협력 객체를 대상 객체의 인스턴스 변수에 주입하여 대상 객체에 최대한 영향을 주지 않고 외부에서 대상 객체의 의존 객체를 바꿀 수 있다
    • 마치, 학교에서 학생(대상 객체)에게 과제 양식(외부 협력 객체)을 주면 과제에 대한 학생의 답은 변하지 않지만 과제 제출에 대한 규칙을 바꾼 것(외부에서 대상 객체의 의존 객체를 바꿀 수 있다).

  • DIP 관련 UML

    • 반려동물에 따라 민감한 설계(DIP X) 변화
    • 반려동물 변화에 따라 민감하지 않은 설계(DIP ㅇ)



  1. 참조
    • 오픈소스 소프트웨어로 실습하는 소프트웨어공학, 정인상, 생능출판사, 2017

0개의 댓글

관련 채용 정보