# アーキテクチャ設計書

## 概要

本ドキュメントは、Wikipedia iOS アプリケーションのアーキテクチャ設計を記述したものです。このアプリケーションは、Wikimedia Foundation によって開発・保守されている公式 Wikipedia iOS クライアントであり、Swift と Objective-C のハイブリッド構成で実装されています。本書では、システム全体構成、レイヤー構成、モジュール構成、データフロー、および横断的関心事について詳細に説明します。

## システム全体構成

### アーキテクチャ概要図

詳細なアーキテクチャ構成図は [アーキテクチャ構成図.md](./アーキテクチャ構成図.md) を参照してください。

### システム境界と外部連携

| 外部システム | 連携方式 | 用途 |
| --- | --- | --- |
| Wikipedia MediaWiki API | REST API (HTTPS) | 記事取得、検索、編集、認証、ユーザー情報取得 |
| Wikimedia RESTBase API | REST API (HTTPS) | Page Content Service (モバイルHTML)、フィードコンテンツ、メトリクス |
| Wikidata API | REST API (HTTPS) | Wikidataエンティティ情報、多言語データ取得 |
| Commons API | REST API (HTTPS) | 画像・メディアファイル取得 |
| Wikimedia Uploads | HTTPS | 画像・メディアファイルのホスティング |
| Apple Push Notification service (APNs) | Push通知 | リモート通知配信 |
| Core Data (ローカル) | SQLite | オフラインデータ永続化、キャッシュ |

## レイヤー構成

### アーキテクチャスタイル

Wikipedia iOS は **モジュラーアーキテクチャ** と **Coordinator パターン** を組み合わせた設計を採用しています。厳密なレイヤードアーキテクチャではなく、機能ごとにモジュール化された構造で、以下の特徴があります:

1. **Swift Package Manager によるモジュール分離**: WMFData、WMFComponents を独立パッケージとして管理
2. **Coordinator パターンによるナビゲーション管理**: 画面遷移ロジックを ViewController から分離
3. **Fetcher パターンによるネットワーク抽象化**: API 通信を Fetcher クラスに集約
4. **MVC + MVVM ハイブリッド**: 画面によって MVC または MVVM を適用

### レイヤー定義

| レイヤー | 責務 | 主なコンポーネント |
| --- | --- | --- |
| Presentation | UI表示、ユーザーインタラクション処理 | ViewController群、UIView、Coordinator、SwiftUI Components |
| Application | ビジネスロジックの調整、ナビゲーション制御 | Coordinator群、WMFAppViewController、Router |
| Domain | ドメインモデル、ビジネスルール | Model群、Data Controllers、Fetcher群 |
| Infrastructure | 外部システム連携、データ永続化 | Session、WMFService、WMFCoreDataStore、MWKDataStore |

### レイヤー間の依存関係ルール

```
Presentation
     │
     ▼
Application
     │
     ▼
  Domain
     │
     ▼
Infrastructure
```

**依存の方向性:**
- 上位レイヤーから下位レイヤーへの依存のみ許可
- Presentation は Application、Domain、Infrastructure を参照可能
- Application は Domain、Infrastructure を参照可能
- Domain は Infrastructure を参照可能
- Infrastructure は外部フレームワーク・システムのみを参照

**許可される参照:**
- ViewController から Coordinator への参照
- Coordinator から ViewController への参照（初期化・表示目的）
- Fetcher から Session/Configuration への参照
- Data Controller から Service への参照

**禁止される参照:**
- Infrastructure から Domain への直接参照
- WMFData パッケージから Wikipedia メインモジュールへの参照
- WMFComponents から Wikipedia メインモジュールへの直接参照（Delegate/Protocol経由のみ）

## モジュール構成

### ドメイン分割

| ドメイン | 責務 | 関連モジュール |
| --- | --- | --- |
| Article | 記事表示、編集、履歴管理 | ArticleViewController, ArticleFetcher, ArticleCoordinator |
| Search | 検索機能、検索履歴 | SearchViewController, MWKRecentSearchList |
| Explore | フィード、おすすめコンテンツ | ExploreViewController, WMFExploreFeedContentController |
| Reading Lists | 保存記事管理、オフラインアクセス | ReadingListsController, SavedPageList |
| Notifications | 通知管理、リモート通知 | NotificationsController, RemoteNotificationsController |
| User | 認証、ユーザープロファイル | AuthenticationManager, LoginCoordinator, ProfileCoordinator |
| Talk Pages | トークページ表示・投稿 | TalkPageViewController, TalkPageFetcher, TalkPageCoordinator |
| Watchlist | ウォッチリスト管理 | WatchlistCoordinator, WatchlistDataController |
| Widgets | ホーム画面ウィジェット | WidgetContentFetcher, WidgetsExtension |
| Year In Review | 年間レビュー機能 | YearInReviewCoordinator, YearInReviewDataController |

### パッケージ構造

