/* Page prose (ja) */
"VersionAClassic" = "# バージョン A（クラシック）: GCD + completion handler + `DispatchGroup`\n\n各取得は **completion handler** を受け取ります。これは、（シミュレートした）ネットワークが完了したときに `Result` を伴って呼び戻すクロージャです。2 つの取得は独立しているので、両方をバックグラウンドキューに乗せ、*両方*が呼び戻したタイミングを知るために **`DispatchGroup`** を使います。それからメインに移り、組み合わせて報告します。";
"VersionAClassic-2" = "**実行して確認:** 最初に `Fetching menu and stock...` が表示されます。2 つの `fetch` 呼び出しはどちらもすぐに戻ったからです。2 つの取得は並列で実行され（0.6 秒と 0.4 秒）、およそ 0.6 秒後にグループが空になり、メインスレッドで次が得られます。\n\n* callout(出力):\n`Fetching menu and stock...`  \n`Sellable today: [\"Latte\", \"Espresso\"]`\n\nCold brew はフィルタで除外されます。在庫が `0` だからです。\n\n* callout(試してみよう): `fetchStock` の Cold brew の在庫を `0` から `2` に変えてみましょう。販売可能リストに表示されるようになりますか？\n\nさて、これが何を代償にしたか数えてみましょう。\n\n* クロージャの外側に置かれた 2 つの可変な `Result?` 変数。各答えをそれぞれの completion handler の外へこっそり持ち出すためのものです。\n* 手作業の `enter()`/`leave()` の管理。一度でも間違えるとグループはハングするかクラッシュします。\n* 結合点での結果は 2 つの**オプショナルな** `Result` なので、「2 つの `Result?`」から「2 つの実際の値、またはエラー」へ到達するには `guard` *と* `do`-`try`-`catch` の両方が必要です。\n* メインスレッドへの移動は、*あなた*が忘れずに行うものでした（`notify(queue: .main)`）。忘れれば、バックグラウンドスレッドで組み合わせ、そこから UI を更新することになります。コンパイラが決して指摘しないバグです。\n\nどれも間違いではありません。しかしどの部分も手作業であり、本当のロジックである「メニューを在庫でフィルタする」は儀式の中に埋もれています。\n\n* callout(data race についての補足): `menuResult` と `stockResult` はバックグラウンドスレッドから書き込まれ、`notify` の中で読み取られます。これはたまたま安全です。グループの `leave()` → `notify` の順序が、読み取りの前に書き込みが終わることを保証するからです。しかし*それを確認してくれるものは何もありません*。これはまさに、data race が一般に引き起こす種類の危険であり、モダンモデルが構造的に取り除くものそのものです。\n\n[前へ](@previous)  |  3 / 8 ページ  |  [次へ: バージョン B: モダンな方法](@next)";
