객체지향 5원칙 (SOLID)
- 단일 책임 원칙 (Single Responsibility principle)
- 개방 폐쇄 원칙 (Open Close Principle)
- 리스코프 치환 원칙 (Liscov Substitution Principle)
- 인터페이스 분리 원칙 (Interface Sergregation Principle)
- 의존성 역전 원칙 (Dependency Inversion Principle)
# ISP (Interface Segregation) 인터페이스 분리 원칙
클라이언트는 자신이 사용하지 않는 메서드에 의존 관계를 맺으면 안된다.
즉, 객체는 자신이 사용하는 메서드에만 의존해야한다는 법칙이다. 객체가 사용하지 않는 메서드를 의존해서는 안된다는 의미이기도 하다.
인터페이스는 지나치게 광법위하거나 지나치게 많은 기능을 구현해서는 안되고, 그 인터페이스를 사용하는 객체를 기준으로 잘게 분리되어야한다고 한다.
보통 인터페이스라고 이야기하는데 swift관점에서 보자면 protocol을 의미한다.
- 하나의 통상적인 인터페이스보다는 차라리 여러 개의 세부적인 (구체적인) 인터페이스 낫다.
- 인터페이스는 해당 인터페이스를 사용하는 클라이언트를 기준으로 잘게 분리되어야 한다.
- 각 클라이언트가 필요로 하는 인터페이스들을 분리함으로써, 클라이언트가 사용하지 않는 인터페이스에 변경이 발생하더라도 영향을 받지 않도록 만들어야 하는 것이 핵심이다.
단일 책임 원칙(SRP)과 인터페이스 분리 원칙(ISP)은 같은 문제에 대한 두 가지 다른 해결책으로 볼 수 있다. 실제 프로젝트를 요구사항과 설계자 취향에 따라 단일 책임 원칙이나 인터페이스 분리 원칙 중 하나를 선택하여 설계할 수 있다.
이 두 원칙은 비슷한 개념을 공유하지만 객체 지향 설계에서 상호 보완적으로 사용될 수 있다.
- SRP는 각 클래스가 자체적으로 변경되어야 하는 이유가 하나여야 한다.
- ISP는 인터페이스를 분리하여 클라이언트가 필요로 하는 기능만 사용하도록 한다.
# 인터페이스 최소주의 원칙
- ISP를 이야기할 때 함께 등장하는 원칙 중 하나로 인터페이스 최소주의 원칙이 있다. 이것은 인터페이스를 통해 메서드를 외부에 제공할 때는 최소한의 메서드만 제공하라는 것이다.
# 예시 코드
-
ISP원칙에 위배한 코드
- 위의 코드를 보게되면 Vehicle프로토콜에 go와 fly 메서드를 정의해 놓았다. 하지만 프로토콜을 채택했다면 프로토콜에서 정의한 메서드는 반드시 정의해 줘야한다. 그렇기에 Car클래스에서는 fly메서드가 필요가 없지만 정의를 하게되어 불필요한 추가를 하게된다.
-
ISP원칙에 준수한 코드
- 그래서 Vehicle프로토콜 안에 정의했던 메서드를 더 잘게 나누어서 정의했다. Move프로토콜과 Fly프로토콜로 나누어 각자에게 필요한 프로토콜을 채택해서 사용해 불필요한 메서드를 정의하지 않는 ISP원칙에 맞게 구현하게 된다.
# DIP (Dependency Inversion) 의존 역전 원칙
고차원 모듈은 저차원 모듈에 의존하면 안된다. 이 두 모듈 모두 다른 추상화된 것에 의존해야 한다.
- 고차원 모듈 : 일반적으로 더 큰 규모의 기능을 수행하는 클래스, 패키지 등을 의미 즉, 사용자 인터페이스와 관련된 작업을 하는 controller나 비즈니스 로직을 처리하는 Service 계층이 고차원 모듈에 속한다고 볼 수 있다.
- 저차원 모듈 : 고차원 모듈에 정의한 기능을 구체적으로 구현하는 클래스 등을 의미. 주로 데이터베이스 접근 객체 클래스나 파일 처리를 위한 클래 등이 저차원 모듈에 손한다고 할 수 있다.
- 의존성 : 의존성은 특정 클래스가 기능을 수행 할 때, 다른 클래스의 기능이 필요한 경우를 말한다.
의존 관계를 맺을 때, 변하기 쉬운 것 (구체적인 것) 보다는 변하기 어려운 것 (추상적인 것)에 의존해야 한다 그래서 구체화된 클래스에 의존하기 보다는 추상 클래스나 인터페이스에 의존해야 한다.
# 예시코드
- DIP원칙에 위배한 코드
- 현재 Calculate클래스 내에서 외부 클래스 함수를 정의하고 있기에 의존성이 강하게 주입되고 있어 외부의 클래스에서 수정이 이루어질 경우 Calculate클래스 내부에서 add, sub클래스 인스턴스를 참조하는 값들에도 에러가 발생한다.
- DIP원칙에 준수한 코드
- 이번에는 직접 외부의 클래스를 의존하지 않고 Operation클래스 내부에 프로토콜인 CalculatorProtocol을 인스턴스 생성을 하여 추상 클래스에 의존하게 만들어 다른 외부 클래스가 변하더라도 Operation클래스에는 아무런 변화가 없어 의존성을 낮출 수 있다.
틸 구경 왔는데 쏠리드네 하..🥲라고 썼지만 그래도 이거 읽으면서 공부해야겠다