mcpField
S
swift-architecture

swift-architecture

github.com/dpearson2699開発1.2k3.1k 回インストール13 週間前に更新
リポジトリ

swift-architecture について

swift-architecture は、状態や依存関係、副作用などの具体的な要件に基づき、Swift アプリのアーキテクチャ選択と移行を支援するスキルです。単純な SwiftUI 機能では MV を起点とし、複雑さに応じた段階的な拡張方法を示します。

主な機能

  1. 01実際の複雑さに応じたパターン選択
  2. 02SwiftUI の出発点として MV を採用
  3. 03状態所有者と依存境界の明確化
  4. 04機能単位の段階的な移行計画
  5. 05状態と依存失敗のテストによる検証

活用シーン

  1. 01SwiftUI 機能のアーキテクチャ選定
  2. 02MV から TCA へ進む時期の判断
  3. 03既存機能境界の段階的な移行
  4. 04依存性注入と状態遷移の設計確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/dpearson2699/swift-ios-skills --skill swift-architecture

インストール後、Claude Code で/swift-architectureを入力して読み込まれたか確認します。

同梱ファイルevals/evals.jsonreferences/architecture-patterns.md

詳細

Swift アーキテクチャ

状態の所有者、依存関係、副作用、テストを明確にできる最小限のアーキテクチャを選択します。新しい SwiftUI 機能では MV を既定とし、実際に複雑さが確認された場合にのみ、より高度なパターンへ移行します。

目次

適用範囲の境界

このスキルでは、パターンの選択、モジュール境界、依存関係の方向、移行戦略、アーキテクチャレベルでのテスト境界を扱います。SwiftUI のプロパティラッパーの接続やビューの構成については swiftui-patterns に、ナビゲーション API やルートモデルについては swiftui-navigation に、分離に関する診断については swift-concurrency に、テストの構文やフィクスチャについては swift-testing に任せます。

判断のワークフロー

  1. 機能の状態の所有者、入力、出力、依存関係、副作用、ナビゲーションの受け渡し、現在のテストを記録します。
  2. 具体的な課題を特定します。複雑な状態マシン、共有される派生状態、依存関係の制御、機能の合成、チームの担当範囲、UIKit のナビゲーションなどです。
  3. その課題に対応する最小限のパターンを選び、追加するものと変更しないものを書き出します。
  4. 依存関係を注入し、状態遷移を観察できるようにしたうえで、垂直スライスを 1 つ実装します。
  5. 既存の動作テストに加えて、状態遷移と依存関係の失敗に関するテストを実行します。動作が変わった場合はフィクスチャを元に戻し、最小限の境界を修正してから、別のスライスの移行に進む前に再実行します。

パターンの選択

パターン選択する場合主なコスト
MVSwiftUI 機能の状態とオーケストレーションが単純な場合分解しないと、ロジックが大きなビューに入り込む可能性があります
MVVMプレゼンテーションロジックに、独立してテスト可能なアダプターが必要な場合余分なレイヤーが処理を転送するだけの殻になる可能性があります
MVI機能を明示的な state + intents + reducer/effects としてモデル化するのが最適な場合ボイラープレートと、遷移を一元的に設計するコストがかかります
TCA多くの合成可能な機能で、決定論的なエフェクト、依存関係、テストが必要な場合フレームワークの習得と、アーキテクチャへのコミットメントが必要です
Clean Architecture大規模なプロダクトで、domain/data/UI 間の厳格な依存関係の方向が必要な場合プロトコルとマッピングのオーバーヘッドがかかります
CoordinatorUIKit またはハイブリッドのナビゲーションで、フローを別個の所有者に管理させる必要がある場合ライフサイクルとルーティングの所有者が増えます
VIPER確立された VIPER の境界を持つ既存の UIKit モジュールを保守する場合非常に大掛かりで、新しい SwiftUI 機能の既定には適しません

ナビゲーションの複雑さが課題である場合は、別の状態パターンとともに Coordinator を使用します。Coordinator は domain/state アーキテクチャの代替ではありません。

MV を既定とする

ビューは状態を表現するものにし、ビジネス操作は監視可能なモデルと注入されたサービスに配置します。

@MainActor
@Observable
final class TripStore {
    private let client: TripClient
    var trips: [Trip] = []
    var error: Error?

