# 객체 지향 설계 원칙 (SOLID)

## 5가지 원칙 요약

| 약어      | 원칙 이름       | 한줄요약                                                                            |
| ------- | ----------- | ------------------------------------------------------------------------------- |
| **SRP** | 단일 책임 원칙    | 클래스에는 변경 해야 할 이유(책임)가 하나만 존재 해야 한다.                                             |
| **OCP** | 개발 폐쇄 원칙    | <p>클래스 동작을 수정하지 않고, 확장할 수 있어야한다. <br>(클래스나 모듈확장에는 열려있고, 클래스의 동작 변경에는 닫혀있다.)</p> |
| **LSP** | 리스코프 치환 원칙  | 파생 클래스는 기본 클래스로 대체 가능해야한다.                                                      |
| **ISP** | 인터페이스 분리 원칙 | 클라이언트 별로 세밀한 인터페이스를 만들어야한다.                                                     |
| **DIP** | 의존관계 역전 원칙  | 추상화에 의존                                                                         |

### The Single Responsibility Principle (SRP, 단일 책임 원칙)

* 정의
  * **모든 클래스는 하나의 책임(= 변경해야할 이유)만 가지며, 그 책임을 완전히 캡슐화 해야한다.**
  * 책임에 대한 적절한 분배는 유지보수, 가독성을 높힌다.
  * 하나의 책임 변경에서, 다른 책임의 변경으로의 연쇄 작용에 자유롭다.
* 높은 응집도와 낮은 결합도 (High Coherence and Low Coupling)
  * 높은 응집도:&#x20;
    * 하나의 모듈, 클래스가 하나의 책임 또는 관심사에만 집중 되어있는 경우.
    * 불필요하거나, 직접 관련이 없는 외부의 관심과 책임이 얽혀있지 않고, 하나의 공통 관심사는 한 클래스에 모여있다.
    * 클래스 레벨 뿐만 아니라, 패키지, 컴포넌트, 보듈에 이르기까지 대상의 크기가 다르더라도 동일 원리가 적용된다.
  * 낮은 결합도:&#x20;
    * 결합도: 하나의 오브젝트가 변경이 일어날 때에 관계를 맺고 있는 다른 오브젝트에게 변화를 요구하는 정도
    * 따라서 낮은 결합도 일 수록 변경에 따른 여타 모듈과 객체로 변경에 대한 요구가 전파되지 않는다.
* 산탄총 수술이라는 용어가 나오는데, 산재(분산)되어있는 기능들을 공동 책임끼리 한 곳에 모아 응집도를 높히는 과정을 뜻한다.

### Open Closed Principle (OCP, 개방 폐쇄 원칙)

* **클래스나 모듈확장에는 열려있어야하고, 변경에는 닫혀있어야한다.**
  * DAO에 영향을 주지 않고도, 얼마든지 DB 연결 방법이라는 기능 확장에는 열려있고
  * DAO에 구현한 핵심 기능 코드는 기능 확장이나 변화에 영향을 받지 않고 유지할 수 있다.
  * 상위 클래스나 인터페이스를 활용해서 수정 및 변동사항이 생길 경우, 기존 구성 요소의 수정은 막고(close)

    확장을 통한 재정의 및 재사용은 허용(open) 함으로써 객체간의 결합도를 줄여준다.
* 디자인 패턴 중 **전략 패턴(Strategy Pattern)**
  * 자신의 기능 맥락(Context)에서 필요에 따라 변경이 필요한 알고리즘을 인터페이스를 통해 통째로 외부로 분리시키고
  * 이를 구현한 구체적인 알고리즘 클래스를 필요에 따라 바꿔 사용할 수 있게 하는 디자인 패턴
  * 여기서 알고리즘 = 독립적인 책임으로 분리가 가능한 기능

### The Liskov Substitution Principle (LSP, 리스코프 치환 원칙)

* 정의
  * **파생 클래스는 기본 클래스로 대체 가능해야한다.**
  * 부모 클래스와 자식 클래스 사이의 행위에는 일관성이 있어야한다.&#x20;
  * 부모 클래스의 인스턴스 대신, 자식 클래스의 인스턴스를 사용해도 문제가 없어야한다.
  * 자식 클래스는 부모 클래스에서 가능한 행위를 수행할 수 있어야한다.
  * 상속관계에서 IS-A관계 성립. (=일관성 있다.)

### Interface Segregation Principle (ISP, 인터페이스 분리 원칙)

* 정의
  * **클라이언트 별로 세밀한 인터페이스를 만들어야한다.** &#x20;
  * 하나의 일반적인 인터페이스 보다는, 여러개의 구체적인 인터페이스가 낫다.&#x20;
  * 인터페이스의 클라이언트에 특화되도록 분리시키는 설계원칙
* 예
  * 복합기의 기능에는 print, fax, copy기능이 있다.
  * 이를 이용하는 사람은 본인이 원하는 기능만 작동 되면 되며, 자신이 이용하지 않는 기능에 대해서는 영향을 받지 않는다.
  * 이 때 범용의 interface를 만드는게 아니라, 클라이언트에 특화된 interface를 사용해야한다는 것.

### Dependency Inversion Principle (DIP, 의존 역전 원칙)

* **의존 관계를 맺을 때, 변화하기 쉬운 것 보단 변화하기 어려운 것(추상)에 의존해야한다.**
  * 변화하기 쉬운 것 (구체적인 것, 구체화 된 클래스)
  * 변화하기 어려운 것 (추상적인 것, 추상클래스나 인터페이스)
* DI를 할 때 유연한 설계가 가능.

[참고1](https://dev-momo.tistory.com/entry/SOLID-%EC%9B%90%EC%B9%99)

[참고2](http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod?)

[참고3](https://velog.io/@kyle/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-SOLID-%EC%9B%90%EC%B9%99-%EC%9D%B4%EB%9E%80)

[참고4](https://minhee0327.gitbook.io/mini-til/design-pattern/broken-reference)
