/* Page prose (fr) */
"ClassicVsModernWrappingUp" = "# Récapitulatif\n\nTu as maintenant observé une tâche du quotidien (récupérer deux choses, les combiner, gérer les erreurs, livrer sur le principal) résolue des deux façons, et la version moderne l'emporte sur la lisibilité, la sécurité et le pur nombre de lignes. Le vrai enseignement n'est pourtant pas \"réécris tout\"; c'est de savoir ce qui correspond à quoi, et où migrer paie réellement. Le résumé ci-dessous est une carte pour les deux.\n\n* Le modèle moderne gagne sur la même tâche: aucun état mutable partagé, aucun `enter`/`leave`, un seul chemin d'erreur, et un saut automatique vers le thread principal via `@MainActor`.\n* Chaque outil classique a une contrepartie moderne:\n  * completion handler ➡️ fonction `async`\n  * `DispatchGroup`/sémaphore ➡️ `async let`/`TaskGroup`\n  * protection par file en série ➡️ **actor**\n  * `DispatchQueue.main` ➡️ **`@MainActor`**\n  * annulation manuelle d'`Operation` ➡️ annulation coopérative de `Task`\n  * delegate/callback ➡️ `AsyncStream`/continuation\n* **Le classique gagne encore sa place** pour les APIs plus anciennes, le contrôle de dispatch fin, les cibles d'OS antérieures à `async`/`await`, et le code qui fonctionne déjà: une réécriture est un coût, donc le piège est de le dépenser là où il n'y a aucun bénéfice.\n* **Migre au niveau des coutures:** enveloppe les callbacks hérités avec des continuations, écris le nouveau code de façon moderne, remplace les verrous ad hoc par des actors, adopte `@MainActor` pour l'UI, et active la vérification data-race de Swift 6 de façon incrémentale.\n* **Fais le pont avec la frontière avec soin:** une continuation reprend **exactement une fois**, donc un callback qui se déclenche plusieurs fois a besoin d'un `AsyncStream`. Et ne bloque jamais sur `DispatchGroup.wait()`/`semaphore.wait()` à l'intérieur d'une `Task`: fais le pont avec une continuation et fais-lui `await` à la place.\n* **`@MainActor` ne déplace pas ton travail lent**: il garantit que le code annoté s'exécute sur le principal. Fais le travail lourd dans une fonction async simple hors du principal, et réserve la partie `@MainActor` à la petite mise à jour d'UI à la fin.\n* Les deux modèles **interopèrent**: du code mixte est normal et attendu pendant une migration.\n\n---\n\n## Où aller ensuite\n\nC'est là tout le livre: d'un unique barista bloqué sur le thread principal jusqu'aux actors qui gardent l'état partagé en sécurité au sein d'un seul processus. Tu as rencontré le modèle classique (GCD et Operations) et le moderne (`async`/`await`, la concurrence structurée, `AsyncSequence`, et les actors), et tu as vu *pourquoi* le second existe comme réponse au premier.\n\nLes concepts ne se posent vraiment qu'une fois que tu les utilises sur quelque chose qui te tient à cœur. Alors voici l'encouragement pour conclure: **ouvre l'un de tes propres projets et reviens sur les chapitres modernes.** Trouve un completion handler et transforme-le en `async`/`await`. Trouve une valeur mutable partagée protégée par un verrou et fais-en un `actor`. Trouve un écran qui saccade et sors son travail lourd du thread principal. Chaque petit changement fera qu'un chapitre se mettra en place pour de bon.\n\nLa concurrence cesse de faire peur au moment où tu l'as fait fonctionner, exprès, dans du code qui est le tien. Va faire ça. Tu es prêt.\n\n---\n\n## Piste bonus: des actors entre machines\n\nCurieux de savoir jusqu'où s'étire l'idée d'actor? Il y a un chapitre de plus après celui-ci, **[Actors distribués](Distributed%20Actors.playgroundchapter/Overview)**, en crédit supplémentaire. Il porte la même sensation d'`await`-pour-appeler jusqu'à des objets vivant dans *d'autres processus, même sur d'autres machines*. C'est une visite conceptuelle à lire plutôt qu'un labo exécutable, alors traite-le comme un coup d'œil vers l'avant pour quand les idées centrales te sembleront solides.\n\n[Précédent](@previous)  |  page 8 sur 8";
