SlideShare a Scribd company logo
송치원 (곰튀김)
iamchiwon.github.io
만들면서 느껴보는 POP
Realism Programmer
Protocol Oriented Programming
내일 배포 전에
메뉴 기능 하나 없애 주세요
내일 완공 전에
화장실 하나 없애 주세요
내일 배포 전에
메뉴 기능 하나 없애 주세요
VS
Hardware
Software
Software 답게 만들기
쉽게 변경할 수 있게 만들기
Protocol Oriented Programming
If someone is oriented towards or oriented to a particular thing or
person, they are mainly concerned with that thing or person.
oriented
[ ɔːrientɪd ]
ADJECTIVE
Protocol Oriented Programming
Object Oriented Programming
Protocol Basic
Delegate 만들기
protocol JsonFetcherDelegate : AnyObject {


func onFetched(json: String)


}


class JsonFetcher {




weak var delegate: JsonFetcherDelegate?




func fetch(url: String) {


guard let url = URL(string: url) else { return }


DispatchQueue.global(qos: .background).async {


if let data = try? Data(contentsOf: url),


let json = String(data: data, encoding: .utf8) {


self.delegate
?
.
onFetched(json: json)


}


}


}


}
class Main {


var fetcher : JsonFetcher {


let o = JsonFetcher()


o.delegate = self


return o


}




func main() {


fetcher.fetch(url: "
.
.
.
")


}


}


extension Main : JsonFetcherDelegate
{


func onFetched(json: String) {


print(json)


}


}
구현 강제하기
protocol JsonFetcherDelegate : AnyObject {


func onFetched(json: String)


}


class JsonFetcher {




weak var delegate: JsonFetcherDelegate?




func fetch(url: String) {


guard let url = URL(string: url) else { return }


DispatchQueue.global(qos: .background).async {


if let data = try? Data(contentsOf: url),


let json = String(data: data, encoding: .utf8) {


self.delegate
?
.
onFetched(json: json)


}


}


}


}
class Main : JsonFetcherDelegate {


var fetcher : JsonFetcher {


let o = JsonFetcher()


o.delegate = self


return o


}




func main() {


fetcher.fetch(url: "
.
.
.
")


}


}
기본구현 넣기
protocol TypePresentable {


func typeName()
-
>
String


}


extension TypePresentable {


func typeName()
-
>
String {


"(type(of: self))"


}


}
extension Int : TypePresentable {}


extension String : TypePresentable {}


print(42.typeName())


/
/
Int


print("Hello World".typeName())


/
/
String


struct MyStruct : TypePresentable {}


print(MyStruct().typeName())


/
/
MyStruct
추상화 하기
protocol Repository {


func save(data: Data)


func load()
-
>
Data?


}


class MemRepository : Repository {


private var data: Data?




func save(data: Data) {


self.data = data


}




func load()
-
>
Data? {


return data


}




}
class FileRepository : Repository {


private var filePath: URL?




func save(data: Data) {


try! data.write(to: filePath!)


}




func load()
-
>
Data? {


return try? Data(contentsOf: filePath!)


}


}
Repository
MemRepository FileRepository
느슨한 결합
protocol Repository {


func save(data: Data)


func load()
-
>
Data?


}


class MemRepository : Repository {


private var data: Data?




func save(data: Data) {


self.data = data


}




func load()
-
>
Data? {


return data


}




}
class ViewModel {


private let repository: Repository




init(repository: Repository) {


self.repository = repository


}


}


let viewModel = ViewModel(repository: MemRepository())
ViewModel Repository
MemRepository
Q. 다음 중 올바르지 않은 것은?
protocol A {


func a()
-
>
Int


}
protocol B {


func b<T: Numeric>()
-
>
T


}
protocol C<T: Numeric> {


func c()
-
>
T


}
protocol D {


associatedtype T: Numeric


func d()
-
>
T


}
1⃣ 2⃣
3⃣ 4⃣
만들면서 느껴보기
1. 있다 치고
2. 알게 뭐야
TodoViewController
class ToDoViewController: UITableViewController {


let service: ToDoService


@IBAction func onCreateToDo(title: String) {


/
/
TODO: create TODO


tableView.reloadData()


}


}


extension ToDoViewController {


override func tableView(tableView:numberOfRowsInSection:)
-
>
Int {


/
/
TODO: get TODOs count


}


override func tableView(tableView:,cellForRowAt:)
-
>
UITableViewCell {


…


let index = indexPath.row


let item =
/
/
TODO: get TODO


cell.todo = item


return cell


}


}
TodoService
protocol ToDoService {


}
TodoViewController
class ToDoViewController: UITableViewController {


let service: ToDoService


@IBAction func onCreateToDo(title: String) {


service.create(title: title)


tableView.reloadData()


}


}


extension ToDoViewController {


override func tableView(tableView:numberOfRowsInSection:)
-
>
Int {


service.count()


}


override func tableView(tableView:,cellForRowAt:)
-
>
UITableViewCell {


…


let index = indexPath.row


let item = service.item(at: index)


cell.todo = item


return cell


}


}
TodoService
protocol ToDoService {


func create(title: String)


func count()
-
>
Int


func item(at: Int)
-
>
ToDo


}
ToDoItemTableViewCell
class ToDoItemTableViewCell: UITableViewCell {


@IBOutlet var isDone: UISwitch!


@IBOutlet var itemTitle: UILabel!


@IBOutlet var updatedAt: UILabel!




var toggable: Toggable?


@IBAction func onToggle() {


/
/
TODO: toggle done


}


}


Toggable
protocol Toggable {


}
ToDoItemTableViewCell
class ToDoItemTableViewCell: UITableViewCell {


@IBOutlet var isDone: UISwitch!


@IBOutlet var itemTitle: UILabel!


@IBOutlet var updatedAt: UILabel!


var toggable: Toggable?




@IBAction func onToggle() {


toggable
?
.
toggle(withId: todo.id)


}


}


Toggable
protocol Toggable {


func toggle(withId id: String)


}
ToDoServiceImpl
class ToDoServiceImpl: ToDoService {


private var todoItems: [ToDo] = []


func create(title: String) {


let todo = ToDo(id: UUID().uuidString,


title: title,


done: false,


createdAt: Date())


todoItems.append(todo)


}


func count()
-
>
Int {


return todoItems.count


}


func item(at index: Int)
-
>
ToDo {


return todoItems[index]


}


}
extension ToDoServiceImpl : Toggable {


func toggle(withId id: String) {


if let found = todoItems.enumerated()


.first(where: { $0.element.id
=
=
id }) {


let index = found.offset


var todo = found.element


todo.done = !todo.done


todoItems[index] = todo


}


}


}
TodoViewController
typealias ToDoToggableService = ToDoService & Toggable


class ToDoViewController: UITableViewController {


let service: ToDoToggableService


@IBAction func onCreateToDo(title: String) {


service.create(title: title)


tableView.reloadData()


}


}


extension ToDoViewController {


override func tableView(tableView:numberOfRowsInSection:)
-
>
Int {


service.count()


}


override func tableView(tableView:,cellForRowAt:)
-
>
UITableViewCell {


…


let index = indexPath.row


let item = service.item(at: index)


cell.todo = item


cell.toggable = service


return cell


}


}
ToDoServiceImpl
class ToDoServiceImpl: ToDoService {


private let repository: Repository


init(repository: Repository) {


self.repository = repository


/
/
TODO: load todos


}


deinit {


/
/
TODO: save todos


}


.
.
.


}
Repository
protocol Repository {


}
ToDoServiceImpl
class ToDoServiceImpl: ToDoService {


private let repository: Repository


init(repository: Repository) {


self.repository = repository


todoItems = repository.load()


}


deinit {


repository.save(todos: todoItems)


}


.
.
.


}
Repository
protocol Repository {


func load()
-
>
[ToDo]


func save(todos: [ToDo])


}
UserDefaultRepository
class UserDefaultRepository: Repository {


private let TodoKey = "todos"


func load()
-
>
[ToDo] {


guard let json = UserDefaults.standard.string(forKey: TodoKey),


let data = json.data(using: .utf8) else {


return []


}


return (try? JSONDecoder().decode([ToDo].self, from: data))
?
?
[]


}


func save(todos: [ToDo]) {


guard let data = try? JSONEncoder().encode(todos),


let json = String(data: data, encoding: .utf8) else {


return


}


UserDefaults.standard.set(json, forKey: TodoKey)


}


}
Codable
struct ToDo: Identifiable, Codable {


let id: String


let title: String


var done: Bool


let createdAt: Date


}
public protocol Decodable {


init(from decoder: Decoder) throws


}


public protocol Encodable {


func encode(to encoder: Encoder) throws


}


public typealias Codable = Decodable & Encodable
ToDoApp Overview
TodoViewController
UITableViewController
TodoService
TodoServiceImpl
Repository
UserDefaultRepository
Model
Toggable
ToDoItemTableViewCell
https://github.com/iamchiwon/TheToDo
Dependency Injection
class AppDelegate: UIResponder, UIApplicationDelegate {


let container = Container()




func application(application:,didFinishLaunchingWithOptions:)
-
>
Bool {


container.register(Repository.self) { _ in UserDefaultRepository() }


container.register(ToDoToggableService.self) { c in


let repository = c.resolve(Repository.self)!


return ToDoServiceImpl(repository: repository)


}




return true


}


}


func Inject<Service>(_ serviceType: Service.Type)
-
>
Service? {


(UIApplication.shared.delegate as? AppDelegate)
?
.
container.resolve(serviceType)


}


class ToDoListViewController: UITableViewController {


let service: ToDoToggableService = Inject(ToDoToggableService.self)!


.
.
.


}
https:
/
/
github.com/Swinject/Swinject
Q. 다음 중 올바르지 않은 것은?
protocol P {}


protocol PROTOCOL {}


extension PROTOCOL: P {}
protocol C {}


class CLASS {}


extension CLASS: C {}
protocol S {}


struct STRUCT {}


extension STRUCT: S {}
protocol E {}


enum ENUM {}


extension ENUM: E {}
1⃣ 2⃣
3⃣ 4⃣
🤔 OOP 에서는 Protocol 의 역할이 많구나!
😏 그렇다면 Protocol을 더 적극적으로 써보자
🧐 class, struct, enum 전부 다 Protocol 적용하게 하자!
😠 Protocol이 진짜 중요해졌네!!!
😎 그렇다면 이제부터 Protocol을 중심으로 코딩해
🤩 그걸 Protocol Oriented Programming 이라고 하자
의식의 흐름
Summary
1. Protocol 로 할 수 있는 것들 == Protocol을 사용해서 얻는 이점
•Delegate
•구현 강제
•추상화
•느슨한 결합
➡ 유연한 확장
2. 구현 과정에서 구현체 보다 Protocol 을 우선해서 생각하자
3. POP == Protocol을 적극 활용하는 OOP
Oriented Programming

More Related Content

PDF
iOS Modular Architecture with Tuist
PDF
InjectionIII의 Hot Reload를 이용하여 앱 개발을 좀 더 편하게 하기.pdf
PPTX
MVC, MVVM, ReactorKit, VIPER를 거쳐 RIB 정착기
PDF
ReactorKit으로 단방향 반응형 앱 만들기
PDF
생산성을 높여주는 iOS 개발 방법들.pdf
PDF
[TECHCON 2019: MOBILE - Android]3.안드로이드 개발자 로드맵
PDF
DDD와 이벤트소싱
PDF
우아한 모노리스
iOS Modular Architecture with Tuist
InjectionIII의 Hot Reload를 이용하여 앱 개발을 좀 더 편하게 하기.pdf
MVC, MVVM, ReactorKit, VIPER를 거쳐 RIB 정착기
ReactorKit으로 단방향 반응형 앱 만들기
생산성을 높여주는 iOS 개발 방법들.pdf
[TECHCON 2019: MOBILE - Android]3.안드로이드 개발자 로드맵
DDD와 이벤트소싱
우아한 모노리스

What's hot (20)

PDF
Let'Swift 2023 iOS 애플리케이션 개발 생산성 고찰
- 정시 퇴근을 위해 우리는 어떻게 해야할 것인가?
PDF
고려대학교 컴퓨터학과 특강 - 대학생 때 알았더라면 좋았을 것들
PDF
SwiftUI and Combine All the Things
PDF
신입 개발자 생활백서 [개정판]
PDF
SwiftUI와 TCA로 GitHub Search앱 만들기
PDF
A Framework Driven Development
PPTX
Introduction to react_js
PDF
Ingress? That’s So 2020! Introducing the Kubernetes Gateway API
PPTX
Visitor design pattern
PDF
An introduction to Vue.js
PDF
Introduction to React JS
PDF
Gitops Hands On
PDF
Swift in SwiftUI
PDF
Capacitor 1.0 launch
PDF
fastlane을 이용하여 iOS/Mac 앱 관리하기
PDF
The virtual DOM and how react uses it internally
PPTX
Visitor Pattern
PPTX
Android jetpack compose | Declarative UI
PPT
Ionic Framework
PDF
안드로이드 윈도우 마스터 되기
Let'Swift 2023 iOS 애플리케이션 개발 생산성 고찰
- 정시 퇴근을 위해 우리는 어떻게 해야할 것인가?
고려대학교 컴퓨터학과 특강 - 대학생 때 알았더라면 좋았을 것들
SwiftUI and Combine All the Things
신입 개발자 생활백서 [개정판]
SwiftUI와 TCA로 GitHub Search앱 만들기
A Framework Driven Development
Introduction to react_js
Ingress? That’s So 2020! Introducing the Kubernetes Gateway API
Visitor design pattern
An introduction to Vue.js
Introduction to React JS
Gitops Hands On
Swift in SwiftUI
Capacitor 1.0 launch
fastlane을 이용하여 iOS/Mac 앱 관리하기
The virtual DOM and how react uses it internally
Visitor Pattern
Android jetpack compose | Declarative UI
Ionic Framework
안드로이드 윈도우 마스터 되기
Ad

Similar to 20220716_만들면서 느껴보는 POP (20)

PDF
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
PDF
Ji 개발 리뷰 (신림프로그래머)
PDF
Secrets of the JavaScript Ninja - Chapter 12. DOM modification
PDF
20201121 코드 삼분지계
PPTX
파이썬 스터디 15장
PPTX
[Codelab 2017] ReactJS 기초
PDF
SpringCamp 2013 : About Jdk8
PPTX
[스프링 스터디 2일차] 서비스 추상화
PPTX
Eclipse RCP 1/2
PDF
자바8 람다식 소개
PDF
(IT실무교육/국비지원교육/자바/스프링교육추천)#15.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)
PDF
Android ndk jni 설치및 연동
PDF
.NET에서 비동기 프로그래밍 배우기
PPTX
Booting Spring Data REST
PDF
Ryu with OpenFlow 1.3, REST API
PDF
Tensorflow service & Machine Learning
PPTX
Google Protocol buffer
PPTX
불어오는 변화의 바람, From c++98 to c++11, 14
PPTX
Android 기초강좌 애플리캐이션 구조
PPTX
Naver api for android
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
Ji 개발 리뷰 (신림프로그래머)
Secrets of the JavaScript Ninja - Chapter 12. DOM modification
20201121 코드 삼분지계
파이썬 스터디 15장
[Codelab 2017] ReactJS 기초
SpringCamp 2013 : About Jdk8
[스프링 스터디 2일차] 서비스 추상화
Eclipse RCP 1/2
자바8 람다식 소개
(IT실무교육/국비지원교육/자바/스프링교육추천)#15.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)
Android ndk jni 설치및 연동
.NET에서 비동기 프로그래밍 배우기
Booting Spring Data REST
Ryu with OpenFlow 1.3, REST API
Tensorflow service & Machine Learning
Google Protocol buffer
불어오는 변화의 바람, From c++98 to c++11, 14
Android 기초강좌 애플리캐이션 구조
Naver api for android
Ad

More from Chiwon Song (20)

PDF
20250425_AI가 코딩하는 시대에 개발자가 되겠다구요_.pdf
PDF
20250210_AI가 코딩하는시대에 개발자 되기 - Google Slides.pdf
PDF
20240330_고급진 코드를 위한 exception 다루기
PDF
요즘 유행하는 AI 나도 해보자 (feat. CoreML)
PDF
20210812 컴퓨터는 어떻게 동작하는가?
PDF
20200815 inversions
PDF
20191116 custom operators in swift
PDF
[20190601] 직업훈련교사_수업의실행_교안
PPTX
[20190601] 직업훈련교사_수업의실행
PDF
20190330 immutable data
PPTX
20190306 만들면서 배우는 IoT / IoT의 이해
PDF
20181020 advanced higher-order function
PDF
20180721 code defragment
PDF
20180310 functional programming
PDF
20171104 FRP 패러다임
PDF
스크래치로 시작하는 코딩
PPTX
메이커운동과 아두이노
PPTX
아두이노 RC카 만들기
PPTX
[5] 아두이노로 만드는 IoT
PPTX
[4] 아두이노와 인터넷
20250425_AI가 코딩하는 시대에 개발자가 되겠다구요_.pdf
20250210_AI가 코딩하는시대에 개발자 되기 - Google Slides.pdf
20240330_고급진 코드를 위한 exception 다루기
요즘 유행하는 AI 나도 해보자 (feat. CoreML)
20210812 컴퓨터는 어떻게 동작하는가?
20200815 inversions
20191116 custom operators in swift
[20190601] 직업훈련교사_수업의실행_교안
[20190601] 직업훈련교사_수업의실행
20190330 immutable data
20190306 만들면서 배우는 IoT / IoT의 이해
20181020 advanced higher-order function
20180721 code defragment
20180310 functional programming
20171104 FRP 패러다임
스크래치로 시작하는 코딩
메이커운동과 아두이노
아두이노 RC카 만들기
[5] 아두이노로 만드는 IoT
[4] 아두이노와 인터넷

20220716_만들면서 느껴보는 POP

