refactor(docs): réorganiser la documentation selon principes DDD
Réorganise la documentation du projet selon les principes du Domain-Driven Design (DDD) pour améliorer la cohésion, la maintenabilité et l'alignement avec l'architecture modulaire du backend. **Structure cible:** ``` docs/domains/ ├── README.md (Context Map) ├── _shared/ (Core Domain) ├── recommendation/ (Supporting Subdomain) ├── content/ (Supporting Subdomain) ├── moderation/ (Supporting Subdomain) ├── advertising/ (Generic Subdomain) ├── premium/ (Generic Subdomain) └── monetization/ (Generic Subdomain) ``` **Changements effectués:** Phase 1: Création de l'arborescence des 7 bounded contexts Phase 2: Déplacement des règles métier (01-19) vers domains/*/rules/ Phase 3: Déplacement des diagrammes d'entités vers domains/*/entities/ Phase 4: Déplacement des diagrammes flux/états/séquences vers domains/*/ Phase 5: Création des README.md pour chaque domaine Phase 6: Déplacement des features Gherkin vers domains/*/features/ Phase 7: Création du Context Map (domains/README.md) Phase 8: Mise à jour de mkdocs.yml pour la nouvelle navigation Phase 9: Correction automatique des liens internes (script fix-markdown-links.sh) Phase 10: Nettoyage de l'ancienne structure (regles-metier/, diagrammes/, features/) **Configuration des tests:** - Makefile: godog run docs/domains/*/features/ - scripts/generate-bdd-docs.py: features_dir → docs/domains **Avantages:** ✅ Cohésion forte: toute la doc d'un domaine au même endroit ✅ Couplage faible: domaines indépendants, dépendances explicites ✅ Navigabilité améliorée: README par domaine = entrée claire ✅ Alignement code/docs: miroir de backend/internal/ ✅ Onboarding facilité: exploration domaine par domaine ✅ Tests BDD intégrés: features au plus près des règles métier Voir docs/REFACTOR-DDD.md pour le plan complet.
This commit is contained in:
@@ -0,0 +1,188 @@
|
||||
# language: fr
|
||||
Fonctionnalité: File d'attente et commande "Suivant"
|
||||
En tant qu'auditeur en déplacement
|
||||
Je veux que l'application pré-calcule intelligemment les prochains contenus
|
||||
Afin d'avoir une navigation fluide sans latence
|
||||
|
||||
Contexte:
|
||||
Étant donné que l'API RoadWave est disponible
|
||||
Et qu'un utilisateur est connecté
|
||||
Et que la géolocalisation est activée
|
||||
|
||||
Scénario: Pré-calcul initial de 5 contenus en cache
|
||||
Étant donné que je viens de démarrer l'application
|
||||
Et que je suis situé à Paris (48.8566, 2.3522)
|
||||
Et que je suis en mode voiture (vitesse ≥ 5 km/h)
|
||||
Quand l'application initialise la lecture
|
||||
Alors une file d'attente de 5 contenus est pré-calculée
|
||||
Et la file est stockée en cache Redis avec la clé "user:{user_id}:queue"
|
||||
Et les métadonnées incluent ma position, le timestamp de calcul et le mode
|
||||
Et le cache a un TTL de 15 minutes
|
||||
|
||||
Scénario: Commande "Suivant" sans latence
|
||||
Étant donné qu'une file d'attente de 5 contenus est en cache
|
||||
Et que j'écoute actuellement le contenu "A"
|
||||
Quand j'appuie sur le bouton "Suivant"
|
||||
Alors le contenu suivant démarre immédiatement (< 100ms)
|
||||
Et le contenu est retiré de la file d'attente
|
||||
Et il reste 4 contenus dans la file
|
||||
|
||||
Scénario: Recalcul automatique après déplacement >10km
|
||||
Étant donné que la file a été calculée à Paris (48.8566, 2.3522)
|
||||
Et que j'ai 5 contenus en cache
|
||||
Quand je me déplace à Versailles (48.8049, 2.1204) soit 12km
|
||||
Alors la file d'attente est invalidée automatiquement
|
||||
Et une nouvelle file de 5 contenus est recalculée
|
||||
Et elle est basée sur ma nouvelle position
|
||||
|
||||
Scénario: Recalcul automatique toutes les 10 minutes
|
||||
Étant donné qu'une file a été calculée il y a 10 minutes
|
||||
Et que ma position n'a pas changé
|
||||
Quand le timer de rafraîchissement expire
|
||||
Alors une nouvelle file de 5 contenus est recalculée
|
||||
Et les anciens contenus non écoutés sont remplacés
|
||||
Et les nouveaux contenus publiés depuis sont inclus
|
||||
|
||||
Scénario: Recalcul quand il reste moins de 3 contenus
|
||||
Étant donné qu'il reste 3 contenus dans ma file d'attente
|
||||
Quand j'appuie sur "Suivant"
|
||||
Alors il reste 2 contenus
|
||||
Et un recalcul asynchrone est déclenché en arrière-plan
|
||||
Et 3 nouveaux contenus sont ajoutés à la file
|
||||
Et la file contient maintenant 5 contenus
|
||||
|
||||
Scénario: Insertion prioritaire d'un contenu géolocalisé en mode voiture
|
||||
Étant donné que j'ai une file de 5 contenus pré-calculée
|
||||
Et que je suis en mode voiture
|
||||
Et que je me déplace à 50 km/h vers un point avec contenu géolocalisé
|
||||
Quand je suis à 98m du point (ETA = 7 secondes)
|
||||
Alors une notification est envoyée (icône + compteur 7→1 + son)
|
||||
Et je dois appuyer sur "Suivant" dans les 7 secondes pour valider
|
||||
Quand j'appuie sur "Suivant"
|
||||
Alors un décompte de 5 secondes démarre
|
||||
Et après 5 secondes, le contenu géolocalisé s'insère et démarre
|
||||
Et il remplace le contenu actuel dans la lecture
|
||||
|
||||
Scénario: Contenu géolocalisé ignoré est perdu (cooldown activé)
|
||||
Étant donné qu'une notification géolocalisée est affichée (compteur 7→1)
|
||||
Quand je ne clique pas sur "Suivant" pendant les 7 secondes
|
||||
Alors la notification disparaît
|
||||
Et le contenu géolocalisé est perdu (pas d'insertion dans la file)
|
||||
Et un cooldown de 10 minutes est activé
|
||||
Et aucune nouvelle notification géolocalisée ne sera envoyée pendant 10 minutes
|
||||
|
||||
Scénario: Validation d'une notification géolocalisée
|
||||
Étant donné qu'une notification géolocalisée est affichée (compteur à 5)
|
||||
Et que j'écoute un podcast
|
||||
Quand j'appuie sur "Suivant"
|
||||
Alors le compteur bascule à "5" (décompte final)
|
||||
Et le podcast actuel continue de jouer
|
||||
Et après 5 secondes, le contenu géolocalisé démarre
|
||||
Et le podcast est mis en pause et sauvegardé dans l'historique
|
||||
|
||||
Scénario: Invalidation immédiate après modification des préférences
|
||||
Étant donné que j'ai une file de 5 contenus en cache
|
||||
Et que ma vitesse GPS est de 5 km/h (piéton)
|
||||
Quand je modifie mes curseurs de préférences (géo/découverte/politique)
|
||||
Alors la file d'attente est invalidée immédiatement
|
||||
Et une nouvelle file est recalculée avec les nouvelles préférences
|
||||
Et les anciens contenus en cache sont supprimés
|
||||
|
||||
Scénario: Blocage modification préférences en conduite (>10 km/h)
|
||||
Étant donné que ma vitesse GPS est de 50 km/h (en voiture)
|
||||
Quand j'essaie d'accéder aux réglages de préférences
|
||||
Alors l'interface affiche "Paramètres verrouillés en conduite"
|
||||
Et je ne peux pas modifier les curseurs géo/découverte/politique
|
||||
Et un message "Arrêtez-vous pour modifier vos préférences" s'affiche
|
||||
|
||||
Scénario: Invalidation lors du démarrage d'un live suivi
|
||||
Étant donné que je suis abonné au créateur "RadioVoyage"
|
||||
Et que j'ai une file de 5 contenus en cache
|
||||
Et que je suis dans la zone géographique du créateur
|
||||
Quand le créateur "RadioVoyage" démarre une radio live
|
||||
Alors je reçois une notification push
|
||||
Et le contenu live s'insère en tête de la file d'attente
|
||||
Et la file d'attente est recalculée
|
||||
|
||||
Scénario: Métadonnées de cache Redis
|
||||
Étant donné qu'une file d'attente est calculée
|
||||
Quand elle est stockée dans Redis
|
||||
Alors la clé est "user:{user_id}:queue"
|
||||
Et les métadonnées incluent:
|
||||
| champ | valeur |
|
||||
| last_lat | 48.8566 |
|
||||
| last_lon | 2.3522 |
|
||||
| computed_at | 2026-01-21T10:30:00Z |
|
||||
| mode | voiture |
|
||||
Et le TTL est de 15 minutes (900 secondes)
|
||||
|
||||
Scénario: Contenu géolocalisé remplace le contenu actuel (pas d'insertion en file)
|
||||
Étant donné que j'écoute le contenu C2 de ma file [C1, C2, C3, C4, C5]
|
||||
Et qu'une notification géolocalisée "Tour Eiffel" est déclenchée
|
||||
Quand je valide la notification
|
||||
Et que le décompte de 5s se termine
|
||||
Alors le contenu "Tour Eiffel" remplace C2 et démarre
|
||||
Et C2 est sauvegardé dans l'historique de navigation
|
||||
Et la file reste [C3, C4, C5] (pas de contenu retiré)
|
||||
Et quand "Tour Eiffel" se termine, C3 démarre
|
||||
|
||||
Scénario: Invalidation après déplacement exactement 10km
|
||||
Étant donné que la file a été calculée à une position donnée
|
||||
Quand je me déplace d'exactement 10.0 km
|
||||
Alors la file d'attente n'est PAS invalidée (seuil strict >10km)
|
||||
Et les contenus en cache restent valides
|
||||
Quand je me déplace de 10.1 km supplémentaires (total 10.1km)
|
||||
Alors la file d'attente est invalidée
|
||||
Et une nouvelle file est calculée
|
||||
|
||||
Scénario: Rafraîchissement exactement après 10 minutes
|
||||
Étant donné qu'une file a été calculée à 10:00:00
|
||||
Quand l'heure actuelle est 10:10:00
|
||||
Alors le timer de rafraîchissement expire
|
||||
Et une nouvelle file de 5 contenus est recalculée
|
||||
Et le timestamp "computed_at" est mis à jour
|
||||
|
||||
Scénario: Recalcul asynchrone non-bloquant
|
||||
Étant donné qu'il reste 2 contenus dans la file
|
||||
Et que j'appuie sur "Suivant"
|
||||
Quand le recalcul asynchrone démarre
|
||||
Alors la lecture du contenu actuel n'est pas interrompue
|
||||
Et le recalcul se fait en arrière-plan
|
||||
Et les nouveaux contenus sont ajoutés dès disponibles (< 500ms)
|
||||
Et l'utilisateur ne perçoit aucune latence
|
||||
|
||||
Scénario: Notification basée sur ETA (pas distance fixe)
|
||||
Étant donné qu'un contenu géolocalisé existe à un point GPS
|
||||
Et que je roule à 130 km/h
|
||||
Quand je suis à 252m du point (ETA = 7 secondes)
|
||||
Alors une notification est envoyée
|
||||
Quand je suis à 300m du point (ETA = 8 secondes)
|
||||
Alors aucune notification n'est envoyée (ETA >7s)
|
||||
|
||||
Plan du Scénario: Différentes distances de déplacement et invalidation
|
||||
Étant donné qu'une file a été calculée à une position donnée
|
||||
Quand je me déplace de <distance> km
|
||||
Alors la file est <action>
|
||||
|
||||
Exemples:
|
||||
| distance | action |
|
||||
| 5 | conservée |
|
||||
| 9.9 | conservée |
|
||||
| 10.0 | conservée |
|
||||
| 10.1 | invalidée et recalculée |
|
||||
| 15 | invalidée et recalculée |
|
||||
| 50 | invalidée et recalculée |
|
||||
|
||||
Scénario: Quota de 6 contenus géolocalisés par heure
|
||||
Étant donné que j'ai validé 6 notifications géolocalisées dans la dernière heure
|
||||
Quand un 7ème contenu géolocalisé est détecté (ETA 7s)
|
||||
Alors aucune notification n'est envoyée
|
||||
Et le quota horaire est respecté
|
||||
|
||||
Scénario: Mode piéton - pas de notification avec compteur 7s
|
||||
Étant donné que je suis en mode piéton (vitesse <5 km/h)
|
||||
Et qu'un audio-guide géolocalisé existe à 150m
|
||||
Quand je passe dans le rayon de 200m
|
||||
Alors une notification push système est envoyée
|
||||
Et aucun compteur 7s n'est affiché
|
||||
Et je peux ouvrir l'app en tapant sur la notification
|
||||
Reference in New Issue
Block a user