SOLID는 로버트 C. 마틴이 객체 지향 프로그래밍 및 설계의 다섯 가지 기본 원칙으로 제시한 것이다.
이 원칙들은 다음의 고전 원칙을 객체 지향의 관점에서 재정립한 것이다.
High Cohesion, Loose Coupling
응집도는 높이고, 결합도는 낮춰라
이제 각각의 원칙들을 알아보자.
"어떤 클래스를 변경해야하는 이유는 오직 하나뿐이어야 한다." - 로버트 C. 마틴
만약 음식점이라는 한 클래스에서 요리도 하고, 주문도 받고, 배달도 한다면 유지보수하기에 아주 어지러울 것이다.
class 음식점 {
void 요리하기() {
// 맛있게 만들어준다.
}
void 주문받기() {
// 손님에게 친절하게 대응하며 주문을 받는다.
}
void 배달하기() {
// 빠르고 안전한 배달 서비스합니다.
}
}
이를 SRP를 적용하면 아래의 코드처럼 각각의 역할을 만들어서 분리시키면 된다.
class 요리사 {
void 요리하기() {
// 맛있게 만들어준다.
}
}
class 캐셔 {
void 주문받기() {
// 손님에게 친절하게 대응하며 주문을 받는다.
}
}
class 배달원 {
void 배달하기() {
// 빠르고 안전한 배달 서비스합니다.
}
}
단일 책임의 원칙은 클래스 뿐만 아니라 속성, 메서드, 패키지, 모듈, 컴포넌트, 프레임워크 등에도 적용할 수 있다.
"소프트웨어 엔티티(클래스, 모듈, 함수 등)는 확장에 대해서는 열려 있어야 하지만 변경에 대해서는 닫혀 있어야 한다." - 로버트 C.마틴
"소프트웨어 엔티티(클래스, 모듈, 함수 등)는 확장에 대해서는 열려 있어야 하지만 변경에 대해서는 닫혀 있어야 한다." - 로버트 C.마틴
객체 지향에서의 상속은 조직도나 계층도가 아닌 분류도가 돼야 한다.
리스코프 치환 원칙은 객체 지향의 상속이라는 특성을 올바르게 활용하면 자연스럽게 얻게 되는 것이다.
하위 클래스 is a kind of 상위 클래스 - 하위 분류는 상위 분류의 한 종류다.
구현 클래스 is able to 인터페이스 - 구현 분류는 인터페이스할 수 있어야 한다.
리스코프 치환 원칙 위키
하위형에서 선행 조건은 강화될 수 없다.
하위형에서 후행 조건은 약화될 수 없다.
하위형에서 상위형의 불변 조건은 반드시 유지돼야 한다.
"클라이언트는 자신이 사용하지 않는 메서드에 의존 관계를 맺으면 안 된다." - 로버트 C.마틴
인터페이스를 통해 메서드를 외부에 제공할 때 최소한의 기능만 제공해야한다.
"고차원 모듈은 저차원 모듈에 의존하면 안 된다. 이 두 모듈 모두 다른 추상화된 것에 의존해야 한다."
"추상화된 것은 구체적인 것에 의존하면 안 된다. 구체적인 것이 추상화된 것에 의존해야 한다."
"자주 변경되는 구체(Concrete)클래스에 의존하지 마라" - 로버트 C.마틴
JPA에서 DIP의 예를 볼 수 있다.
상위클래스일수록, 인터페이스일수록, 추상 클래스일수록 변하지 않을 가능성이 높다.
따라서 하위 클래스나 구체 클래스가 아닌 상위클래스, 인터페이스, 추상 클래스를 통해 의존하는 것이 DIP이다.
하지만 이는 이해하기 쉽고, 유지보수가 편하도록 만든 것이기 때문에 충분히 감수할 만하다.
SoC를 적용하면 SRP, ISP, OCP에 자연스럽게 도달할 수 있다.