  • 1. 송치원 (곰튀김) iamchiwon.github.io 만들면서 느껴보는 POP Realism Programmer Protocol Oriented Programming
  • 2. 내일 배포 전에 메뉴 기능 하나 없애 주세요
  • 3. 내일 완공 전에 화장실 하나 없애 주세요 내일 배포 전에 메뉴 기능 하나 없애 주세요 VS Hardware Software
  • 4. Software 답게 만들기 쉽게 변경할 수 있게 만들기
  • 5. Protocol Oriented Programming If someone is oriented towards or oriented to a particular thing or person, they are mainly concerned with that thing or person. oriented [ ɔːrientɪd ] ADJECTIVE
  • 9. Delegate 만들기 protocol JsonFetcherDelegate : AnyObject { func onFetched(json: String) } class JsonFetcher { weak var delegate: JsonFetcherDelegate? func fetch(url: String) { guard let url = URL(string: url) else { return } DispatchQueue.global(qos: .background).async { if let data = try? Data(contentsOf: url), let json = String(data: data, encoding: .utf8) { self.delegate ? . onFetched(json: json) } } } } class Main { var fetcher : JsonFetcher { let o = JsonFetcher() o.delegate = self return o } func main() { fetcher.fetch(url: " . . . ") } } extension Main : JsonFetcherDelegate { func onFetched(json: String) { print(json) } }
  • 10. 구현 강제하기 protocol JsonFetcherDelegate : AnyObject { func onFetched(json: String) } class JsonFetcher { weak var delegate: JsonFetcherDelegate? func fetch(url: String) { guard let url = URL(string: url) else { return } DispatchQueue.global(qos: .background).async { if let data = try? Data(contentsOf: url), let json = String(data: data, encoding: .utf8) { self.delegate ? . onFetched(json: json) } } } } class Main : JsonFetcherDelegate { var fetcher : JsonFetcher { let o = JsonFetcher() o.delegate = self return o } func main() { fetcher.fetch(url: " . . . ") } }
  • 11. 기본구현 넣기 protocol TypePresentable { func typeName() - > String } extension TypePresentable { func typeName() - > String { "(type(of: self))" } } extension Int : TypePresentable {} extension String : TypePresentable {} print(42.typeName()) / / Int print("Hello World".typeName()) / / String struct MyStruct : TypePresentable {} print(MyStruct().typeName()) / / MyStruct
  • 12. 추상화 하기 protocol Repository { func save(data: Data) func load() - > Data? } class MemRepository : Repository { private var data: Data? func save(data: Data) { self.data = data } func load() - > Data? { return data } } class FileRepository : Repository { private var filePath: URL? func save(data: Data) { try! data.write(to: filePath!) } func load() - > Data? { return try? Data(contentsOf: filePath!) } } Repository MemRepository FileRepository
  • 13. 느슨한 결합 protocol Repository { func save(data: Data) func load() - > Data? } class MemRepository : Repository { private var data: Data? func save(data: Data) { self.data = data } func load() - > Data? { return data } } class ViewModel { private let repository: Repository init(repository: Repository) { self.repository = repository } } let viewModel = ViewModel(repository: MemRepository()) ViewModel Repository MemRepository
  • 14. Q. 다음 중 올바르지 않은 것은? protocol A { func a() - > Int } protocol B { func b<T: Numeric>() - > T } protocol C<T: Numeric> { func c() - > T } protocol D { associatedtype T: Numeric func d() - > T } 1⃣ 2⃣ 3⃣ 4⃣
  • 15. 만들면서 느껴보기 1. 있다 치고 2. 알게 뭐야
  • 16. TodoViewController class ToDoViewController: UITableViewController { let service: ToDoService @IBAction func onCreateToDo(title: String) { / / TODO: create TODO tableView.reloadData() } } extension ToDoViewController { override func tableView(tableView:numberOfRowsInSection:) - > Int { / / TODO: get TODOs count } override func tableView(tableView:,cellForRowAt:) - > UITableViewCell { … let index = indexPath.row let item = / / TODO: get TODO cell.todo = item return cell } } TodoService protocol ToDoService { }
  • 17. TodoViewController class ToDoViewController: UITableViewController { let service: ToDoService @IBAction func onCreateToDo(title: String) { service.create(title: title) tableView.reloadData() } } extension ToDoViewController { override func tableView(tableView:numberOfRowsInSection:) - > Int { service.count() } override func tableView(tableView:,cellForRowAt:) - > UITableViewCell { … let index = indexPath.row let item = service.item(at: index) cell.todo = item return cell } } TodoService protocol ToDoService { func create(title: String) func count() - > Int func item(at: Int) - > ToDo }
  • 18. ToDoItemTableViewCell class ToDoItemTableViewCell: UITableViewCell { @IBOutlet var isDone: UISwitch! @IBOutlet var itemTitle: UILabel! @IBOutlet var updatedAt: UILabel! var toggable: Toggable? @IBAction func onToggle() { / / TODO: toggle done } } Toggable protocol Toggable { }
  • 19. ToDoItemTableViewCell class ToDoItemTableViewCell: UITableViewCell { @IBOutlet var isDone: UISwitch! @IBOutlet var itemTitle: UILabel! @IBOutlet var updatedAt: UILabel! var toggable: Toggable? @IBAction func onToggle() { toggable ? . toggle(withId: todo.id) } } Toggable protocol Toggable { func toggle(withId id: String) }
  • 20. ToDoServiceImpl class ToDoServiceImpl: ToDoService { private var todoItems: [ToDo] = [] func create(title: String) { let todo = ToDo(id: UUID().uuidString, title: title, done: false, createdAt: Date()) todoItems.append(todo) } func count() - > Int { return todoItems.count } func item(at index: Int) - > ToDo { return todoItems[index] } } extension ToDoServiceImpl : Toggable { func toggle(withId id: String) { if let found = todoItems.enumerated() .first(where: { $0.element.id = = id }) { let index = found.offset var todo = found.element todo.done = !todo.done todoItems[index] = todo } } }
  • 21. TodoViewController typealias ToDoToggableService = ToDoService & Toggable class ToDoViewController: UITableViewController { let service: ToDoToggableService @IBAction func onCreateToDo(title: String) { service.create(title: title) tableView.reloadData() } } extension ToDoViewController { override func tableView(tableView:numberOfRowsInSection:) - > Int { service.count() } override func tableView(tableView:,cellForRowAt:) - > UITableViewCell { … let index = indexPath.row let item = service.item(at: index) cell.todo = item cell.toggable = service return cell } }
  • 22. ToDoServiceImpl class ToDoServiceImpl: ToDoService { private let repository: Repository init(repository: Repository) { self.repository = repository / / TODO: load todos } deinit { / / TODO: save todos } . . . } Repository protocol Repository { }
  • 23. ToDoServiceImpl class ToDoServiceImpl: ToDoService { private let repository: Repository init(repository: Repository) { self.repository = repository todoItems = repository.load() } deinit { repository.save(todos: todoItems) } . . . } Repository protocol Repository { func load() - > [ToDo] func save(todos: [ToDo]) }
  • 24. UserDefaultRepository class UserDefaultRepository: Repository { private let TodoKey = "todos" func load() - > [ToDo] { guard let json = UserDefaults.standard.string(forKey: TodoKey), let data = json.data(using: .utf8) else { return [] } return (try? JSONDecoder().decode([ToDo].self, from: data)) ? ? [] } func save(todos: [ToDo]) { guard let data = try? JSONEncoder().encode(todos), let json = String(data: data, encoding: .utf8) else { return } UserDefaults.standard.set(json, forKey: TodoKey) } }
  • 25. Codable struct ToDo: Identifiable, Codable { let id: String let title: String var done: Bool let createdAt: Date } public protocol Decodable { init(from decoder: Decoder) throws } public protocol Encodable { func encode(to encoder: Encoder) throws } public typealias Codable = Decodable & Encodable
  • 27. Dependency Injection class AppDelegate: UIResponder, UIApplicationDelegate { let container = Container() func application(application:,didFinishLaunchingWithOptions:) - > Bool { container.register(Repository.self) { _ in UserDefaultRepository() } container.register(ToDoToggableService.self) { c in let repository = c.resolve(Repository.self)! return ToDoServiceImpl(repository: repository) } return true } } func Inject<Service>(_ serviceType: Service.Type) - > Service? { (UIApplication.shared.delegate as? AppDelegate) ? . container.resolve(serviceType) } class ToDoListViewController: UITableViewController { let service: ToDoToggableService = Inject(ToDoToggableService.self)! . . . } https: / / github.com/Swinject/Swinject
  • 28. Q. 다음 중 올바르지 않은 것은? protocol P {} protocol PROTOCOL {} extension PROTOCOL: P {} protocol C {} class CLASS {} extension CLASS: C {} protocol S {} struct STRUCT {} extension STRUCT: S {} protocol E {} enum ENUM {} extension ENUM: E {} 1⃣ 2⃣ 3⃣ 4⃣
  • 29. 🤔 OOP 에서는 Protocol 의 역할이 많구나! 😏 그렇다면 Protocol을 더 적극적으로 써보자 🧐 class, struct, enum 전부 다 Protocol 적용하게 하자! 😠 Protocol이 진짜 중요해졌네!!! 😎 그렇다면 이제부터 Protocol을 중심으로 코딩해 🤩 그걸 Protocol Oriented Programming 이라고 하자 의식의 흐름
  • 30. Summary 1. Protocol 로 할 수 있는 것들 == Protocol을 사용해서 얻는 이점 •Delegate •구현 강제 •추상화 •느슨한 결합 ➡ 유연한 확장 2. 구현 과정에서 구현체 보다 Protocol 을 우선해서 생각하자 3. POP == Protocol을 적극 활용하는 OOP Oriented Programming