```
wikipedia-ios-main/
├── Wikipedia/                          # メインアプリターゲット
│   ├── Code/                           # Swift/Objective-C ソースコード
│   │   ├── *ViewController.swift       # View Controllers
│   │   ├── *Coordinator.swift          # Coordinators
│   │   ├── *Fetcher.swift              # API Fetchers
│   │   ├── Controllers/                # 追加コントローラー
│   │   ├── Advanced Settings/          # 高度な設定画面
│   │   └── SchemeHandler/              # URL Scheme ハンドラー
│   ├── Resources/                      # リソースファイル
│   ├── Localizations/                  # ローカライゼーション
│   └── Images.xcassets/                # 画像アセット
│
├── WMF Framework/                      # 共有フレームワーク
│   ├── Configuration.swift             # 環境設定・API URL構築
│   ├── Router.swift                    # URL ルーティング
│   ├── Fetcher.swift                   # 基底 Fetcher クラス
│   ├── Theme.swift                     # テーマ管理
│   ├── *.xcdatamodeld/                 # Core Data モデル
│   ├── Widget/                         # ウィジェット共有コード
│   └── Remote Notifications/           # リモート通知処理
│
├── WMFData/                            # Swift Package: データ層
│   └── Sources/WMFData/
│       ├── Data Controllers/           # ドメイン別データコントローラー
│       ├── Service/                    # ネットワークサービス
│       ├── Store/                      # データストア (Core Data)
│       ├── Models/                     # データモデル
│       ├── Environment/                # 環境設定
│       └── Extensions/                 # 拡張
│
├── WMFComponents/                      # Swift Package: UI コンポーネント
│   └── Sources/WMFComponents/
│       ├── Components/                 # 再利用可能な UI コンポーネント
│       ├── Coordinator/                # コーディネーターデリゲート
│       ├── Style/                      # スタイル・テーマ
│       └── Extensions/                 # 拡張
│
├── Widgets/                            # ウィジェット拡張
│   ├── Extension/                      # ウィジェット実装
│   └── Views/                          # ウィジェット UI
│
├── NotificationServiceExtension/       # 通知サービス拡張
├── ContinueReadingWidget/              # 続きを読むウィジェット
└── Wikipedia Stickers/                 # iMessage ステッカー
```

### コンポーネント依存関係

**メインアプリ (Wikipedia) の依存関係:**
- WMF Framework (共有フレームワーク)
- WMFData (Swift Package - データ層)
- WMFComponents (Swift Package - UI コンポーネント)
- CocoaLumberjackSwift (ログ)

**WMFComponents の依存関係:**
- WMFData
- WMFDataMocks (テスト用)
- SDWebImage (画像読み込み)

**WMFData の依存関係:**
- Foundation (標準ライブラリのみ)

## ミドルウェア構成

### データベース

| 種類 | ミドルウェア | バージョン | 用途 |
| --- | --- | --- | --- |
| RDB | SQLite (Core Data) | iOS標準 | 記事キャッシュ、閲覧履歴、保存リスト、検索履歴 |

**Core Data モデル:**
- `Wikipedia.xcdatamodeld`: メインデータモデル (WMFArticle, WMFContentGroup等)
- `Cache.xcdatamodeld`: キャッシュ用データモデル
- `PersistentCache.xcdatamodeld`: 永続キャッシュ用データモデル
- `WMFData.momd`: WMFData パッケージ用データモデル (CDPage, CDPageView等)

### キャッシュ

| ミドルウェア | バージョン | 用途 | TTL |
| --- | --- | --- | --- |
| URLSession Cache | iOS標準 | HTTP レスポンスキャッシュ | URLRequest.CachePolicy に依存 |
| Core Data Cache | iOS標準 | 記事・画像のオフラインキャッシュ | 1年 (バックグラウンドハウスキーピングで削除) |
| ImageCacheController | カスタム | 画像キャッシュ管理 | 設定可能 |
| SharedContainerCacheStore | カスタム | ウィジェット共有キャッシュ | アプリ設定依存 |

### メッセージキュー

| ミドルウェア | バージョン | 用途 |
| --- | --- | --- |
| BGTaskScheduler | iOS標準 | バックグラウンドタスクスケジューリング |
| NotificationCenter | iOS標準 | アプリ内イベント通知 |

### その他ミドルウェア

| ミドルウェア | バージョン | 用途 |
| --- | --- | --- |
| CocoaLumberjackSwift | - | ロギング |
| SDWebImage | 5.19.0+ | 画像の非同期読み込み・キャッシュ |
| WKWebView | iOS標準 | 記事表示 (モバイルHTML) |

## データフロー

### リクエスト処理の流れ

**記事表示フローの例:**

1. ユーザーが記事リンクをタップ
2. `Router` が URL を解析し、`Destination.article(URL)` を返す
3. `LinkCoordinator` または `ArticleCoordinator` が起動
4. `ArticleViewController` がインスタンス化される
5. `ArticleFetcher` が `Session` を通じて Page Content Service API を呼び出し
6. `Session` が `URLSession` でリクエストを実行
7. レスポンスが JSON/HTML でパースされる
8. `WKWebView` でモバイルHTML をレンダリング
9. 記事メタデータが Core Data に保存される

