SOLID 를 알아보자
객체지향 5대 개발 원리 SOLID
면접을 준비할겸 나의 경험을 바탕으로 SOLID 에 대해서 정리 한다.
이 글을 읽기 전에…
- 이유를 알고 사용해야 진정한 의미로 사용한다고 할 수 있다.
- 이유를 설명을 하지 못한다면 그것은 모르고 있다.
- 어려운 용어를 쉬운 용어와 예제를 들어서 설명할 수 있어야 한다.
- 설명하고자 하는 규칙을 사용하지 않았을 때의 단점을 이야기한다면, 사용 해야 할 이유가 더욱 와닿는다.
위에 적어둔 내용은 내가 생각하기에 어떠한 개념을 100%에 가깝게 이해했다고 할 수 있는 기준 요건이다.
따라서 위에 언급한 내용을 토대로 객체지향 SOLID를 설명해 보자!
SRP(Single Responsibility Principle) 단일 책임 원칙
한 클래스는 하나의 책임만 가져야 한다.
-
SRP 방법?
- 하나의 클래스에는 그와 관련된 하나의 책임을 진 기능을 구현한다.
- 그 책임은 캡슐화를 해야 한다.
- 해당 클래스에만 초점을 맞추는 것이 아니라 해당 클래스에 어떤 액터(시스템이 동일한 방식으로 변경되기를 원하는 사용자 집단)들이 의존하게 되는지를 생각하며 구현한다.
-
SRP 장점?
-
이해하기 쉽다.
-
문제가 발생했을 때 한 가지 책임에 대한 처리를 하므로 해결하기 쉽다.
-
그로 인해 유지보수가 쉽다.
-
-
SRP 를 위배하면 생기는 문제?
-
하나의 클래스에서 여러 기능을 처리하게 된다면 유지 보수를 할 때 해당 클래스가 어떤 동작을 하는지 이해하기가 어렵게 된다.
-
하나의 클래스에 두 가지 이상의 책임이 있으면, 해당 클래스의 특정 기능의 수정이 필요해 수정하면, 같은 클래스를 사용 중이면서 수정된 기능이 필요 없는 다른 곳에서 문제가 발생하게 된다.
-
-
좋지 않은 예시
public class 세제 {
public void 세척을_위한_계면활성제() {
// 세제를 사용하면 계면활성제가 나오는 기능
}
public void 빨래의_향기를_위한_섬유유연제_성분() {
// 세제를 사용하면 은은한 섬유유연제 향이 나오는 기능
}
}
- 위와 같이 세제를 설거지, 빨래에 사용 중이다.
- 하지만 식기에서 섬유유연제 향이 나면 곤란해서 해당 기능을 제거하려고 한다.
- 그렇게 되면 섬유유연제 성분이 필요한 빨래에도 기능이 빠져버리는 문제가 발생한다.
OCP(Open Closed Principle) 개방 폐쇄 원칙
소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.
아니 이게 무슨 소리지?
위의 정의는 확장은 가능하면서 변경은 불가능해야 한다는 의미이다.
그래도 아직 이해가 잘되지 않는다.
좀 더 풀어서 설명하자면, 기능을 변경 또는 확장할 수 있으면서 그 기능을 사용하는 코드는 수정하지 않는 것을 의미한다.
-
OCP 방법?
- 인터페이스를 주입해서 사용하면 된다.
- 상속을 사용해도 OCP 를 지킬 수 있다.
-
OCP 장점?
- 기능의 변경이 일어날 때 해당 기능이 구현된 곳만 변경해주거나 다른 구현된 기능을 주입하면 된다.
-
OCP 를 위배하면 생기는 문제?
- 기능 내부의 변경이 발생할 때 내부 소스 코드를 수정 해야 하는 상황이 발생한다.
LSP(Liskov Substitution Principle) 리스코프 치환 원칙
프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.
- LSP 방법?
- is-a 관계에 맞게 설계한다.
- 부모 클래스의 조건을 모두 만족 해야 한다.
- 부모 클래스를 대신할 수 있어야 한다.
- 상속받은 메서드가 재정의(오버라이드)되지 않아야 한다.
- LSP 장점?
- 부모 클래스의 행위를 더 명확하게 정의할 수 있는 수단으로 사용할 수 있다.
- 기존 코드 변경 없이 확장이 가능하다.
- LSP 를 위배하면 생기는 문제?
- 불변 객체가 아닐 경우 설계 구조에 따라 구조가 변경되어 원하지 않은 결과가 도출되는 문제가 발생할 수 있다.
- 예를 들어 정사각형 객체가 직사각형을 다루는 경우, 길이를 수정할 때 문제가 발생한다.
ISP(Interface Segregation Principle) 인터페이스 분리 원칙
특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.
- ISP 방법?
- 큰 덩어리의 인터페이스를 구체적이고 작은 단위로 분리한다.
- ISP 장점?
- 클라이언트가 꼭 필요한 메서드만 이용할 수 있다.
- 의존성을 약화해 리팩토링을 쉽게 할 수 있다.
- ISP 를 위배하면 생기는 문제?
- 불필요한 메서드도 포함하게 된다.
- 리팩토링 시에 영향을 미치는 범위가 커진다.
DIP(Dependency Inversion Principle) 의존관계 역전 원칙
프로그래머는 추상화에 의존하고 구체화에 의존하면 안 된다.
의존성 주입은 원칙을 따르는 방법의 하나다.
자신보다 변하기 쉬운 것에 의존하지 마라.
- DIP 방법?
- 상위 모듈과 하위 모듈은 모두 추상화에 의존해야 한다.
- 세부사항이 추상화에 의존해야 한다.
- 자신보다 변하기 쉬운 것에 의존하는 것을 인터페이스, 상위 클래스에 위치시켜서 변하기 쉬운 것에 영향을 받지 않게 한다.
- DIP 장점?
- 의존성 주입을 사용하여 종속성 감소, 재사용성 증가, 코드 단순화가 된다.
- 리팩토링할 때 기존 코드를 건드리지 않고 주입할 코드만 변경하면 된다.
- DIP 를 위배하면 생기는 문제?
- 수정이 이루어질 때마다 코드를 계속 바꿔줘야 한다.
- DIP 를 위반하면 OCP 의 위반으로 이어진다.
느낀 점
SOLID 에서 정의하는 내용을 한 줄로 정의해 본다.
단일책임, 추상화, 의존성 약화, 캡슐화를 지켜서 프로그램을 설계 해야 한다.