OOP - SOLID 원칙

이유석·2022년 1월 6일
0

OOP

목록 보기
3/3

객체 지향 설계 에는 SOLID라고 부르는 5가지 설계 원칙이 존재한다.
1. SRP - 단일 책임 원칙 : 한 클래스는 하나의 책임만 가져야 한다.
2. OCP - 개방/폐쇄 원칙 : 소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.
3. LSP - 리스코프 치환 원칙 : 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.
4. ISP - 인터페이스 분리 원칙 : 특정 클라이언트를 위한 인터페이스 여러개가 범용 인터페이스 하나보다 낫다.
5. DIP - 의존관계 역전 원칙 : 프로그래머는 추상화에 의존해야지, 구체화에 의존하면 안된다.

SRP(Single Responsibility) - 단일 책임 원칙

정의

  • 한 클래스는 하나의 책임만 가져야 한다.

  • 책임의 중요한 기준은 변경이다.
    변경이 있을 때 파급효과가 적으면, 단일 책임 원칙을 잘 따른 것.

  • 이는 객체지향 원리의 대전제 격인 OCP원리 뿐만 아니라, 다른 원리들을 적용하는 기초가 된다.

적용 방법

  • 여러 책임을 가지고 있는 경우
    혼재된 각 책임을 각각의 개별 클래스(Extract Class) 로 분할 → 클래스 당 하나의 책임만 맡도록 한다.
    핵심은 단순리 책임 만 분리하는 것이 아닌, 분리된 두 클래스간의 관계의 복잡도를 줄이도록 설계하는 것이다.

  • 산발적으로 여러 곳에 책임이 분산 된 경우
    해당 책임을 Move Field와 Move Method를 통해 특정 클래스로 모은다.
    (마땅한 클래스가 없으면 새로운 클래스를 만든다.) → 응집성 증가

효과

  • 책임 영역이 확실해 집으로 특정 책임 A의 변화가 책임 B의 변화로 이뤄지는 잘못된 연쇄작용에서 자유로워 질 수 있다.

  • 책임을 적절히 분배함으로써 코드의 가독성을 향상하고 유지보수를 용이하게 한다.

OCP(Open/Close Principle) - 개방/폐쇄 원칙

정의

  • 소프트웨어의 구성요소인 컴포넌트, 클래스, 모듈, 함수는 확장에는 열려있고 변경에는 닫혀있어야 한다.

  • 변경을 위한 비용을 최소화 하고, 확장을 위한 비용은 최대화 한다.
    즉, 요구사항의 변경에도 기존 구성요소는 수정이 일어나면 안되며, 단순한 확장을 통한 재사용이 가능해야 한다.

  • OCP를 가능하게 하는 주요 메커니즘은 추상화와 다형성.

적용 방법

  • 변경(확장)될 것 과 변치 않는 것을 엄격히 구분한다.
  • 이 두 모듈이 만나는 지점에 인터페이스를 정의 한다.
  • 구현에 의존하기보다 정의된 인터페이스에 의존하도록 코드를 작성한다.
  • 변경이 발생하는 부분을 추상화 하여 분리한다.

효과

  • 관리가능하고 재사용 가능한 코드를 만드는 기반으로써 객체 지향의 장점을 극대화 하는 중요한 원리 이다.

LSP(Liskov substitution principle) - 리스코프 치환 원칙

정의

  • 서브 클래스(자식)는 언제나 기반 클래스(조상)로 교체할 수 있어야 한다.
    즉, 서브 클래스는 기반 클래스가 약속한 규약(public 인터페이스, 메소드가 던지는 예외 등)을 지켜야 한다.

상속은 구현 상속(extends)이든, 인터페이스 상속(implements)이든 궁극적으로는 다형성을 통한 확장성 획득을 목표로 한다.
다형성과 확장성을 극대화 하기 위해서는 , 하위 클래스를 사용하는 것 보다는 상위 클래스(or 인터페이스)를 사용하는 것이 더 좋다.

