SOLID 원칙
SOLID 원칙: 객체 지향 설계의 5대 핵심 원칙
S - 단일 책임 원칙(Single Resposibility Principle, SRP)
- 정의: 클래스는 하나의 책임만 가져야 한다.
- 클래스 뿐만 아니라 더 큰 레벨 혹은 더 작은 레벨 모두 적용된다. 모듈, 패키지, 함수, 메서드 등등
- 하나의 책임만을 가지는 것은 변경의 이유가 하나라는 의미!
- 책임이 여러개라면 변경의 이유도 여러가지일 수 있기 때문에
- 작게 쪼개라는 것과 한가지 책임만을 갖도록 나누는 것은 다름
O - 개방-폐쇄 원칙(Open-Closed Priciple, OCP)
- 정의: 확장에는 열려 있어야 하고, 수정에는 닫혀 있어야 한다.
- 새로운 요구사항이 생겼을 때 기존 코드를 수정하지 않고 새로운 코드를 추가할 수 있어야 한다는 의미
- 즉, 새로운 기능이 추가될 때 기존 코드와 충돌 없이 확장이 가능해야 한다는 의미
- 예를 들어, enum 타입에 새로운 기능의 확장을 위해 케이스를 추가해야 한다면 모든 switch문에 케이스를 추가해야 하고 기존 코드 수정이 불가피하므로 OCP를 위반한 것
- 프로토콜과 같은 추상화 인터페이스를 통해 풀어낼 수 있음
L - 리스코프 치환 원칙(Liskov Substitution Principle, LSP)
- 정의: 서브타입은 언제나 부모 타입으로 치환 가능해야 한다.
- 부모 타입을 기대하는 코드에서 자식 타입을 할당했을 때 의도대로 동작해야 한다는 뜻
- 즉 다형성을 보장하기 위한 원칙!
- 추상 타입의 규칙(행동)을 잘 지킬 수 있어야 함
I - 인터페이스 분리 원칙(Interface Segregation Principle, ISP)
- 정의: 클라이언트는 자신이 사용하지 않는 메서드에 의존하지 않아야 한다.
- 하나의 인터페이스(프로토콜)에 너무 많은 기능과 역할을 몰아넣음으로써, 인터페이스 구현체가 불필요한 구현을 강제로 할 수 밖에 없는 것을 방지하자는 의미
- 인터페이스의 일부 메서드만 수정해도 모든 구현체가 영향을 받기 때문에, 최대한 필요한 기능만큼 작게 쪼개서 불필요한 의존을 줄여야 함
D - 의존 역전 원칙(Dependency Inversion Principle, DIP)
- 정의: 고수준 모듈은 저수준 모듈에 의존하면 안되고, 둘 다 추상화에 의존해야 한다.
- 고수준 모듈(High-level module): 비즈니스 로직, 도메인 규칙 등 앱이 무엇을 해야 하는지를 결정하는 수준의 코드들
- 저수준 모듈(Low-level module): 구체적인 기술 구현체로, 앱이 그것을 어떻게 하는지를 담당하며 URLSession, CoreData 등과 같은 것
- 추상화: 고수준과 저수준을 이어주는 계약으로, Swift에서는 프로토콜
- 고수준 모듈 ───▶ 추상화 ◀── 저수준 모듈
- 즉, 의존 방향을 역전시켜서 고수준 모듈(비즈니스로직)이 저수준 모듈(구현 세부사항)을 알 필요가 없다는 뜻
- 클린아키텍처에서 UseCase -> Repository -> DataSource 구조가 전형적인 DIP 구현 사례
- “역전”이라는 표현은 원래 흐름을 거스르는 것
- 이런 원칙을 따르지 않고 구현한다면 뷰모델에서 바로 UserDefaults에 저장하거나 바로 URLSession을 호출할테지만. 추상화를 통해 이 흐름을 역전 시켜 고수준 모듈이 더이상 저수준 구현을 모르도록 설계하는 것