검색결과 리스트
글
[swift1.2] Swift 프로토콜 지향 프로그래밍
Swift
2015. 8. 6. 00:57
WWDC 2015 세션중 "Protocol-Oriented Programming in Swift" 라는 흥미로운 세션이 있습니다. 애플에서 Standard Library 그룹의 리더를 맡고 있는 Dave Abrahams 라는 분이 발표한 세션입니다. 세션에서 제공하는 슬라이드와 InfoQ에서 이 세션을 정리한 아티클을 바탕으로 내용을 요약했습니다.
클래스는 멋집니다!
다음과 같은 멋진 특징들을 제공하지요.
- 캡슐화 (Encapsulation)
- 접근제어 (Access Cotrol)
- 추상화 (Abstraction)
- 네임스페이스 (Namespace)
- 풍부한 문법 (Epressive Syntax)
- 확장성 (Extensibility)
그런데...
구조체로도 다 할수 있습니다.
클래스는 훌륭합니다.타입은 훌륭합니다!
사실 위 특징들은 모든 타입들의 특징이며 클래스는 그것을 구현하는 하나의 방법에 불과합니다. 그렇다면 클래스 사용으로 인한 단점은 무엇이 있을까요?
1. 암묵적인 참조(Reference) 공유
- 두 객체가 동시에 어떤 객체를 참조하는 경우, 서로 그 사실을 모른채 그 객체를 변경할 수 있습니다.
- 참조 공유를 방지하기 위해 참조하는 객체를 복사할 수 있지만, 그렇게 하면 효율성이 나빠집니다.
- 참조를 공유하는 객체에 Race Conditions 이 발생할 수도 있습니다.
- Lock을 사용하여 레이스 컨디션을 방지할수 있지만 효율성은 더 나빠집니다.
- Lock을 잘못 사용하면 Deadlock 상태에 빠질 수 있습니다.
- 잦은 Lock 사용은 코드를 복잡하게 합니다.
- 복잡성은 더 많은 버그를 유발합니다.
Values Don't Share. (That's a good thing)
2. 상속 (비지니스에 관한 모든 것을 가지고 있습니다.)
- 슈퍼 클래스를 하나 밖에 가질수 없기 때문에, 초기에 잘 선택해야합니다.
- 슈퍼 클래스를 나중에 변경하는 것은 매우 어렵습니다.
- 슈퍼클래스가 갖는 모든 저장속성은 서브클래스에도 (강제적으로) 상속됩니다.
- 초기화 처리가 복잡해집니다.
- 수퍼클래스의 불변성을 깨뜨리지 않을수 없게됩니다.
- 언제 무엇을, 어떻게 재정의해야 하는지 (수퍼 클래스에 대해서)알아야 합니다.
More and more, we promote delegation.
3. 타입관계를 잃어버립니다.(Lost Type Relationships.)
- 추상 수퍼클래스와 서브클래스의 구현코드가 함께 존재하게 됩니다.
서브클래스 메소드에 접근하기 위해 수퍼클래스를 서브클래스로 다운캐스팅하면서 타입관계를 잃게됩니다.
이진탐색 클래스 모델 Ordered 정의
class Ordered {
func precedes(other: Ordered) -> Bool { fatalError("메소드를 구현해주세요.") }
}
class Number:Ordered {
var value:Double = 0
override func precedes(other: Ordered) -> Bool {
return value < (other as! Number).value //
}
}
func binarySearch(sortedKeys: [Ordered], forkey k: Ordered) -> Int {
var lo = 0
var hi = sortedKeys.count
while hi > lo {
let mid = lo + (hi - lo) / 2
if sortedKeys[mid].precedes(k) { lo = mid + 1 }
else { hi = mid }
}
return lo
}
as! ASubclass 는 타입 관계를 잃어버렸다는 신호
대부분 추상화를 위해 클래스를 사용하기 때문이다.
4. 좋은 추상화 메커니즘이란?
- Value type을 지원합니다.(클래스 외에도)
- 정적 타입관계를 지원합니다. (동적 디스패치 외에도)
- 큰 덩어리로 뭉치지 않아야합니다.
- Retroactive 모델링을 지원합니다.
- 모델에 인스턴스 데이터를 강요하지 않아야 합니다.
- 모델에 초기화의 부담이 없어야 합니다.
- 무엇을 구현해야 하는지 명확해야 합니다.
Swift는 프로토콜 지향 프로그래밍 언어!
5. 프로토콜 지향 프로그래밍
- Swift에서 새롭게 추상화를 생각할 때 첫 번째 포인트는 프로토콜!
이진탐색 프로토콜 모델 Ordered 변경해보겠습니다.
protocol Ordered {
func precedes(other:Self) -> Bool
}
struct Number : Ordered {
var value:Double = 0
func precedes(other:Number) -> Bool {
return self.value < other.value
}
}
이진탐색 함수를 정의합니다.
func binarySearch<T:Ordered>(sortedKeys:[T], forKey k: T) -> Int {
var lo = 0
var hi = sortedKeys.count
while hi > lo {
let mid = lo + (hi-lo)/2
if sortedKeys[mid].precedes(k) { lo = mid + 1 }
else { hi = mid }
}
return lo
}
Int 배열에 이진탐색 함수를 적용해 보겠습니다.
- 먼저 Int가 프로토콜 Ordered를 구현해야합니다.
// Int형 Ordered 프로토콜 구현하기
extension Int:Ordered {
func precedes(other: Int) -> Bool {
return self < other
}
}
- Int 배열에 이진탐색을 적용합니다.
// 1. 키 정렬
var keys = [10, 30, 1, 4, 5, 6, 7, 8, 55, 20]
var sortedKeys = keys.sorted { $0 < $1 }
// sortedKeys: [1, 4, 5, 6, 7, 8, 10, 20, 30, 55]
// 2. 찾을 키
var searchKey = 30
// 키 30의 index는 8.
// 3. 이진탐색
var searchIndex = binarySearch(sortedKeys, forkey: searchKey)
// searchIndex: 8
Number 배열에도 이진탐색을 적용해보겠습니다.
// 1. 정렬된 Number 배열 생성
var numbers = sortedKeys.map { return Number(value: Double($0)) }
// numbers: [1.0, 4.0, 5.0, 6.0, 7.0, 8.0, 10.0, 20.0, 30.0, 55.0]
// 2. 찾을 키
var keyToSearch = 5.0
// 3. 이진탐색
var index = binarySearch(numbers, forkey: Number(value: keyToSearch))
// index: 2
프로토콜을 사용하면, 커스텀 Number 구조체 뿐만 아니라 기존 타입에도 이진탐색을 쉽게 적용할 수 있음을 알 수 있습니다.
'Swift' 카테고리의 다른 글
| [swift2] Xcode7 beta6 Swift 언어 변경사항 (0) | 2015.08.27 |
|---|---|
| [swift2] Xcode7 beta5 Swift 언어 변경사항 (0) | 2015.08.14 |
| [swift1.2] Swift 프로토콜 지향 프로그래밍 (0) | 2015.08.06 |
| [swift] 문자열과 문자 -1 (Strings and Characters) (0) | 2015.08.01 |
| [swift2] Xcode7 beta4 Swift 언어 변경사항 (0) | 2015.07.30 |
| [swift] 성능향상 시키기 - 다이나믹 디스패치를 최소화 (0) | 2015.07.16 |