repository pattern in swift

25
Naoto Kaneko Repository pattern in Swift

Upload: naotybot

Post on 16-Mar-2018

707 views

Category:

Software


3 download

TRANSCRIPT

Page 1: Repository pattern in swift

Naoto Kaneko

Repository pattern in Swift

Page 2: Repository pattern in swift
Page 3: Repository pattern in swift

リポジトリパターン•リポジトリとは、データの取得、保存、削除のためのインターフェイス

• リポジトリを使ってデータにアクセスする。

• メモリ、Realm、APIといったバックエンドを知る必要がなくなる。

Page 4: Repository pattern in swift

ViewController

RecipeRepository

WebAPIRecipeRepository RealmRecipeRepository

query model

params JSON NSPredicate RealmObject

Page 5: Repository pattern in swift

in Swiftprotocol RecipeRepository { func find(id: UInt) -> Recipe? func findAll(query: Query, sort: Sort) -> [Recipe] func save(recipes: [Recipe]) -> Recipe? func delete(recipes: [Recipe]) -> Recipe?}

Page 6: Repository pattern in swift

in Swiftclass MemoryRecipeRepository: RecipeRepository { let recipes = [ Recipe(id: 1, name: “…”), Recipe(id: 2, name: “…”), Recipe(id: 3, name: “…”), ]

func find(id: UInt) -> Recipe? { recipes.filter { $0.id == id }.first }}

Page 7: Repository pattern in swift

問題点•データへのアクセスはだいたい非同期

• クエリやソートはどうやって指定するのか

• RecipeRepository, ChefRepository, UserRepository…と似たようなコードをコピペすることになりそう

Page 8: Repository pattern in swift

リポジトリで非同期処理をあつかう

Page 9: Repository pattern in swift

Promiseprotocol RecipeRepository { func find(id: UInt) -> Task<Void, Recipe, ErrorType> func findAll(query: Query, sort: Sort) -> Task<Void, [Recipe], ErrorType> func save(recipes: [Recipe]) -> Task<Void, Recipe, ErrorType> func delete(recipes: [Recipe]) -> Task<Void, Recipe, ErrorType>}

Page 10: Repository pattern in swift

ViewController

RecipeRepository

WebAPIRecipeRepository RealmRecipeRepository

query model

params JSON NSPredicate RealmObject

Page 11: Repository pattern in swift

ViewController

RecipeRepository

WebAPIRecipeRepository RealmRecipeRepository

Task<Void, Model, Error>

params JSON NSPredicate RealmObject

query

Page 12: Repository pattern in swift

汎用的なクエリを定義する

Page 13: Repository pattern in swift

naoty/AnyQuerylet query = AnyQuery.Equal(key: “name”, value: “naoty”)query.predicate //=> NSPredicate(format: "name == ‘naoty’")query.dictionary //=> ["name": “naoty”]

let sort = AnySort.Ascending(key: “id”)sort.sortDescriptors //=> [NSSortDescriptor(key: "id", ascending: true)]sort.dictionary //=> ["sort": ["id"]]

Page 14: Repository pattern in swift

naoty/AnyQueryprotocol RecipeRepository { func find(id: UInt) -> Task<Void, Recipe, ErrorType> func findAll(query: AnyQuery, sort: AnySort) -> Task<Void, [Recipe], ErrorType> func save(recipes: [Recipe]) -> Task<Void, Recipe, ErrorType> func delete(recipes: [Recipe]) -> Task<Void, Recipe, ErrorType>}

Page 15: Repository pattern in swift

ViewController

RecipeRepository

WebAPIRecipeRepository RealmRecipeRepository

Task<Void, Model, Error>

params JSON NSPredicate RealmObject

query

Page 16: Repository pattern in swift

ViewController

RecipeRepository

WebAPIRecipeRepository RealmRecipeRepository

Task<Void, Model, Error>

[String: AnyObject] JSON NSPredicate RealmObject

AnyQuery

Page 17: Repository pattern in swift

汎用的なリポジトリ型 を定義する

Page 18: Repository pattern in swift

これはできないprotocol Repository { associatedtype Domain

func find(id: Uint) -> Task<Void, Domain, ErrorType>}

let repository: Repository = MemoryRecipeRepository()

Page 19: Repository pattern in swift

型消去struct AnyRepository<DomainType>: Repository { let _find: (id: UInt) -> Task<Void, DomainType, ErrorType>

init<T: Repository where T.Domain == DomainType>(_ repository: T) { _find = repository.find }

func find(id: UInt) -> Task<Void, DomainType, ErrorType> { return _find(id) }}

let repository = AnyRepository(MemoryRecipeRepository())// repository: AnyRepository<Recipe>

Page 20: Repository pattern in swift

ViewController

RecipeRepository

WebAPIRecipeRepository RealmRecipeRepository

Task<Void, Model, Error>

[String: AnyObject] JSON NSPredicate RealmObject

AnyQuery

Page 21: Repository pattern in swift

ViewController

AnyRepository<Recipe>

WebAPIRecipeRepository RealmRecipeRepository

Task<Void, Model, Error>

[String: AnyObject] JSON NSPredicate RealmObject

AnyQuery

Page 22: Repository pattern in swift

実装例• https://github.com/naoty/Playground/tree/master/Repository

Page 23: Repository pattern in swift

応用例: キャッシュ

Page 24: Repository pattern in swift

キャッシュ•リポジトリから取得した結果をキャッシュしたい。

• キャッシュになければ別のリポジトリから取得して、キャッシュに保存した上で返す。

• キャッシュにあれば返す。

• 例: ログインユーザーの取得など

Page 25: Repository pattern in swift

ありがとうございました