SOLID 객체지향 5대 원칙

jj J·2023년 1월 11일
0

JAVA

목록 보기
15/15

SOLID 객체지향 5대원칙에 대해 한번 정리해보고자 한다.

1. SRP, 단일책임의 원칙(Single Responsibility Principle)

  • 작성된 클래스는 하나의 기능만 가지며, 클래스가 제공하는 모든 서비스는 그 하나의 책임을 수행하는데 집중되어 있어야 한다는 원칙
  • 어떤 변화에 의해 클래스를 변경해야하는 이유는 오직 하나뿐이어야 함
  • SRP 원리를 적용하면 무엇보다도 책임 영역이 확실해지기 때문에 한 책임의 변경에서 다른 책임의 변경으로의 연쇄작용에서 자유로울 수 있다.
  • 책임을 적적히 분배함으로써 코드의 가독성 향상, 유지보수 용이라는 이점까지 누릴 수 있다.
  • 적용방법
    • 혼재된 여러 책임을 각각의 개별 클래스로 분할하여 클래스 당 하나의 책임만을 맡도록 함
    • 관건은 책임만 분리하는 것이 아니라, 분리된 두 클래스 간 관계의 복잡도를 줄이도록 설계함
    • 예를 들어 각각의 클래스들이 유사한 책임을 중복으로 갖고 있다면 부모 클래스를 사용해 각 클래스들의 중복되는 책임을 부모에게 위임하고 다른 책임들을 각자 정의할 수 있다.
    • 즉, 산발적으로 여러 곳에 분포된 책임들을 한 곳에 모으면서 설계를 깨끗하게 함

2. OCP, 개방폐쇄의 원칙(Open Close Principle)

  • 확장에는 열려있고, 변경에는 닫혀있어야 한다는 원리
  • 요구사항의 변경이나 추가사항이 발생하더라도, 기존 구성요소는 수정이 일어나지 말아야 하며, 기존 구성요소를 쉽게 확장해서 재사용할 수 있어야 함
  • 이를 가능케하는 중요 메커니즘은 추상화와 다형성
  • 적용 방법
    • 변경(확장)될 것과 변하지 않을 것을 구분
    • 이 두 모듈이 만나는 지점에 인터페이스를 정의
    • 구현에 의존하기보다 정의한 인터페이스에 의존하도록 코드를 작성
  • 추상화란 다른 모든 종류의 객체로부터 식별될 수 있는 객체의 본질적인 특징

3. LSP 리스코브 치환 법칙(The Liskov Substitution Principle)

  • 서브 타입은 언제나 기반 타입과 호환될 수 있어야 한다.
  • 서브 타입은 기반 타입이 약속한 규약(public 인터페이스, 예외 등)을 지켜야함
  • 다형성과 확장성을 극대화하려면 서브 클래스를 사용하는 것 보다는 상위 클래스(인터페이스)를 사용하는 것이 더 좋다.
  • 일반적으로 선언은 기반 클래스, 생성은 서브 클래스로 대입하는 방법을 사용함
  • 생성 시점에서 구체 클래스를 노출 시키기 꺼려질 경우 생성 부분을 Abstract Factory 등의 패턴을 사용해 유연성을 높일 수 있음
  • 상속을 통한 재사용은 기반 클래스와 서브 클래스 사이에 is - a 관계가 있을 경우로만 제한되야함
  • 그외엔 합성을 이용한 재사용을 해야함. 상속은 다형성과 따로 생각할 수 없음
  • 결국 이 구조는 다형성을 통한 확장 원리인 OCP를 제공하게 되고, LSP는 OCP를 구성하는 구조가 됨
  • 적용 방법
    • 만약 두 개체가 같은 일을 한다면 둘을 하나의 클래스로 표현하고 이들을 구분할 수 있는 필드를 둠
    • 똑같은 연산을 제공하지만, 이들을 약간씩 다르게 한다면 공통의 인터페이스를 만들고 둘이 이를 구현(인터페이스 상속)
    • 공통된 연산이 없다면 완전 별개인 2개의 클래스를 만듬
    • 두 개체가 하는 일에 추가적으로 무언가를 더 한다면 구현 상속을 사용함

4. ISP, 인터페이스 분리의 원칙 (Interface Segregation Principle)

  • 한 클래스는 자신이 사용하지 않는 인터페이스는 구현하지 말아야한다.
  • 어떤 클래스가 다른 클래스에 종속될 때는 가능한 최소한의 인터페이스만을 사용해야함
  • 하나의 일반적인 인터페이스보다는, 여러 개의 구체적인 인터페이스가 낫다
  • 만약 어떤 클래스를 이용하는 클라이언트가 여러 개고, 이들이 해당 클래스의 특정 부분집합만을 이용한다면, 이들을 따로 인터페이스로 빼내어 클라이언트가 기대하는 메시지만을 전달할 수 있도록 함.
  • 적용 방법
    • 클래스 인터페이스를 통한 분리
      • 클래스의 상속을 이용해 인터페이스를 나눌 수 있음
      • 이 구조는 클라이언트에게 변화를 주지 않을 뿐 아니라, 인터페이스를 분리하는 효과를 가짐
      • 하지만, 상속을 이용한 확장은 상속받는 클래스의 성격을 디자인 시점에 규정해버리기 때문에, 인터페이스를 상속 받는 순간 인터페이스에 예속되어 제공하는 서비스의 성격이 제한됨
    • 객체 인터페이스를 통한 분리
      • 위임을 이용해 인터페이스를 나눌 수 있음
        • 위임이란, 특정 일의 책임을 다른 클래스나 메서드에 맡기는 것
        • 만약 다른 클래스의 기능을 사용해야하지만, 그 기능을 변경하고 싶지 않다면 상속대신 위임을 사용

5. DIP, 의존성 역전의 원칙(Dependency Inversion Principle)

  • 저수준 모듈의 변경으로 인해 고수준 모듈의 변경을 요구하는 역전이 일어나면 안된다는 원칙
  • DIP의 키워드는 IOC, Hook, 확장성이다. 이 세가지 요소가 조합되어 복잡한 컴포넌트들의 관계를 단순화하고 컴포넌트 간의 커뮤니케이션을 효율적이게 함
  • 적용 방법
    • 잘 구조화된 객체 지향 아키텍처들은 각 레이어마다 잘 정의되고 통제되는 인터페이스를 통한 긴밀한 서비스들의 집합을 제공하는 레이어들로 구성되어 있다.
    • 이것은 단순히 레이어를 통한 구조화 뿐만 아니라 Transitive Dependency가 발생했을 때 상위 레벨의 레이어가 하위 레벨의 레이어를 바로 의존하는 것이 아니라, 이 둘 사이 존재하는 추상 레벨을 통해 의존해야 할 것을 말하고 있음
    • 이를 통해, 상위 모듈은 하위 모듈로의 의존성에서 벗어나 그 자체로 재사용되고 확장성도 보장받을 수 있음

출처 : https://www.nextree.co.kr/p6960/

profile
매일 발전

0개의 댓글