# 03. 설계 원칙

## 설계원칙

* 07장 - **SRP (단일책임 원칙)**
* 08장 - **OCP** **(개방폐쇄 원칙)**
* 09장 - **LSP (리스코프 치환 원칙)**
* 10장 - **ISP (인터페이스 분리 원칙)**
* 11장 - **DIP (의존성 역전 원칙)**

### **목적**

* **변경에 유연**
* **이해하기 쉬움**
* 많은 소프트웨어 시스템에 사용될 수 있는 **컴포넌트의 기반**

### **SRP (단일책임 원칙)**

* **변경의 이유가 단 하나여야 한다.**



### OCP (개방폐쇄 원칙)

* 기존 코드 변경 보다는 **새로운 코드 추가의 방식** 으로 될 수 있도록 설계 되어야 한다.
* 확장에는 열려 있고(추가, 확장등), 수정에는 닫혀 있어야(수정의 범위는 제한적이어야함) 한다.
* 컴포넌트 간 화살표 (단방향). A->B (A는 B를 알고, 사용 / B는 A를 모름)
* 추이의존성 주의!
  * A->B, B->C => A->C 의 의존성을 갖게되면.... A의 변경이 C에 까지 영향을 미치게됨... ISP 필요(의존성분리)
  * 1뎁스의 의존성을 갖도록 설계해야함

### LSP (리스코프 치환 원칙)

* **하위타입**에 대한 유명한 원칙. **구성요소는 서로 치환가능** 해야한다.
* **다형성에** 기인한다.
* T타입(상위) S타입(하위) -> T타입 자리에 S타입 적용 -> 프로그램 행위변화가 없도록 설계.
  * 여기서 **S타입에 대한 수정이 발생한다면..? 안되겠지.** 하위타입에 따라 수정사항이 발생하니!!&#x20;
* 가장 좋은 예는 **전략패턴** 인듯
* 아키텍처 수준까지 확장할 수 있고, 반드시 확장해야한다. 그렇지 않으면 별도의 메커니즘이 필요해지고, 그러다보면 시스템이 점차 오염되어 유지보수성이 떨어지게 됨

### ISP (인터페이스 분리 법칙)

* **사용하지 않는 것에 의존해서는 안된다.**
* **한 메서드에 여러가지 기능 존재 -> 간단한 변경사항 발생 -> 모든 클라이언트에 영향 미침 -> 적절한 분리필요**

### DIP (의존성 역전 법칙)

* 고수준 정책을 구현하는 코드는 **저수준 세부사항(블랙박스, 라이브러리 등)을 구현하는 코드에 절대 의존해서는 안된다. 대신 세부사항이 정책에 의존해야한다.**
* **추상에 의존해야지 구현체에 의존해서는 안된다.**
* 대상 -> **변동성이 큰 구현체**
* **인터페이스의 변동성을 낮추기 위해 노력**. 인터페이스 변경 없이 구현체의 기능 추가가 될 수 있게!! **설계 기본**

#### 규칙

* 변동성이 큰 구체 클래스 참조하지 말 것 -> 일반적으로 객체 생성방식 제약 -> **추상팩토리 사용 권장**
* 변동성이 큰 구체 클래스로 부터 파생하지 말 것 -> 상속은 신중히!
* 구체 함수를 오버라이드 하지 말 것 -> **추상메서드 활용하여 서브타입에서 정의**

#### 팩토리

* 생성관리
* **추상팩토리 패**
* **의존성역전(DI) -> 제어흐름이 소스코드 의존성과 반대 방향으로**

**구체컴포넌트**

* DIP를 완전히 배제할 수는 없다.
* 적절한 **시스템 관점에서 분리** 필요.

