코딩못하는사람

객체지향 설계 5원칙-SOLID 본문

스프링(Spring)/개념

객체지향 설계 5원칙-SOLID

공부절대안함 2021. 9. 17. 02:27

-SOLID란?

클린코드의 저자인 로버트 마틴이 객체지향 지향 프로그래밍 설계의 다섯가지 기본 원칙으로 제시한 것이다.

  1. SRP 단일 책임 원칙
  2. OCP 개방-폐쇄 원칙
  3. LSP 리스코프 치환 원칙
  4. ISP 인터페이스 분리 원칙
  5. DIP 의존관계 역전 원칙

응집도는 높이고 결합도는 낮추라는 원칙을 재정립한 것이다.

개발자들 마다 해석의 차이가 있다고 하지만, 객체지향을 이해하고 디자인 패턴 및 스프링을 이해하는데 큰 도움이 되는 SOLID를 나에게 맞는 예시를 들어 생각하며 정리하자.

 

SRP 단일 책임 원칙

"한 클래스는 하나의 책임만 가져야 한다,"

스프링으로 프로젝트를 만들때를 생각해보자.

우리는 주요 클래스들을 컨트롤러 단, 서비스 단, 레포지토리 단 으로 나눠서 개발을 한다.

이렇게 주요 기능별로 나눠서 개발해온 것도 단일 책임 원칙을 잘 지킨 부분이다.

에러가 발생했을때 어디서 나타난 것인지 확실히 알 수 있고, 그 부분만 고치면 되기 때문이다.

변경이 있을때 파급 효과가 적으면 단일 책임 원칙을 잘 따른 것이다.

 

개방-폐쇄 원칙

“소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.”

말이 어렵지만 객체지향의 특징인 '다형성'과 관련된 부분이다. 많이 예를 드는 자동차를 생각해보자.

대리운전 기사님이 자동차가 바뀐다고 운전을 못하게 되면 될까? 클라이언트(대리운전 기사님)에 변경이 필요하면 안된다 (변경에는 닫혀 있다).

하지만 자동차의 특성을 가지고 있다면 새로운 출시되는 차는 얼마든지 운전할 수 있다(확장에는 열려 있다)

JDBC도 좋은 예이다.

우리가 JDBC를 통해서 오라클을 사용하다가 MYSQL로 바꾸어야할때 DB설정파일 빼고 바꾸어야할게 있을까?

없다. 확장이 자유로운 것이다.자바 애플리케이션은 JDBC라는 인터페이스로 변화에 영향을 받지 않고 확장에 열려있게 해준다.

 

리스코프 치환 원칙

“프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.” 

객체지향의 상속에 대한 특징이 관련된 부분이다. 객체지향의 상속은 조직도나 계층도가 아닌 분류도가 되어야 한다.

하위 클래스는 상위 클래스의 한 종류이다.

구현 클래스는 인터페이스할 수 있어야 한다.

이 두줄을 잘 지키고 있다면 LSP를 잘 지킨다고 볼 수 있다.

ex) 아버지-아들(계층도) LSP X,

동물 - 펭귄(분류도) LSP O

인터페이스에 엑셀이라는 기능을 뒤로가도록 구현하면 LSP X


인터페이스 분리 원칙

“특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.”

자동차 인터페이스-> 운전 인터페이스, 정비 인터페이스로 분리

사용자 클라이언트-> 운전 클라이언트,정비사 클라이언트로 분리

이렇게 하면 어떤 장점이 있을까?

인터페이스 분리로 인해 각각의 인터페이스가 변해도 서로의 클라이언트에 영향을 주지 않게 되었다.

인터페이스가 명확해지고, 대체 가능성이 높아진다.

상위 클래스는 풍성할수록 좋고,인터페이스는 작을수록 좋다.


의존관계 역전 원칙

프로그래머는 “추상화에 의존해야지, 구체화에 의존하면 안된다.”

대리운전 기사가 특정 자동차인 소나타를 알고 있으면 될까? 안된다. 자동차(인터페이스)를 알아야지 특정 자동차(구현체)를 알면 안된다.

다시 말해 추상화에 의존해야지 구체화에 의존하면 안된다. 그래야 유지보수 및 확장이 용이하다.

 

추가적으로 SoC(관심사의 분리)를 생각하자.

관심이 같은 것 끼리는 하나 or 비슷한 객체로 모으고 관심이 다르다면 가능한 떨어져 서로 영향을 주지 않게 하자.

이러한 SoC의 특성을 잘 따라가다보면 ISP,SRP,OCP에 자연스럽게 도달하게 될 것이다.

 

 

마지막으로 OCP와 DIP는 밀접한 관계에 있다. 다음 코드를 보자

레포지토리가 바뀔때마다 클라이언트의 코드가 변경되어야 한다.(OCP 위반)

그 이유는? 추상적인것이 아닌 구체적인 것에 의존해 놨기 때문(DIP 위반)

 

하지만 당연히 바뀔때마다 클라이언트가 변경되어야 하는것 아닌가? 라는 생각이 들 수 있다.

하지만 우리에겐 스프링이 있다. 스프링은 다형성을 활용하면서 DIP,OCP를 위반하지 않도록

스프링 컨테이너,DI(Dependency Injection),IoC(Inversion of Control)를 통해 객체지향적인 코드를 짤 수 있도록 우리를 도와준다.

 

 

'스프링(Spring) > 개념' 카테고리의 다른 글

@AuthenticationPrincipal 어노테이션  (0) 2022.01.02
Filter와 Interceptor  (0) 2021.12.30
스프링과 스프링부트  (0) 2021.09.17
스프링이 무엇이고 왜 나왔을까?  (1) 2021.09.17
스프링 Bean,Singleton,Bean Scope  (0) 2021.03.06
Comments