SOLID
객체 지향 설계 원칙은 객체지향의 특징을 잘 살릴 수 있는 설계의 특징을 의미한다. 디자인 패턴이 특별한 상황에서 발생하는 문제에 대한 구체적인 솔루션이라고 한다면 설계 원칙은 일반적인 상황 좀더 높은 수준에서 지켜야할 원칙이라고 할까? 디자인 패턴을 보면 대부분 객체 지향 설계 원칙을 잘 지켜서 만들어진 것이다. 이미 검증된 객체 지향 설계 원칙을 지켜서 설계한다면 좀 더 유지보수하기 쉽고, 유연하고 확장이 쉬운 소프트웨러를 작성할 수 있다.
SOLID는 설계 5원칙의 첫 글자를 따서 만든 단어이다.
SRP(The Single Responsibility Princilpe) 단일 책임 원칙
모든 객체는 하나의 책임만을 가지며 객체가 제공하는 모든 서비스는 그 하나의 책임을 수행하는데 집중되어 있어야 한다. 즉 어떤 클래스를 변경해야 하는 이유는 오직 하나뿐이어야 한다.
객체 지향 프로그래밍에서 단일 책임 원칙(single responsibility principle)이란 모든 클래스는 하나의 책임만 가지며, 클래스는 그 책임을 완전히 캡슐화해야 함을 일컫는다. 클래스가 제공하는 모든 기능은 이 책임과 주의 깊게 부합해야 한다.
OCP(The Open-Closed Principle) 개방-폐쇄의 원칙
클래스,모듈, 함수 등등 소프트웨어 엔티티는 확장에는 열려있고 수정에는 닫혀 있어야 한다. 변경이 필요한 경우 기존 코드를 변경하지 않으면서 상속과 확장을 통해 변경 가능하게 설계한다.
개방-폐쇄 원칙의 두 가지 속성
- 확장에 대해 열려 있다.
- 이것은 모듈의 동작을 확장할 수 있다는 것을 의미한다. 애플리케이션의 요구 사항이 변경될 때, 이 변경에 맞게 새로운 동작을 추가해 모듈을 확장할 수 있다. 즉, 모듈이 하는 일을 변경할 수 있다.
- 수정에 대해 닫혀 있다
- 모듈의 소스 코드나 바이너리 코드를 수정하지 않아도 모듈의 기능을 확장하거나 변경할 수 있다. 그 모듈의 실행 가능한 바이너리 형태나 링크 가능한 라이브러리(예를 들어 윈도의 DLL이나 자바의 .jar)를 건드릴 필요가 없다.
LSP(The Liskov Substitution Principle) 리스코프 치환 원칙
자식 타입은 언제나 부모 타입들이 사용되는 곳에 교체할 수 있어야 한다.
컴퓨터 프로그램에서 자료형 S 가 자료형 T의 서브타입라면 필요한 프로그램의 속성(정확성, 수행하는 업무 등)의 변경 없이 자료형 T의 객체를 자료형 S의 객체로 교체(치환)할 수 있어야 한다는 원칙이다. 리스코프 치환 원칙(영어: Liskov substitution principle, LSP)은 바바라 리스코프가 자료 추상화와 계층 (Data abstraction and hierarchy)이라는 제목으로 기조연설을 한 1987년 컨퍼런스에서 처음 소개한 내용으로, 이 원칙을 엄밀한 용어로 말하자면 (강한) 행동적 하위형화라 부르는 하위형화 관계의 특정한 사례이다. 이 정의는 1994년 논문에서 다음 원칙을 만들어낸 자료형의 의미론적 상호처리를 보장하기 때문에 단순한 문법적 관계일 뿐만 아니라 의미론적 관계다.
전형적인 위반
이 부분의 본문은 Circle ellipse problem입니다.
LSP를 위반하는 전형적인 예로, 너비와 높이의 조회(getter) 및 할당(setter) 메서드를 가진 직사각형 클래스로부터 정사각형 클래스를 파생하는 경우를 들 수 있다. 정사각형 클래스는 항상 너비와 높이가 같다고 간주할 수 있다. 정사각형 객체가 직사각형을 다루는 문맥에서 사용되는 경우, 정사각형의 크기는 독립적으로 변경할 수 없기 때문에 (혹은 그래서는 안되기 때문에) 예기치 못한 행동을 하게 된다. 이 문제는 고치기 쉽지 않다. 정사각형 클래스의 할당 메서드를 수정하여 정사각형의 불변 조건(즉, 너비와 높이가 같음)을 유지하면, 이 메서드는 크기를 독립적으로 변경할 수 있다고 설명한 직사각형의 할당자의 사후 조건을 무력화(위반)한다. 이러한 LSP 위반은 실전에서는 LSP를 위반한 클래스를 사용하는 코드가 실제로 기대하는 사후 조건이나 불변 조건에 따라 문제가 될 수도 있고 아닐수도 있다. 여기서 중요한 사안은 가변성이다. 정사각형과 직사각형이 조회 메서드만 가진다면 (즉, 이들이 불변 객체라면), LSP 위반을 발생하지 않는다.
ISP(The Interface Segregation Principle) 인터페이스 분리 원칙
자신이 사용하지 않은 메소드에 의존관계를 맺지 말것. 어떤 객체의 사용자에게 그 사용자한테 필요한 메소드만 있는 인터페이스를 제공하라.
인터페이스 분리 원칙은 클라이언트가 자신이 이용하지 않는 메서드에 의존하지 않아야 한다는 원칙이다. 인터페이스 분리 원칙은 큰 덩어리의 인터페이스들을 구체적이고 작은 단위들로 분리시킴으로써 클라이언트들이 꼭 필요한 메서드들만 이용할 수 있게 한다. 이와 같은 작은 단위들을 역할 인터페이스라고도 부른다. 인터페이스 분리 원칙을 통해 시스템의 내부 의존성을 약화시켜 리팩토링, 수정, 재배포를 쉽게 할 수 있다. 인터페이스 분리 원칙은 SOLID 5원칙의 하나이며, GRASP의 밀착 원칙과 비슷하다.
DIP(The Dependency Inversion Principle) 의존관계 역전 원칙
고차원 모듈은 저차원 모듈에 의존하면 안된다. 추상화된 것은 구체적인 것에 의존하면 안된다. 고차원 모듈이든 저차원 모듈이든 최대한 추상화된 것에 의존하게 설계하고 구체적인 클래스에 의존하게 설계하지 말것.
이 원칙을 따르면, 상위 계층(정책 결정)이 하위 계층(세부 사항)에 의존하는 전통적인 의존관계를 반전(역전)시킴으로써 상위 계층이 하위 계층의 구현으로부터 독립되게 할 수 있다.
이 원칙은 다음과 같은 내용을 담고 있다.
- 상위 모듈은 하위 모듈에 의존해서는 안된다. 상위 모듈과 하위 모듈 모두 추상화에 의존해야 한다.
- 추상화는 세부 사항에 의존해서는 안된다. 세부사항이 추상화에 의존해야 한다.
이 원칙은 '상위와 하위 객체 모두가 동일한 추상화에 의존해야 한다'는 객체 지향적 설계의 대원칙을 제공한다.