적용 방법

  • 객체가 같은 일을 한다면, 둘을 하나의 클래스로 표현하고 구분 가능한 필드를 둔다.
    (Enum Type을 이용하는 것 처럼)
  • 같은 연산을 제공하나 약간씩 차이가 있다면 공통의 인터페이스를 만들고 각각 이를 구현한다.
    (인터페이스 상속)
  • 공통된 연산이 없다면, 완전 별개의 각각의 클래스를 만든다.
  • 두 객체가 하는 일에 추가적인 일이 있다면 구현 상속을 사용한다.

효과

  • 다형성을 통한 확장의 원리인 OCP를 제공하게 된다. 즉, LSP 는 OCP를 구성하는 구조가 된다.

ISP(Interface Segregation Principle) - 인터페이스 분리 원칙

정의

  • 어떤 클래스는 자신이 사용하지 않는 인터페이스는 구현하지 말아야 한다.
    즉, 종속 관계를 가질 때는, 최소한의 인터페이스만을 사용해야 한다.
  • 하나의 일반적인 인터페이스 보다, 여러개의 구체적인 인터페이스가 낫다. → 인터페이스 분리의 필요성
  • SRP : "클래스"의 단일 책임을 강조, ISP : "인터페이스"의 단일 책임을 강조

적용 방법

  • 클래스 인터페이스를 통한 분리
    클래스의 상속을 이용해 인터페이스를 분리한다.
    분리된 인터페이스를 여러개 상속받아 클라이언트에게 변화를 주지 않을 수 있다.

  • 객체 인터페이스를 통한 분리
    위임(Delegation)을 이용해 인터페이스를 나눌 수 있다.

    위임 : 특정 작업의 책임을 다른 클래스나 메소드에 맡기는 것으로, 만약 다른 클래스의 기능을 사용해야 하나 그 기능을 바꾸고 싶지 않다면 상속 대신 위임을 사용한다.

효과

  • 두 개 이상의 인터페이스가 공유하는 부분의 재사용을 극대화 한다.

  • 서로 다른 성격의 인터페이스를 명백히 분류한다.

DIP(Dependency Inversion Prinsiple) - 의존관계 역전 원칙

정의

  • 구조적 디자인에서 발생하던 하위 레벨 모듈의 변경이 상위 레벨 모듈의 변경을 요구하는 위계 관계를 끊는 의미의 역전이다.

  • 추상화(인터페이스)는 구체화(구현 클래스)에 의존해서는 안되고, 구체화는 추상화에 의존해야 한다.

적용 방법

  • 레이어링
    Transitive Dependency가 발생했을 때, 상위 레벨의 레이어가 하위 레벨의 레이어를 바로 의존하게 하는 것이 아니라, 이 둘 사이에 존재하는 추상레벨을 통해 의존 해야 한다.
    상위 레벨의 모듈을 하위 레벨의 모듈로의 의존성에서 벗어나 그 자체로 재사용되고 확장성도 보장 받을 수 있다.

    Transitive Dependency (전이 의존성) : 어떤 라이브러리를 의존성으로 추가하면, 그 라이브러리가 가지고 있는 의존성이 함께 딸려온다. 그렇게 딸려온 의존성들을 전이 의존성이라고 한다.
    재귀적으로 라이브러리가 라이브러리를 요구하게 되는 상황을 전이 의존성이라 한다.

효과

  • IOC, Hook Method, 확장성 이라는 핵심 요소가 조합되어, 복잡한 컴포넌트들의 관계를 단순화 하고 컴포넌트 간의 커뮤니케이션을 효율적이게 한다.

  • 복잡하고 지난한 컴포넌트 간의 커뮤니케이션 관계를 단순화 하기 위한 원칙

Hook Method : 슈퍼 클래스에서 디폴트 기능을 정의 or 내용을 비워두어서, 서브 클래스에서 선택적으로 오버라이드 할 수 있도록 만든 메서드.
서브 클래스에서는 Hook Method를 오버라이드하거나, 추상 메서드를 구현하는 방법을 이용해 기능의 일부를 확장한다.

profile
https://github.com/yuseogi0218

0개의 댓글