Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- clean architecture
- Protocol
- uitableview
- collectionview
- 클린 코드
- tableView
- swiftUI
- MVVM
- SWIFT
- ios
- 스위프트
- Clean Code
- Xcode
- RxCocoa
- uiscrollview
- UITextView
- 리펙토링
- Human interface guide
- combine
- swift documentation
- Observable
- map
- 애니메이션
- UICollectionView
- HIG
- rxswift
- 리팩토링
- ribs
- 리펙터링
- Refactoring
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] Protocol 지향 프로그래밍 (상속보다 프로토콜을 사용하는게 좋은 이유, 인터페이스, DIP, SRP) 본문
Refactoring (리펙토링)
[iOS - swift] Protocol 지향 프로그래밍 (상속보다 프로토콜을 사용하는게 좋은 이유, 인터페이스, DIP, SRP)
jake-kim 2023. 5. 21. 23:59Protocol 지향 프로그래밍이란?
- 특정 기능이 필요하여 기능을 구현하려고 할 때, protocol을 먼저 선언해 놓고 그 protocol을 준수하는 구현체를 생성하여 사용
- 기존 기능을 그대로 사용하면서 새로운 기능을 추가하려고 할 때, 상속보다는 protocol을 사용하여 확장하는 형태로 구현하는 것
Protocol 지향 프로그래밍을 해야하는 이유
- DIP (Dependency Inversion Principle): 소스코드 의존성이 구현체에 의존하지 않고 추상(protocol)에 의존하는 것
- DIP 구체적인 개념은 이전 포스팅 글 참고
- 기능제공(=확장성)
- 확장성이라는 의미는 개발자가 코드를 작성할 때 매우 자연스럽게 사용이 가능
- 사용하는쪽에서 매우 자연스러움 -> 프로토콜을 준수한다 -> 기능을 준수한다
- protocol을 적절히 이용하면 코드를 사용하는쪽에서 관심사의 범위를 좁혀서 의존성을 낮추기가 가능 (ISP 원칙 - 이전 포스팅 글 참고)
- 상속을 사용할때보다 더욱 변경에 유리한 코드 (아래에서 계속 이해하기)
protocol과 상속 차이 이해하기
- 프로토콜은 추상적인 object의 행위를 정의하고 상속은 구현체의 object 자체를 정의
- 특정 기능을 변경했을때 사이드이펙이 적음 - 상속을 사용하면 변경할 때 object 자체를 변경하는 것과 같고, 프로토콜을 변경하면 object의 행위만을 변경하는 것
- 서브 클래스가 수퍼 클래스의 구현 세부사항에 결합되게 되어 수퍼 클래스의 변경이 서브 클래스에 영향을 미칠 수 있음
- 개발자가 수퍼 클래스를 변경하려고 할 때 서브 클래스를 고려해야하는 상황이 발생
- protocol을 이용했을 때, 해당 클래스를 변경하려고 하는 경우 다른 클래스를 고려하지않고 해당 클래스만 고려하여 수정하면 되므로 변경이 더욱 쉬움 (SRP 원칙)
프로토콜로의 리펙토링
- 상속 -> 프로토콜로 변경
- 기능 제공 -> 프로토콜로 만들어서 구현하고, 이를 준수하여 사용하도록 변경
ex) 상속인 경우 - SRP 위반
- Shape클래스만 관심있지만 다른 클래스도 신경써야하는 상황
- 프로토콜은 추상적인 object의 행위를 정의하고 상속은 구현체의 object 자체를 정의하기 때문에, Shape클래스를 변경한다는 것은 object를 변경한다는 것이고 이것은 서브클래스에도 영향을 미침
- Shape에서 draw() 메소드의 이름을 변경하면 서브 클래스들에서 컴파일 에러 발생
- Shape에서 abc()라는 메소드를 추가하면, Circle에서 컴파일 에러가 발생
class Shape {
func draw() {
print("draw shape")
}
}
class Circle: Shape {
override func draw() {
print("draw circle")
}
func abc() {
print("abc")
}
}
class Square: Shape {
override func draw() {
print("draw square")
}
}
class Triangle: Shape {
override func draw() {
print("draw triangle")
}
}
(위 코드를 protocol로 리펙토링)
- 위에서 Shape는 object 자체이므로 변경될 여지가 많았지만, Drawable이라는 프로토콜로 변경됨으로서 새로운 기능을 추가할 땐 또 다른 protocol을 만들어서 준수하게하는 형태가 되므로 나중에 추가하기 쉽고, 수정하기 쉬운 코드가 유지됨
protocol Drawable {
func draw()
}
class Circle: Drawable {
func draw() {
print("Drawing a circle")
}
}
class Square: Drawable {
func draw() {
print("Drawing a square")
}
}
class Triangle: Drawable {
func draw() {
print("Drawing a triangle")
}
}
* 참고
'Refactoring (리펙토링)' 카테고리의 다른 글
[Refactoring] 9-1. 조건부 로직 최소화 (조건문 분해하기) (0) | 2023.05.27 |
---|---|
[Refactoring] 8-5 데이터 조작화 (값을 참조로 바꾸기) (0) | 2023.05.22 |
[Refactoring] 8-4 데이터 조작화 (참조를 값을 바꾸기) (0) | 2023.05.15 |
[Refactoring] 8-3. 데이터 조작화 (파생 변수를 질의 함수로 바꾸기) (0) | 2023.05.14 |
[Refactoring] 8-1. 데이터 조작화 (변수 쪼개기) (0) | 2023.05.12 |
Comments