### 非同期処理の流れ

**バックグラウンドフェッチフローの例:**

1. `BGTaskScheduler` がバックグラウンドタスクをトリガー
2. `AppDelegate.registerBackgroundTasks()` で登録されたハンドラーが実行
3. `WMFAppViewController.performBackgroundFetch()` が呼び出される
4. `BackgroundFetcher` がフィードコンテンツの更新を実行
5. 新しいコンテンツが Core Data に保存される
6. タスク完了を `BGTaskScheduler` に通知
7. 次回のバックグラウンドフェッチをスケジュール

### データ永続化の流れ

1. **保存リクエスト**: UI アクションまたはフェッチ完了時にトリガー
2. **コンテキスト選択**: `viewContext` (メインスレッド) または `backgroundContext` を使用
3. **エンティティ操作**: `fetchOrCreate` でエンティティを取得または作成
4. **プロパティ更新**: モデルプロパティを更新
5. **保存実行**: `moc.save()` で変更を永続化
6. **変更通知**: `NSManagedObjectContext` の変更通知が自動配信

## 横断的関心事

### 認証・認可

| 方式 | 実装箇所 | 対象 |
| --- | --- | --- |
| MediaWiki OAuth/CentralAuth | WMFAuthenticationManager | 全てのログイン必要操作 |
| CSRF Token | Fetcher.requestMediaWikiAPIAuthToken() | 編集、投稿、その他変更操作 |
| Cookie 管理 | Session.cloneCentralAuthCookies() | Wikimedia サイト間のセッション共有 |

### ロギング・監査

| 種類 | 実装方式 | 保存先 |
| --- | --- | --- |
| アプリケーションログ | CocoaLumberjackSwift (DDLog) | コンソール出力 |
| 監査ログ | EventPlatform | Wikimedia イベントプラットフォーム |
| アクセスログ | なし (サーバー側で管理) | - |

**ログレベル:**
- Verbose: 詳細ログ
- Debug: デバッグ情報
- Info: 一般情報
- Warning: 警告
- Error: エラー

### エラーハンドリング

| エラー種別 | ハンドリング方式 | レスポンス |
| --- | --- | --- |
| ネットワークエラー | Result型 / NSError | リトライ提案、オフラインフォールバック |
| MediaWiki APIエラー | MediaWikiAPIDisplayError | ユーザーフレンドリーなエラーメッセージ表示 |
| Core Dataエラー | NSError | ログ出力、静かな失敗 |
| 認証エラー (401) | SessionAuthenticationDelegate | 自動再認証試行 |

### トランザクション管理

| 範囲 | 管理方式 | 分離レベル |
| --- | --- | --- |
| Core Data 操作 | NSManagedObjectContext.perform() | NSMergeByPropertyStoreTrumpMergePolicy |
| 複数 API 呼び出し | DispatchGroup / async-await | 呼び出し元で管理 |

## 設計原則・コーディング規約

### 適用している設計原則

| 原則 | 適用箇所 | 実装例 |
| --- | --- | --- |
| 単一責任原則 (SRP) | Coordinator, Fetcher | 各 Coordinator は特定の画面遷移フローのみ担当 |
| 依存性逆転原則 (DIP) | WMFService プロトコル | Protocol を通じてサービス実装を抽象化 |
| インターフェース分離原則 (ISP) | Delegate プロトコル | 必要なメソッドのみを持つ細粒度の Delegate |
| オープン・クローズド原則 (OCP) | Fetcher 基底クラス | 基底 Fetcher を継承して機能を拡張 |

### コーディング規約

**Objective-C:**
- Apple's Coding Guidelines for Cocoa に準拠
- ClangFormat による自動フォーマット (`.clang-format` 設定ファイル)

**Swift:**
- swift.org API Design Guidelines に準拠
- SwiftLint による静的解析 (`.swiftlint.yml`, `.swiftlint-autocorrect.yml`)
- 4スペースインデント (Xcode デフォルト)

**ファイル命名規則:**
- ViewController: `*ViewController.swift`
- Coordinator: `*Coordinator.swift`
- Fetcher: `*Fetcher.swift`
- Data Controller: `*DataController.swift`
- Extension: `OriginalType+ExtensionName.swift`

## 備考

### 技術的負債・改善点

- **Objective-C コードの存在**: 一部のコア機能 (MWKDataStore等) が依然として Objective-C で実装されており、Swift への移行が段階的に進められている
- **アーキテクチャパターンの混在**: MVC と MVVM が画面によって混在しており、統一が望まれる
- **テスト戦略**: Unit Test は存在するが、UI Test や Integration Test のカバレッジ拡充が課題

### バージョン要件

- **Xcode**: 16.0 以上
- **iOS**: 16.0 以上
- **Swift**: 5.8 以上
