객체 지향 설계 에는 SOLID라고 부르는 5가지 설계 원칙이 존재한다.
1. SRP - 단일 책임 원칙 : 한 클래스는 하나의 책임만 가져야 한다.
2. OCP - 개방/폐쇄 원칙 : 소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.
3. LSP - 리스코프 치환 원칙 : 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.
4. ISP - 인터페이스 분리 원칙 : 특정 클라이언트를 위한 인터페이스 여러개가 범용 인터페이스 하나보다 낫다.
5. DIP - 의존관계 역전 원칙 : 프로그래머는 추상화에 의존해야지, 구체화에 의존하면 안된다.
정의
한 클래스는 하나의 책임만 가져야 한다.
책임의 중요한 기준은 변경이다.
변경이 있을 때 파급효과가 적으면, 단일 책임 원칙을 잘 따른 것.
이는 객체지향 원리의 대전제 격인 OCP원리 뿐만 아니라, 다른 원리들을 적용하는 기초가 된다.
적용 방법
여러 책임을 가지고 있는 경우
혼재된 각 책임을 각각의 개별 클래스(Extract Class) 로 분할 → 클래스 당 하나의 책임만 맡도록 한다.
핵심은 단순리 책임 만 분리하는 것이 아닌, 분리된 두 클래스간의 관계의 복잡도를 줄이도록 설계하는 것이다.
산발적으로 여러 곳에 책임이 분산 된 경우
해당 책임을 Move Field와 Move Method를 통해 특정 클래스로 모은다.
(마땅한 클래스가 없으면 새로운 클래스를 만든다.) → 응집성 증가
효과
책임 영역이 확실해 집으로 특정 책임 A의 변화가 책임 B의 변화로 이뤄지는 잘못된 연쇄작용에서 자유로워 질 수 있다.
책임을 적절히 분배함으로써 코드의 가독성을 향상하고 유지보수를 용이하게 한다.
정의
소프트웨어의 구성요소인 컴포넌트, 클래스, 모듈, 함수는 확장에는 열려있고 변경에는 닫혀있어야 한다.
변경을 위한 비용을 최소화 하고, 확장을 위한 비용은 최대화 한다.
즉, 요구사항의 변경에도 기존 구성요소는 수정이 일어나면 안되며, 단순한 확장을 통한 재사용이 가능해야 한다.
OCP를 가능하게 하는 주요 메커니즘은 추상화와 다형성.
적용 방법
효과
정의
상속은 구현 상속(extends)이든, 인터페이스 상속(implements)이든 궁극적으로는 다형성을 통한 확장성 획득을 목표로 한다.
다형성과 확장성을 극대화 하기 위해서는 , 하위 클래스를 사용하는 것 보다는 상위 클래스(or 인터페이스)를 사용하는 것이 더 좋다.
적용 방법
효과
정의
적용 방법
클래스 인터페이스를 통한 분리
클래스의 상속을 이용해 인터페이스를 분리한다.
분리된 인터페이스를 여러개 상속받아 클라이언트에게 변화를 주지 않을 수 있다.
객체 인터페이스를 통한 분리
위임(Delegation)을 이용해 인터페이스를 나눌 수 있다.
위임 : 특정 작업의 책임을 다른 클래스나 메소드에 맡기는 것으로, 만약 다른 클래스의 기능을 사용해야 하나 그 기능을 바꾸고 싶지 않다면 상속 대신 위임을 사용한다.
효과
두 개 이상의 인터페이스가 공유하는 부분의 재사용을 극대화 한다.
서로 다른 성격의 인터페이스를 명백히 분류한다.
정의
구조적 디자인에서 발생하던 하위 레벨 모듈의 변경이 상위 레벨 모듈의 변경을 요구하는 위계 관계를 끊는 의미의 역전이다.
추상화(인터페이스)는 구체화(구현 클래스)에 의존해서는 안되고, 구체화는 추상화에 의존해야 한다.
적용 방법
Transitive Dependency (전이 의존성) : 어떤 라이브러리를 의존성으로 추가하면, 그 라이브러리가 가지고 있는 의존성이 함께 딸려온다. 그렇게 딸려온 의존성들을 전이 의존성이라고 한다.
재귀적으로 라이브러리가 라이브러리를 요구하게 되는 상황을 전이 의존성이라 한다.
효과
IOC, Hook Method, 확장성 이라는 핵심 요소가 조합되어, 복잡한 컴포넌트들의 관계를 단순화 하고 컴포넌트 간의 커뮤니케이션을 효율적이게 한다.
복잡하고 지난한 컴포넌트 간의 커뮤니케이션 관계를 단순화 하기 위한 원칙
Hook Method : 슈퍼 클래스에서 디폴트 기능을 정의 or 내용을 비워두어서, 서브 클래스에서 선택적으로 오버라이드 할 수 있도록 만든 메서드.
서브 클래스에서는 Hook Method를 오버라이드하거나, 추상 메서드를 구현하는 방법을 이용해 기능의 일부를 확장한다.