
객체 지향 소프트웨어를 견고하고 확장 가능하게 설계하기 위한 다섯가지 기본 원칙
SRP 단일책임 원칙:
모든 클래스는 단 하나의 책임(responsibility)만을 가져야 함
(하나의 클래스는 하나의 기능만을 담당하여 하나의 책임을 수행하는데 집중)
"변경"에 취약
예측하지 못한 변경사항이 발생하더라도 유연하고 확장성있게 시스템구조를 설계(유지보수성을 높이기 위함)
하나의 클래스에 여러 책임이 있다면, 변경이 일어났을 때 수정해야하는 코드가 많아짐
(클래스 내부에서 서로 다른 역할을 수행하는 코드가 강하게 결합되면 변경에 유연하게 대응할 수 없음)
한 클래스에서 너무 많은 책임을 부여하지 말고 단 하나의 책임만 수행하도록 변경하는 것
ex) 여러 역할을 하는 student라는 클래스
Student 클래스의 변경사유가 될 수 있는 것들을 분리
1) 학생의 고유정보
2) 데이터베이스 스키마
3) 출력 형식 변화
OCP 개방-폐쇄 원칙
확장에는 열려 있어야 하며, 수정에는 닫혀 있어야 함
- 확장에 열림: 변경사항이 발생했을 때 기존의 코드를 유연하게 확장
- 수정에 닫힘: 기존의 코드에는 수정이 없음
추상화를 통해 상속 및 다형성 구조를 잘 마련한다면 OCP가 간편해짐
무엇이 변하는 것인지, 무엇이 변하지 않는 것인지를 명확하게 구분
(변해야 하는 것은 손쉽게 변하고, 않아야 하는 것은 변하는 것에 영향을 받지 않도록)
LSP 리스코프 치환 원칙
상위 타입의 객체를 하위 타입의 객체로 치환해도 상위 타입을 사용하는 프로그램은 정상 작동해야 함

LSP가 지켜지지 않은 예시
- 오버라이딩을 잘못 한 경우
- 부모의 의도와 다른 오버라이딩
- 잘못된 상속 관계 구성1
A개발자가 상속 구조의 호환성을 위해 Fish에서 speak은 구현하되 의미없는 동작을 하게 함 (예외를 출력)
B개발자는 상속 구조를 보고 LSP에 입각하여 위와 같이 list에서 사용을 했는데 예상치 못한 예외가 출력- 잘못된 상속 관계 구성2
코드를 수정한다면 speak은 따로 빼서 필요한 클래스에서만 구현하게 상속 구조를 수정
B개발자는 speak을 할 수 있는 객체만 리스트에 담을 수 있음
(LSP를 따른다면 Fish를 리스트에 포함시키지 않아야 함)
ISP 인터페이스 분리 원칙
클라이언트가 사용하지 않는 메소드에 의존하지 않음

DIP 의존성 역전 원칙
의존 관계는 변화하기 어렵거나 변화가 거의 없는 것과 맺어야 함
변하기 어려운 추상적인 것들을 표현하는 수단으로 추상클래스와 인터페이스가 있음
DIP를 만족하려면 구체적인 클래스보다 추상클래스 또는 인터페이스와 의존관계를 맺도록 설계

기존에는 고수준의 클래스가 저수준의 클래스에 직접적으로 의존하는 방식으로 구현
DIP -> 고수준 클래스와 저수준 클래스 둘 다 추상화에 의존해야 함을 의미
기존의 의존 구조를 뒤집는 것을 역전 Inversion 이라 함

객체가 단일책임을 가지게 하고, 클라이언트마다 다른 인터페이스를 사용하게 함
한 기능의 변경이 미치는 영향을 최소화 함 (기능 변경이 용이)
개방-폐쇄 원칙은 변화되는 부분을 추상화하고 다형성을 이용해 기능확장을 하면서도 기존코드를 수정하지 않도록 함
의존 역전 원칙: 변화되는 부분을 추상화할 수 있도록 도와주는 원칙
리스코프 치환 원칙: 다형성을 도와주는 원칙