    init(client: TripClient) { self.client = client }

    func load() async {
        do { trips = try await client.fetchTrips() }
        catch { self.error = error }
    }
}

struct TripList: View {
    @State private var store: TripStore

    init(client: TripClient) {
        _store = State(initialValue: TripStore(client: client))
    }

    var body: some View {
        List(store.trips) { Text($0.name) }
            .task { await store.load() }
    }
}

MVVM、MVI、TCA、Clean Architecture、Coordinator、VIPER の構成については、Architecture Pattern Recipes を読み込みます。

より高度なパターンを選ぶ判断材料

  • レンダリングせずにテストする必要のある実質的なプレゼンテーション変換があり、アダプターが実際の振る舞いを担う場合は、MVVM を選びます。
  • 遷移、無効な状態、エフェクトに対して、監査可能な reducer のような単一の経路が必要な場合は、MVI を選びます。
  • 機能の合成、依存関係のオーバーライド、キャンセル、決定論的なエフェクトテストが複数のモジュールで繰り返し必要な場合は、TCA を選びます。
  • 複数の配信レイヤーやデータレイヤーにまたがって、独立した domain ルールと依存関係の方向が重要な場合は、Clean Architecture を選びます。
  • UIKit/ハイブリッド環境でルートの所有が必要な場合、複雑なフローを合成する場合、またはビューコントローラーの外部で条件付きナビゲーションを行う場合は、Coordinator を追加します。
  • 互換性のあるレガシーモジュールや意図的な移行では VIPER を維持します。慣例だけで新しい SwiftUI 機能に採用してはいけません。

ビューが長いという理由だけで、より高度なパターンに移行してはいけません。まずサブビュー、サービス、目的を絞った監視可能なモデルを切り出します。

移行

機能の境界ごとに一つずつ移行します。

  1. テストと依存関係/状態の一覧を用意して、動作を固定します。
  2. 既存の操作を囲む形で、移行先の境界を導入します。
  3. UI と永続化を同時に書き換えず、状態遷移または依存関係を一つずつ移動します。
  4. 各段階の後に、動作、ナビゲーション、キャンセル、エラー、永続化の結果を比較します。
  5. 古い経路に依存する呼び出し元やテストがなくなってから、古い経路を削除します。

ObservableObject から Observation に移行する場合、ラッパーを置き換える前に、同じ所有者と変更の分離を維持します。MVVM から MV に移行する場合、ビューが同じモデル/サービスの動作にバインドされてから、転送のみを行うビューモデルのメンバーを削除します。TCA を導入する場合、まず一つの機能の状態/アクション/エフェクトをラップし、依存関係を段階的に移行します。

よくある間違い

間違い修正方法
人気を理由にパターンを選ぶ実際に観察された機能上の課題と結び付けます。
ビューモデルがプロパティを転送するだけ削除して MV を使います。
一つのオブジェクトがナビゲーション、ネットワーク、書式設定、永続化、UI 状態をすべて担う責務と依存関係の方向に基づいて分割します。
単純な画面に TCA やクリーンアーキテクチャを適用するMV から始め、必要に応じて拡張できる境界を維持します。
コーディネーターを状態アーキテクチャとして使うルート/ライフサイクルの管理に専念させます。
一つの機能内に複数のパターンを混在させるローカルな状態/エフェクトのモデルを一つ定義し、機能の境界ごとに移行します。
一括移行テスト済みの垂直スライスを一つずつ移動し、同じ検証マトリクスを再実行します。

レビューチェックリスト

  • 具体的な機能/チーム上の課題に基づいて選択を正当化している
  • 状態の所有者、変更経路、依存関係、エフェクト、ナビゲーションの所有者が明確である
  • 依存関係が注入され、テストで置き換え可能である
  • パターンのコストが機能の複雑さに見合っている
  • UI の仕組み、ナビゲーション API、分離、テスト構文については、関連するスキルを参照している
  • 一度に一つの垂直スライスを移行し、動作を維持している
  • 各段階の後に、失敗、キャンセル、ナビゲーション、永続化の動作を検証している
  • 転送のみを行うレイヤーや巨大なオブジェクトが残っていない

参考資料

コメント