SOLID 객체지향 설계 원칙
- SRP: 단일 책임 원칙
- OCP: 개방-폐쇄 원칙
- LSP: 리스코프 치환 원칙
- ISP: 인터페이스 분리 원칙
- DIP: 의존성 역전 원칙
Single Responsibility Principle
단일 클래스는 단 한 개의 책임을 가져야 한다. (= 클래스를 변경하는 이유는 오직 하나여야만 한다)
하나의 클래스가 여러 개의 변경하는 메소드를 갖고 있다면, 이 클래스를 분리하라는 신호일 수 있다. 그런데 정확히 ‘변경하다’의 의미가 무슨 뜻일까?
Open-Closed Principle
객체는 확장에 대해서는 열려있지만, 수정에 대해서는 닫혀있다.
상속(Inheritance) 또는 합성(Composition)을 통해 기능을 확장할 수 있다. 요구사항이 변경되었을 때, 기존 클래스 메소드의 내부 코드를 변경하는 대신, 새로운 클래스나 기능을 만들어서 확장하는 것이 이상적이다.
Liskov Substitution Principle
자식 클래스(하위 타입)은 부모 클래스를 항상 대체할 수 있다.
자식 클래스 S의 개체는 모두 부모 클래스 T의 개체라고 간주할 수 있어야 한다. 즉 is-a 관계가 성립해야 한다.
Interface Segregation Principle
인터페이스는 그 인터페이스를 사용하는 클라이언트를 기준으로 분리한다.
클라이언트에서 사용하지 않는 메소드가 존재하면 안 된다. 그러므로 하나의 인터페이스를 여러 개의 클라이언트가 불필요한 메소드를 구현하면서까지 공유하는 것보다, 인터페이스 자체를 분리하는 것이 옳다.
Dependency Inversion Principle
고수준 모듈은 저수준 모듈의 구현에 의존해서는 안 된다. (= 저수준 모듈이 고수준 모듈에서 정의한 추상 타입에 의존해야 한다.)
- 고수준 모듈: 의미있는 단일 기능을 제공하는 모듈
- ex) 바이트 데이터를 읽어온다 → 암호화하고 → 결과 바이트 데이터를 쓴다
- 저수준 모듈: 고수준 모듈의 기능을 구현하기 위해 필요한 개별 기능
- ex) 파일에서 바이트 데이터를 읽어온다 → AES 알고리즘으로 암호화 → 파일에 바이트 데이터를 쓴다
추가: 디미터(Demeter) 법칙
어떤 객체의 메소드는 다음과 같은 종류의 객체에 있는 메소드들만 실행시킬 수 있다.
- 객체의 메소드
- 메소드의 변수
- 메소드 안에서 만들어진 객체
- 객체가 직접 관리하는 component 객체
- 메소드의 스코프 안에서 객체가 접근 가능한 전역변수
즉, 어떤 객체의 메소드에서 다른 객체에 속한 변수에 직접 접근하는 것은 잘못된 설계의 신호일 수 있다.
예시
어떤 원칙이 깨질 때에 어떤 현상이 나타나는지 그 예시를 아래의 글에서 확인할 수 있다.
- https://jungwoon.github.io/solid/2017/07/31/Solid-Principle/
객체지향 3요소
- Encapsulation
- Inheritance or Delegation
- Polymorphism