좋은 객체지향 설계의 5가지 원칙
: 클린코드로 유명한 로버트 마틴이 정리한 원칙이다.
1. SRP(Single Responsibility Principle) : 단일 책임 원칙
- 한 클래스는 하나의 책임을 가져야 함
- 하나의 책임이란 기준이 모호하다 → 변경이 있을 때 파급효과가 적으면 SRP를 따른 것으로 생각한다.
2. OCP(Open Closed) : 개방 폐쇄 원칙
- 확장에는 열려있으나 변경에는 닫혀있어야 한다.
- 클라이언트가 인터페이스에 의존하면, 인터페이스 구현체가 변경되거나 확장돼도 클라이언트에 영향을 주지 않는다.
- 확장은 인터페이스를 통해 자유롭게 열려있되, 인터페이스를 의존하는 클라이언트는 변경에 닫혀있어야 한단 의미
- 다형성을 생각해보면 됨.
3. LSP(Liskov Substitution) : 리스코프 치환 원칙
- 객체는 프로그램 정확성을 깨트리지 않으면서 하위 타입 인스턴스로 바꿀 수 있어야 한다.
- 인터페이스 규약을 지켜 다형성을 활용해야 한다는 의미
- 예를들어, 자동차 인터페이스의 엑셀을 밟으면 속도가 증가해야하는데, 뒤로가게 구현하면 LSP 원칙을 위반한 것이다.
4. ISP(Interface Segregation) : 인터페이스 분리 원칙
- 특정 클라이언트를 위한 인터페이스 여러개가 범용 인터페이스 하나보다 더 나음
- 자동차 인터페이스 → 운전, 정비 인터페이스로 분리
- 사용자 클라이언트 → 운전자, 정비사 클라이언트로 분리
- 분리하면 서로 영향을 주지 않고, 인터페이스가 명확해지고 대체가능성이 높아진다.
5. DIP (Dependency Inversion) : 의존관계 역전 원칙
- 추상화에 의존해야지 구체화에 의존하면 안됨 (= 역할에 의존해야 한다.)
- 클라이언트가 클래스가 아닌 인터페이스에 의존해야 한다.
- 로미오역할이 어떤 배우여야 된다는것은 안된다. 대체가 안되면 안된다!
✔︎ 정리
- 객체지향의 핵심은 다형성이다.
- 다형성만으로는 OCP, DIP를 지킬 수 없다.
- 따라서, 무언가 더 필요한데 이는 스프링에서 지원한다.
- 스프링은 DI (의존관계, 의존성 주입) 과 DI 컨테이너를 제공함으로써 OCP와 DIP를 가능하게 지원한다.
- 모든 설계에 역할과 구현을 분리해야 한다.
역할과 구현을 분리?
: 역할과 구현으로 구분하면 세상이 단순해지고 유연해지며, 변경도 편리해진다.
- 장점
- 클라이언트는 대상의 역할(인터페이스)만 알면 된다.
- 클라이언트는 구현대상의 내부구조를 몰라도 된다.
- 클라이언트는 구현대상의 내부구조가 변경돼도 영향을 받지 않는다.
- 클라이언트는 구현대상 자체를 변경해도 영향을 받지 않는다.
- 자바언어의 다형성을 활용
- 역할 = 인터페이스
- 구현 = 인터페이스를 구현한 클래스, 구현 객체
- 객체를 설계할 때 역할과 구현을 명확히 분리
- 객체 설계시 역할(인터페이스)을 먼저 부여하고, 그 역할을 수행하는 구현 객체 만들기
다형성의 본질
- 인터페이스를 구현한 객체 인스턴스를 실행시점에 유연하게 변경
- 다형성의 본질을 이해하려면 협력이라는 객체사이의 관계에서 시작해야함
- 클라이언트를 변경하지 않고, 서버의 구현 기능을 유연하게 변경할 수 있다.