TCAで実現する、ルパン一味のような洗練されたアプリ設計
pointfreeco/swift-composable-architecture
このライブラリは、Swift Composable Architecture (TCA) と呼ばれ、ルパン一味が完璧な計画を立ててお宝を盗むように、アプリのロジックを整理し、一貫性のある、理解しやすい方法で構築するためのものです。
ルパンは常に、次の動きを完璧に予測していますよね。TCAは、それに似ています。
予測可能な状態管理
アプリの状態(ボタンが押されたか、データが読み込まれたかなど)が、いつ、どのように変わるかが明確になります。これにより、バグを未然に防ぎ、デバッグがずっと楽になります。
テストのしやすさ
銭形警部が、ルパンの行動を再現して罠を仕掛けるように、TCAではアプリの各部品の動作を簡単にテストできます。これにより、あなたのコードが、期待通りに動くことを保証できます。
再利用性とコンポジション
ルパンがいろんな道具を使い分けてお宝を盗むように、TCAでは小さな部品(コンポーネント)を組み合わせて、大きな機能を作り上げることができます。これにより、コードの再利用性が高まり、開発効率が向上します。
TCAをあなたのプロジェクトに導入するのは、ルパンが厳重な警備を突破するより簡単です。
Xcodeを開き、プロジェクトを選択します。
File > Add Packages... を選択します。
検索バーに以下のURLを貼り付けます。
https://github.com/pointfreeco/swift-composable-architecture.git
指示に従って追加すれば完了です。
ルパンがお宝を盗むとき、彼は必ず「計画」を立てます。TCAも同じで、「State」「Action」「Reducer」「ViewStore」という4つの要素で、その計画を立てます。
ここでは、シンプルなカウンターアプリを例に見ていきましょう。
アプリの状態、つまりデータです。カウンターアプリなら、現在の数値がこれにあたります。
struct CounterState: Equatable {
var count = 0
}
ユーザーが行う操作や、システム内で発生するイベントです。ボタンをタップする、データが読み込まれるなど。
enum CounterAction: Equatable {
case incrementButtonTapped
case decrementButtonTapped
}
StateとActionを受け取り、新しいStateを計算して返します。ここで、ロジックのすべてが処理されます。
let counterReducer = Reducer<CounterState, CounterAction, Void> { state, action, _ in
switch action {
case .incrementButtonTapped:
state.count += 1
return .none
case .decrementButtonTapped:
state.count -= 1
return .none
}
}
Reducerのロジックに従って、StateをViewに反映させます。ViewからActionをReducerに送る役割も担います。
import ComposableArchitecture
import SwiftUI
struct CounterView: View {
let store: Store<CounterState, CounterAction>
var body: some View {
WithViewStore(self.store) { viewStore in
VStack {
Text("\(viewStore.count)")
.font(.largeTitle)
HStack {
Button("-") {
viewStore.send(.decrementButtonTapped)
}
Button("+") {
viewStore.send(.incrementButtonTapped)
}
}
}
}
}
}
このように、TCAを使えば、まるでルパン一味が計画を練るように、アプリのロジックを整理し、予測可能で、テストしやすいコードを構築できます。