SOLID 원칙은, 객체지향프로그래밍/설계를 위해 다섯 가지 기본 원칙을 모아 둔 것으로, SW 작업에서
S SRP(Single responsibility principle) : 단일 책임 원칙
O OCP(Open/closed principle) : 개방-폐쇄 원칙
L LSP(Liskov substitution principle) : 리스코프 치환 원칙
I ISP(Interface segregation principle) : 인터페이스 분리 원칙
D DIP(Dependency inversion principle) : 의존관계 역전 원칙
어떤 설계가 좋은 설계인가?
-> 고치는 부분이 적은
그럼 나쁜 설계는?
- 경직성 (Shotgun)
- 부서지기 쉬움 (작동이 멈춤)
- 부동성 (재사용이 어려움)
- 끈끈함 (long cycle)
- 쓸데없이 복잡함 (이해하기 어려움)
- 필요없이 복잡함 (clone이 많음)
- 불투명함 (의도가 희미한 것)
=> 이런것들을 없애야 함
SRP(Single responsibility principle) : 단일 책임 원칙
클래스에게 너무 많이 알게 하지 말고, 한 클래스에게 책임을 단일하게 주도록!
즉, Separation of Concerns 하라! -> 클래스가 많아지고 설계가 Simple 해짐
한 클래스가 너무 많은 책임을 갖고 있으면 수정이 어려움
ex) 한 클래스를 변경(추가)하려할 때
OCP(Open/closed principle) : 개방-폐쇄 원칙
SW 요소는 확장/추가에 대해 열려있지만, 변경/수정에 대해서는 닫혀 있어야(localize) 한다.
ex) DB를 바꿈 -> DB안의 쿼리만 바꾸지 다른 구현 사항은 변경되지 않아야 함.
LSP(Liskov substitution principle) : 리스코프 교체 원칙
Base class(기본 클래스)를 사용.
-> 파생 클래스에 대해서 알 필요 없이 사용하게 해야함
- 서브타입이 베이스 타입에 교체될 수 있어야 함
- 더 이상의 요구(슈퍼클래스에서 받는 매개변수는 서브클래스가 다 받아야 함) 없음 / 더 이하의 약속(슈퍼클래스가 사용되었을 때 유효하면 서브클래스가 사용되었을 때도 유효하다는) 없음
- 인터페이스 상속할 때에, LSP가 적용되어야 함
- 구현 상속 ( 상속 대신 컴포지션 사요아 )
상속을 구현할 때 A KIND OF의 의미에 맞춰서 작성해야하는데, 그렇지 않고 단지 슈퍼 클래스의 메소드를 사용하기 위해 사용한다면 LSP에 위배 됨(exception해야할 수도)
ISP(Interface segregation principle) : 인터페이스 분리 원칙
- 클라이언트는 자신이 사용하지 않는 메서드에 의존하면 안됨
- 다른 여러 클라이언트를 위한 기능을 하나의 인터페이스나 클래스에 넣어 비대하게 만들면, 1. 클라이언트에 불필요한 결합이 생기고, 2. 한 클라이언트에 변경이 생기면 다른 클라이언트도 다시 컴파일해야 함
DIP(Dependency inversion principle) : 의존관계 역전 원칙
높은 수준의 개념(인터페이스, 추상클래스)이 낮은 수준의 구현보다 더 안정적임(덜 변한다)
- 구체적인 것이 추상적인 것에 의존하하여야 함.
번외
디메테르의 법칙 (Law of Demeter)
주어진 프로그램에서 모듈 사이의 결합을 최소화하는 것
1. 클래스 안의 메소드
2. 메소드에 전달된 파라미터 객체의 메소드 호출
3. 자신이 만든 객체의 매소드
4. 내부 객체의 메소드
추상 재사용
- 재사용 가능 소프트웨어
느슨한 결함
강한 응집
- 컴포넌트의 지속적인 리팩토링
- 과한 사용
Abstraction Layers everywhere
다중 구현이 필요하여 확실해질 때까지 추상 층을 넣지 않을 것
- 상속의 과다 사용 -> 캡슐화를 위배
*상속은 재사용을 어렵게 만듦. 꼭 필요할 때에만 사용하는 것을 권고.