TCA Nedir?

The Composable Architecture (TCA), Brandon Williams ve Stephen Celis tarafından geliştirilen, SwiftUI için tasarlanmış bir uygulama mimarisidir. Unidirectional data flow prensibine dayanır ve test edilebilirliği birinci sınıf vatandaş olarak ele alır.

Temel Kavramlar

TCA’nın beş temel bileşeni vardır:

BileşenGörev
StateEkranın tüm verisi
ActionGerçekleşen olaylar
ReducerState + Action → yeni State
StoreRuntime: state tutar, action gönderir
EffectYan etkiler (network, timer vb.)

Basit Bir Örnek: Sayaç

 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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import ComposableArchitecture
import SwiftUI

// 1. State
struct CounterFeature: Reducer {
    struct State: Equatable {
        var count = 0
        var isLoading = false
    }

    // 2. Action
    enum Action {
        case incrementTapped
        case decrementTapped
        case factButtonTapped
        case factResponse(String)
    }

    // 3. Reducer
    var body: some ReducerOf<Self> {
        Reduce { state, action in
            switch action {
            case .incrementTapped:
                state.count += 1
                return .none

            case .decrementTapped:
                state.count -= 1
                return .none

            case .factButtonTapped:
                state.isLoading = true
                return .run { [count = state.count] send in
                    let fact = try await fetchFact(for: count)
                    await send(.factResponse(fact))
                }

            case let .factResponse(fact):
                state.isLoading = false
                // fact'ı state'e kaydet
                return .none
            }
        }
    }
}

View Katmanı

 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
32
struct CounterView: View {
    let store: StoreOf<CounterFeature>

    var body: some View {
        WithViewStore(store, observe: { $0 }) { viewStore in
            VStack(spacing: 20) {
                Text("\(viewStore.count)")
                    .font(.largeTitle.bold())

                HStack {
                    Button("-") {
                        viewStore.send(.decrementTapped)
                    }
                    .buttonStyle(.bordered)

                    Button("+") {
                        viewStore.send(.incrementTapped)
                    }
                    .buttonStyle(.borderedProminent)
                }

                if viewStore.isLoading {
                    ProgressView()
                } else {
                    Button("Fakt Al") {
                        viewStore.send(.factButtonTapped)
                    }
                }
            }
        }
    }
}

Test Yazımı

TCA’nın en güçlü yanı test edilebilirlik:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
@MainActor
final class CounterFeatureTests: XCTestCase {
    func testIncrement() async {
        let store = TestStore(initialState: CounterFeature.State()) {
            CounterFeature()
        }

        await store.send(.incrementTapped) {
            $0.count = 1
        }

        await store.send(.incrementTapped) {
            $0.count = 2
        }

        await store.send(.decrementTapped) {
            $0.count = 1
        }
    }
}

Composability: Feature’ları Birleştirme

TCA’nın adındaki “Composable” özelliği, küçük feature’ları büyük uygulamalarda birleştirmeye yarar:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
struct AppFeature: Reducer {
    struct State {
        var tab1 = CounterFeature.State()
        var tab2 = ProfileFeature.State()
    }

    enum Action {
        case tab1(CounterFeature.Action)
        case tab2(ProfileFeature.Action)
    }

    var body: some ReducerOf<Self> {
        Scope(state: \.tab1, action: /Action.tab1) {
            CounterFeature()
        }
        Scope(state: \.tab2, action: /Action.tab2) {
            ProfileFeature()
        }
    }
}

Sonuç

TCA, büyük ölçekli SwiftUI uygulamaları için güçlü bir mimari sunuyor. Test edilebilirlik, öngörülebilirlik ve bileşen yeniden kullanımı açısından rakipsiz. Öğrenme eğrisi dik olsa da, orta ve büyük projelerde kesinlikle değer.