Implement production vertical slice foundation
This commit is contained in:
1 parent
9d4a89f355
commit
a18e82eb44
104 files changed
+10595
-268
No files matched your search
@@ -0,0 +1,128 @@
|
||||
# 0008 — Services possédés et injectés par la composition
|
||||
|
||||
- Statut : accepté
|
||||
- Date : 2026-08-10
|
||||
- Remplace : aucun
|
||||
|
||||
## Contexte
|
||||
|
||||
Les réglages, l'accès aux sauvegardes, l'audio et une campagne chargée doivent
|
||||
survivre à plusieurs changements d'écran. Godot permet de résoudre ce besoin
|
||||
avec des autoloads, des singletons statiques ou un bus de signaux global. Ces
|
||||
solutions rendent toutefois les dépendances accessibles depuis n'importe quel
|
||||
script, masquent leur durée de vie et compliquent l'isolation des tests.
|
||||
|
||||
La verticale possède déjà une couche `composition`, seule autorisée à connaître
|
||||
les implémentations concrètes de toutes les autres couches. Elle peut donc
|
||||
maintenir les objets de longue durée sans les transformer en état global.
|
||||
|
||||
## Décision
|
||||
|
||||
### Aucun accès global de gameplay
|
||||
|
||||
Aucun autoload personnalisé, singleton statique, registre global, service
|
||||
locator ou bus de signaux global n'est introduit pour le gameplay de la
|
||||
verticale. Une longue durée de vie ne suffit pas à justifier un accès global.
|
||||
|
||||
Les singletons fournis par Godot restent des détails de plateforme. Seuls les
|
||||
adaptateurs autorisés les utilisent ; le domaine et les cas d'usage ne lisent
|
||||
pas directement `Input`, `SceneTree`, `AudioServer`, les fichiers ou l'horloge.
|
||||
|
||||
### Racine persistante
|
||||
|
||||
`vertical_slice_root.tscn` est la racine de composition persistante de la
|
||||
verticale. Elle crée les implémentations concrètes, les relie à leurs ports et
|
||||
possède un emplacement destiné à l'écran ou au monde actif. Une transition
|
||||
remplace ce contenu enfant sans remplacer la racine et sans demander aux scènes
|
||||
de rechercher des services dans l'arbre.
|
||||
|
||||
La composition est responsable de :
|
||||
|
||||
- construire les adaptateurs d'infrastructure et les cas d'usage ;
|
||||
- charger ou créer l'état de campagne ;
|
||||
- injecter les contrats requis avant d'activer une scène ;
|
||||
- connecter les sorties d'une scène aux commandes applicatives appropriées ;
|
||||
- déconnecter et libérer les dépendances de portée courte lors d'une
|
||||
transition ;
|
||||
- choisir l'écran suivant à partir d'un résultat applicatif explicite.
|
||||
|
||||
Une scène ne parcourt pas ses parents, `/root`, un groupe global ou un chemin
|
||||
absolu afin de découvrir une dépendance. Elle expose une méthode de
|
||||
configuration, des propriétés typées ou un constructeur de composition
|
||||
explicite. L'absence d'une dépendance requise échoue immédiatement en
|
||||
développement et dans les tests de chargement.
|
||||
|
||||
### Durées de vie
|
||||
|
||||
Trois portées sont distinguées :
|
||||
|
||||
1. **Application** : réglages, localisation, adaptateurs d'entrée et d'audio,
|
||||
horloge de plateforme, accès au stockage et liste des sauvegardes. Ils vivent
|
||||
tant que la racine existe.
|
||||
2. **Campagne** : `CampaignState`, progression de mission et cas d'usage liés à
|
||||
une partie. Ils sont créés lors d'une nouvelle partie ou d'un chargement et
|
||||
détruits lors de sa fermeture ou de son remplacement.
|
||||
3. **Plongée** : `ResolvedDiveRules`, `DiveSession`, acteurs, adaptateurs
|
||||
physiques et service sonar courant. Ils sont créés au départ d'une plongée
|
||||
et détruits après production de son résultat immuable.
|
||||
|
||||
Un objet de portée longue peut fournir un port à une portée plus courte. Il ne
|
||||
conserve pas en retour une référence implicite vers un acteur ou une scène déjà
|
||||
détruite. Les connexions de signaux suivent la même propriété et sont retirées
|
||||
avec leur portée.
|
||||
|
||||
Les services d'infrastructure ne deviennent pas propriétaires des règles. Par
|
||||
exemple, le dépôt de sauvegarde écrit un document demandé par un cas d'usage ;
|
||||
il ne décide pas quand une mission progresse ou combien d'argent est gagné.
|
||||
|
||||
### Navigation et communications
|
||||
|
||||
La présentation traduit une interaction en commande ou appel de cas d'usage.
|
||||
Elle consomme ensuite un résultat, un snapshot ou un événement typé. Elle ne
|
||||
modifie jamais directement l'état de campagne ou un acteur du monde.
|
||||
|
||||
Les événements locaux peuvent utiliser les signaux Godot entre objets déjà
|
||||
reliés par la composition. Un signal décrit un fait passé et ne sert pas de
|
||||
canal global anonyme. Une intention reste une commande nommée.
|
||||
|
||||
Chaque écran et composition de plongée peut être instancié dans un test avec de
|
||||
faux ports, sans charger une campagne réelle, le stockage de la machine ou tous
|
||||
les autres écrans.
|
||||
|
||||
### Évolution
|
||||
|
||||
Tout nouvel autoload, accès statique global ou exception durable à cette
|
||||
politique exige un ADR qui précise son propriétaire, sa durée de vie, son API,
|
||||
sa stratégie de réinitialisation et son isolation en test.
|
||||
|
||||
## Conséquences
|
||||
|
||||
- Les dépendances et leur durée de vie sont visibles à l'endroit où les scènes
|
||||
sont assemblées.
|
||||
- Un changement d'écran ne détruit pas les services applicatifs nécessaires à
|
||||
la session.
|
||||
- Une nouvelle campagne peut remplacer proprement la précédente sans conserver
|
||||
ses signaux, caches ou acteurs.
|
||||
- Les écrans sont testables avec des doubles légers et ne dépendent pas d'un
|
||||
ordre d'initialisation d'autoloads.
|
||||
- La composition contient davantage de code d'assemblage explicite et doit
|
||||
rester distincte des règles de gameplay.
|
||||
- Les transitions doivent libérer leurs objets de portée courte et seront
|
||||
couvertes par des tests d'intégration et de fuite de nœuds.
|
||||
- Les fonctionnalités transversales passent par des ports nommés plutôt que par
|
||||
une commodité globale.
|
||||
|
||||
## Alternatives considérées
|
||||
|
||||
- **Un autoload par service** : rejeté, car sauvegarde, campagne, audio et
|
||||
navigation deviendraient accessibles et mutables depuis toutes les couches.
|
||||
- **Un unique `GameManager` autoload** : rejeté, car il concentrerait
|
||||
assemblage, navigation et règles dans un propriétaire générique.
|
||||
- **Un bus d'événements global** : rejeté, car producteurs et consommateurs
|
||||
seraient reliés par des noms implicites et des durées de vie difficiles à
|
||||
vérifier.
|
||||
- **Remplacer toute la scène courante à chaque écran** : rejeté comme
|
||||
navigation principale, car les services persistants devraient alors être
|
||||
globaux ou reconstruits avec un état dupliqué.
|
||||
- **Rechercher les services dans les parents ou par groupe Godot** : rejeté,
|
||||
car la dépendance resterait cachée et dépendrait de la forme de l'arbre.
|
||||
Reference in new issue
Block a user