SOLID란?
SOLID는 객체 지향 설계를 할 때 필요한 원칙을 의미하고
SRP(단일 책임 원칙), OCP(개방 폐쇄 원칙), LSP(리스코프 치환 원칙)
ISP(인터페이스 분리 원칙), DIP(의존 역전 원칙)
총 위의 5개로 구성되어 있는 원칙
SRP(단일 책임 원칙)
SRP는 쉽게 말해서 클래스를 역할과 책임에 따라 분리하는 것을 의미한다.
예를 들어 사육사라는 클래스가 있다고 가정하자
위처럼 사육사는 강아지에게 사료주는 일과 호랑이에게 고기를 주는 일, 곰에게 생선을 주는 일 총 3가지일을 맡고 있다.
근데 만약 강아지가 더 이상 동물원에 존재하지 않으면 사육사가 하는 일에서 사료주는 일을 할 대상이 사라지게 된다.
위의 코드는 이러한 점에서 SRP가 지켜지지 않았다.
그럼 SRP원칙을 지켜가면서 코드를 작성하는 방법은 무엇일까?
위에서 말했던 것 처럼 클래스를 역할과 책임에 따라 분리하는 것이다.
위의 코드처럼 강아지를 전담으로 맡는 강아지 사육사와 호랑이를 전담으로 맡는 호랑이 사육사, 곰을 전담으로 맡는
곰 사육사 총 3개의 클래스로 분리를 하였다.
만약 동물원에서 강아지가 더 이상 존재하지 않는다면 강아지사육사 또한 동물원에 있을 필요가 없기 때문에 클래스 자체를 없애면 SRP원칙이 성립한다.
또한 하나의 속성이 여러가지 의미를 갖는 경우도 SRP원칙을 지키지 못하는 경우이다
예를 들어 동물클래스에 먹다()메소드가 있다고 가정하자
여기서 육식 동물은 육고기를 먹지만 바다 생물은 생선을 먹는다.
위처럼 하나의 메소드가 여러가지 의미를 가지면 SRP원칙을 지키지 않았다고 한다.
OCP(개방 폐쇄 원칙)
OCP는 확장에는 열려있고 변경에는 닫혀있는 것을 의미한다.
위의 사진을 보면 최상위 클래스에는 Company클래스가 있고, 바로 아래에는 부서가 있다.
그 아래의 하위클래스에는 Server개발자, UI개발자, DBA관리자 클래스가 3개 있다.
여기서 만약 Server개발자가 한명 갑자기 관두었다고 하자.
그렇다면 과연 회사에 영향이 있을까?
이것을 예방하는 것이 바로 OCP(개방 폐쇄 원칙)이다.
한명이 관두었다고 해서 회사에 영향이 없는 것이다.
여기서 부서는 자신의 확장에는 열려있고, 회사는 주변의 변화에 폐쇄적이라는 것을 의미한다.
OCP원칙을 안 지킨다고 해서 구현이 불가능한 것은 아니지만
객체 지향 프로그래밍의 장점인 유연성, 재사용성, 유지보수성을 얻을 수 없다는 단점이 있다.
LSP(리스코프 치환 원칙)
LSP는 하위클래스의 인스턴스는 상위형 객체 참조 변수에 대입해 상위 클래스의 인스턴스 역할을 하는 데 문제가 없어야하는 원칙이다.
예를 들어서 군인이라는 클래스가 있고, 아이라는 클래스와 남자라는 클래스가 있다.
1. 군인 준 =new 아이();
2. 군인 준=new 남자();
위 문장은 LSP원칙을 지켰다고 할 수 있을까?
1번은 LSP원칙을 지키지 못했고, 2번은 LSP원칙을 지켰다고 할 수 있다.
1번은 준이라는 아이가 태어났는데 아이가 과연 군인역할을 할 수 있을까?
할 수 없다!
위처럼 하위 클래스의 인스턴스가 상위 클래스의 인스턴스의 역할을 하는데 문제가 발생하면
LSP원칙을 위반하였다고 한다.
2번 문장은 준이라는 남자는 군인의 역할을 할 수 있기 때문에 LSP원칙을 지켰다고 할 수 있다.
위의 다이어그램을 보면 남편과 할아버지는 남자로서의 역할을 할 수 있고, 부인과 할머니는 여자로서의 역할을 수행할 수 있고, 남자와 여자는 사람으로서의 역할을 수행할 수 있다.
따라서 위처럼 각각의 하위 클래스의 인스턴스가 상위 클래스의 인스턴스의 역할을 하는데 문제가 없기 때문에
LSP원칙을 지켰다고 할 수 있다.
ISP(인터페이스 분리 원칙)
ISP는 자신이 사용하지 않는 메소드에 의존관계를 맺으면 안된다는 것을 의미한다.
ISP를 보면 위에 설명한 원칙 중 낯익은 원칙이 있을 것이다.
바로 SRP원칙이다!
SRP는 클래스를 두어 역할을 분리했다면 ISP는 인터페이스를 두어 역할을 분리한 것이다.
즉 SRP와 ISP는 같은 문제에 대해 두 가지 다른 해결책을 두었다고 할 수 있다.
ISP를 할 때에는 상위클래스(사육사클래스)는 풍성할수록 좋고, 인터페이스(강아지 사육사, 호랑이 사육사, 곰사육사)는
작을수록 좋다.
왜냐하면 인터페이스는 최소한의 기능만 공개하는 것이 객체 지향적에 더 어울리기 때문이다.
DIP(의존 역전 원칙)
DIP는 자신보다 변하기 쉬운 것에 의존하던 것을 추상화된 인터페이스나 상위클래스를 두어 변하기 쉬운 것의 변화에
영향받지 않게 하는 것을 의미한다.
DIP를 보게되면 위에서 말한 원칙 중에 비슷한 것을 찾을 수 있다.
바로 OCP원칙이다.
다만 차이점이 있다면 클래스가 아닌 인터페이스를 두어서 하위클래스의 변화에 상위클래스가 영향을 받지 않도록 한다.
즉, 상위클래스, 인터페이스, 추상클래스일수록 변하지 않을 가능성이 높기 때문에 하위클래스나 일반 클라스가 아니라
상위클래스, 인터페이스, 추상 클래스를 통해 의존하라는 것이 DIP(의존 역전 원칙)이다.
정리하면....
SRP(단일 책임 원칙) | 어떤 클래스를 변경해야 하는 이유는 오직 하나뿐이어야 함 |
OCP(개방 폐쇄 원칙) | 자신의 확장에는 열려 있고, 주변의 변화에 대해서는 닫혀 있어야 함 |
LSP(리스코프 치환 원칙) | 서브 타입은 언제나 자신의 기반 타입으로 교체할 수 있어야 함 |
ISP(인터페이스 분리 원칙) | 클라이언트는 자신이 사용하지 않는 메소드에 의존 관계를 맺으면 안됨 |
DIP(의존 역전 원칙) | 자신보다 변하기 쉬운 것에 의존하면 안됨 |
'JAVA-SOLID' 카테고리의 다른 글
[OOP] 스프링 삼각형(AOP) (0) | 2023.06.21 |
---|---|
[OOP] 스프링 삼각형(IoC/DI) (0) | 2023.06.18 |
[OOP] 디자인 패턴(Singleton, Template Method, Strategy) (0) | 2023.06.14 |
[OOP] 디자인 패턴(Adapter, Proxy, Decorator Pattern) (0) | 2023.06.08 |
[OOP] 자바 vs 구조적/절차적 프로그래밍 (0) | 2023.05.30 |