단일 모듈은 변경의 이유가 하나, 오직 하나 뿐이어야 한다.
- 하나의 모듈은 오직 하나의 Actor에 대해서만 책임져야 한다.
- 컴포넌트 수준에서는
공통 폐쇄 원칙 (Common Closure Principle)
이 된다.- 아키텍처 수준에서는 아키텍처 경계의 생성을 책임지는
변경의 축
이 된다.
classDiagram
direction LR
PayCalculator --> EmplyeeData
HourReporter --> EmplyeeData
EmployeeSaver --> EmplyeeData
PayCalculator : +calculatePay(EmplyeeData)
HourReporter : +reportHours(EmplyeeData)
EmployeeSaver : +saveEmployee(EmplyeeData)
classDiagram
direction RL
HourReporter <-- Employee
EmployeeSaver <-- Employee
class Employee{
-employeeData
+calculatePay()
+reportHours()
+save()
}
HourReporter : +reportHours()
EmployeeSaver : +saveEmployee()
소프트웨어 개체는 확장에는 열려 있어야 하고, 변경에는 닫혀 있어야 한다.
- 소프트웨어 개체의 행위는 확장할 수 있어야 하지만, 이때 개체를 변경해서는 안된다.
- OCP의 목표는 시스템을 확장하기 쉬운 동시에 변경으로 인해 시스템이 너무 많은 영향을 받지 않도록 하는데 있다.
- 이를 위해서는 시스템을 컴포넌트 단위로 분리한다.
- 저수준 컴포넌트에서 발생한 변경으로부터 고수준 컴포넌트를 보호할 수 있는 형태의 의존성 계층구조가 만들어지도록 해야한다. (의존성 역전)
S가 자료형 T의 서브타입라면 필요한 프로그램의 속성의 변경 없이 자료형 T의 객체를 자료형 S의 객체로 교체(치환)할 수 있어야 한다.
- 객체 지향 초창기에는 LSP는 상속을 사용하도록 가이드하는 방법 정도로 간주되었다.
- 최근에는 인터페이스와 구현체에도 적용되는 더 광범위한 소프트웨어 설계 원칙으로 변모해 왔다.
- 잘 정의된 인터페이스와 그 인터페이스의 구현체끼리의 상호 치환
클라이언트가 자신이 이용하지 않는 메서드에 의존하지 않아야 한다
- Before
첫째, 상위 모듈은 하위 모듈에 의존해서는 안된다. 상위 모듈과 하위 모듈 모두 추상화에 의존해야 한다.
둘째, 추상화는 세부 사항에 의존해서는 안된다. 세부사항이 추상화에 의존해야 한다.
- 👍 소스코드 의존성이
추상
에 의존하고,구체
에는 의존하지 않는 시스템- 우리가 의존하지 않도록 피하고자 하는 것은?
- 변동성이 큰 구체적인 요소 (volatile)
- 주요 담당하는 비지니스 로직
변동성이 큰 구현체에 의존하는 일은 지양하고, 안정된 추상 인터페이스를 선호하라.