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,567 @@
|
||||
# language: fr
|
||||
Fonctionnalité: API - Évolution des jauges d'intérêt
|
||||
En tant qu'API backend
|
||||
Je veux calculer et persister les évolutions de jauges d'intérêt
|
||||
Afin d'alimenter l'algorithme de recommandation
|
||||
|
||||
Contexte:
|
||||
Étant donné que l'API RoadWave est disponible
|
||||
Et que la base de données PostgreSQL est accessible
|
||||
Et qu'un utilisateur "user123" existe avec token JWT valide
|
||||
|
||||
Scénario: API calcule like automatique renforcé (≥80% écoute)
|
||||
Étant donné que l'utilisateur "user123" a une jauge "Automobile" à 45% en base
|
||||
Et qu'un contenu "content456" de 5 minutes est tagué "Automobile"
|
||||
Quand je POST /api/v1/listening-events
|
||||
"""json
|
||||
{
|
||||
"user_id": "user123",
|
||||
"content_id": "content456",
|
||||
"listened_duration_seconds": 270,
|
||||
"total_duration_seconds": 300,
|
||||
"completion_percentage": 90
|
||||
}
|
||||
"""
|
||||
Alors le statut de réponse est 201
|
||||
Et la réponse contient:
|
||||
"""json
|
||||
{
|
||||
"like_type": "automatic_reinforced",
|
||||
"gauge_updates": [
|
||||
{
|
||||
"category": "Automobile",
|
||||
"previous_value": 45,
|
||||
"delta": 2,
|
||||
"new_value": 47
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
Et en base de données, la jauge "Automobile" de "user123" est à 47%
|
||||
|
||||
Scénario: API calcule like automatique standard (30-79% écoute)
|
||||
Étant donné que l'utilisateur "user123" a une jauge "Voyage" à 60% en base
|
||||
Et qu'un contenu "content789" de 10 minutes est tagué "Voyage"
|
||||
Quand je POST /api/v1/listening-events
|
||||
"""json
|
||||
{
|
||||
"user_id": "user123",
|
||||
"content_id": "content789",
|
||||
"listened_duration_seconds": 300,
|
||||
"total_duration_seconds": 600,
|
||||
"completion_percentage": 50
|
||||
}
|
||||
"""
|
||||
Alors le statut de réponse est 201
|
||||
Et la réponse contient:
|
||||
"""json
|
||||
{
|
||||
"like_type": "automatic_standard",
|
||||
"gauge_updates": [
|
||||
{
|
||||
"category": "Voyage",
|
||||
"previous_value": 60,
|
||||
"delta": 1,
|
||||
"new_value": 61
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
Et en base de données, la jauge "Voyage" de "user123" est à 61%
|
||||
|
||||
Scénario: API applique like manuel explicite (+2%)
|
||||
Étant donné que l'utilisateur "user123" a une jauge "Musique" à 55% en base
|
||||
Et qu'un contenu "content999" est tagué "Musique"
|
||||
Quand je POST /api/v1/likes
|
||||
"""json
|
||||
{
|
||||
"user_id": "user123",
|
||||
"content_id": "content999",
|
||||
"like_type": "manual"
|
||||
}
|
||||
"""
|
||||
Alors le statut de réponse est 201
|
||||
Et la réponse contient:
|
||||
"""json
|
||||
{
|
||||
"like_id": "<uuid>",
|
||||
"gauge_updates": [
|
||||
{
|
||||
"category": "Musique",
|
||||
"previous_value": 55,
|
||||
"delta": 2,
|
||||
"new_value": 57
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
Et en base de données, la jauge "Musique" de "user123" est à 57%
|
||||
|
||||
Scénario: API applique unlike (retire like manuel)
|
||||
Étant donné que l'utilisateur "user123" a une jauge "Sport" à 57% en base
|
||||
Et qu'il a liké manuellement le contenu "content888" tagué "Sport"
|
||||
Et que le like a l'ID "like_abc123"
|
||||
Quand je DELETE /api/v1/likes/like_abc123
|
||||
Alors le statut de réponse est 204
|
||||
Et en base de données, la jauge "Sport" de "user123" est à 55%
|
||||
Et le like "like_abc123" est supprimé de la table likes
|
||||
|
||||
Scénario: API refuse unlike d'un like automatique
|
||||
Étant donné que l'utilisateur "user123" a écouté un contenu à 90%
|
||||
Et qu'il a reçu un like automatique "like_auto456"
|
||||
Quand je DELETE /api/v1/likes/like_auto456
|
||||
Alors le statut de réponse est 403
|
||||
Et la réponse contient:
|
||||
"""json
|
||||
{
|
||||
"error": "CANNOT_UNLIKE_AUTOMATIC",
|
||||
"message": "Les likes automatiques ne peuvent pas être retirés"
|
||||
}
|
||||
"""
|
||||
Et en base de données, le like "like_auto456" existe toujours
|
||||
|
||||
Scénario: API cumule like automatique + like manuel
|
||||
Étant donné que l'utilisateur "user123" a une jauge "Technologie" à 50% en base
|
||||
Et qu'un contenu "content777" de 10 minutes est tagué "Technologie"
|
||||
Quand je POST /api/v1/listening-events
|
||||
"""json
|
||||
{
|
||||
"user_id": "user123",
|
||||
"content_id": "content777",
|
||||
"completion_percentage": 50
|
||||
}
|
||||
"""
|
||||
Alors la jauge "Technologie" passe à 51% (+1% auto)
|
||||
Quand je POST ensuite /api/v1/likes
|
||||
"""json
|
||||
{
|
||||
"user_id": "user123",
|
||||
"content_id": "content777",
|
||||
"like_type": "manual"
|
||||
}
|
||||
"""
|
||||
Alors la jauge "Technologie" passe à 53% (+2% manuel)
|
||||
Et le delta total est de 3%
|
||||
|
||||
Scénario: API applique bonus abonnement créateur (+5% tous tags)
|
||||
Étant donné que l'utilisateur "user123" a les jauges suivantes:
|
||||
| catégorie | niveau |
|
||||
| Automobile | 50% |
|
||||
| Technologie | 45% |
|
||||
Et qu'un créateur "creator456" publie des contenus tagués "Automobile" et "Technologie"
|
||||
Quand je POST /api/v1/subscriptions
|
||||
"""json
|
||||
{
|
||||
"user_id": "user123",
|
||||
"creator_id": "creator456"
|
||||
}
|
||||
"""
|
||||
Alors le statut de réponse est 201
|
||||
Et en base de données:
|
||||
| catégorie | niveau |
|
||||
| Automobile | 55% |
|
||||
| Technologie | 50% |
|
||||
Et l'abonnement est créé avec bonus appliqué
|
||||
|
||||
Scénario: API retire bonus désabonnement créateur (-5% tous tags)
|
||||
Étant donné que l'utilisateur "user123" a les jauges suivantes:
|
||||
| catégorie | niveau |
|
||||
| Voyage | 65% |
|
||||
| Culture | 58% |
|
||||
Et qu'il est abonné au créateur "creator789" qui publie "Voyage" et "Culture"
|
||||
Quand je DELETE /api/v1/subscriptions/creator789
|
||||
Alors le statut de réponse est 204
|
||||
Et en base de données:
|
||||
| catégorie | niveau |
|
||||
| Voyage | 60% |
|
||||
| Culture | 53% |
|
||||
|
||||
Scénario: API applique pénalité skip rapide (<10s)
|
||||
Étant donné que l'utilisateur "user123" a une jauge "Politique" à 50% en base
|
||||
Et qu'un contenu "content555" de 300 secondes est tagué "Politique"
|
||||
Quand je POST /api/v1/skip-events
|
||||
"""json
|
||||
{
|
||||
"user_id": "user123",
|
||||
"content_id": "content555",
|
||||
"listened_duration_seconds": 5,
|
||||
"total_duration_seconds": 300
|
||||
}
|
||||
"""
|
||||
Alors le statut de réponse est 201
|
||||
Et la réponse contient:
|
||||
"""json
|
||||
{
|
||||
"skip_type": "early",
|
||||
"gauge_updates": [
|
||||
{
|
||||
"category": "Politique",
|
||||
"previous_value": 50,
|
||||
"delta": -0.5,
|
||||
"new_value": 49.5
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
Et en base de données, la jauge "Politique" de "user123" est à 49.5%
|
||||
|
||||
Scénario: API n'applique pas de pénalité pour skip ≥10s et <30%
|
||||
Étant donné que l'utilisateur "user123" a une jauge "Économie" à 60% en base
|
||||
Et qu'un contenu "content333" de 600 secondes est tagué "Économie"
|
||||
Quand je POST /api/v1/skip-events
|
||||
"""json
|
||||
{
|
||||
"user_id": "user123",
|
||||
"content_id": "content333",
|
||||
"listened_duration_seconds": 120,
|
||||
"total_duration_seconds": 600,
|
||||
"completion_percentage": 20
|
||||
}
|
||||
"""
|
||||
Alors le statut de réponse est 201
|
||||
Et la réponse contient:
|
||||
"""json
|
||||
{
|
||||
"skip_type": "neutral",
|
||||
"gauge_updates": []
|
||||
}
|
||||
"""
|
||||
Et en base de données, la jauge "Économie" de "user123" reste à 60%
|
||||
|
||||
Scénario: API n'applique pas de pénalité pour skip ≥30%
|
||||
Étant donné que l'utilisateur "user123" a une jauge "Sport" à 55% en base
|
||||
Et qu'un contenu "content222" de 600 secondes est tagué "Sport"
|
||||
Quand je POST /api/v1/skip-events
|
||||
"""json
|
||||
{
|
||||
"user_id": "user123",
|
||||
"content_id": "content222",
|
||||
"listened_duration_seconds": 300,
|
||||
"total_duration_seconds": 600,
|
||||
"completion_percentage": 50
|
||||
}
|
||||
"""
|
||||
Alors le statut de réponse est 201
|
||||
Et la réponse contient:
|
||||
"""json
|
||||
{
|
||||
"skip_type": "late",
|
||||
"gauge_updates": []
|
||||
}
|
||||
"""
|
||||
Et en base de données, la jauge "Sport" de "user123" reste à 55%
|
||||
|
||||
Scénario: API applique évolution sur plusieurs tags simultanément
|
||||
Étant donné que l'utilisateur "user123" a les jauges suivantes:
|
||||
| catégorie | niveau |
|
||||
| Automobile | 45% |
|
||||
| Voyage | 60% |
|
||||
Et qu'un contenu "content111" est tagué "Automobile" et "Voyage"
|
||||
Quand je POST /api/v1/listening-events
|
||||
"""json
|
||||
{
|
||||
"user_id": "user123",
|
||||
"content_id": "content111",
|
||||
"completion_percentage": 90
|
||||
}
|
||||
"""
|
||||
Alors le statut de réponse est 201
|
||||
Et la réponse contient:
|
||||
"""json
|
||||
{
|
||||
"like_type": "automatic_reinforced",
|
||||
"gauge_updates": [
|
||||
{
|
||||
"category": "Automobile",
|
||||
"previous_value": 45,
|
||||
"delta": 2,
|
||||
"new_value": 47
|
||||
},
|
||||
{
|
||||
"category": "Voyage",
|
||||
"previous_value": 60,
|
||||
"delta": 2,
|
||||
"new_value": 62
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
Et en base de données:
|
||||
| catégorie | niveau |
|
||||
| Automobile | 47% |
|
||||
| Voyage | 62% |
|
||||
|
||||
Scénario: API respecte la borne maximum 100%
|
||||
Étant donné que l'utilisateur "user123" a une jauge "Cryptomonnaie" à 99% en base
|
||||
Et qu'un contenu "content_crypto" est tagué "Cryptomonnaie"
|
||||
Quand je POST /api/v1/listening-events
|
||||
"""json
|
||||
{
|
||||
"user_id": "user123",
|
||||
"content_id": "content_crypto",
|
||||
"completion_percentage": 95
|
||||
}
|
||||
"""
|
||||
Alors le statut de réponse est 201
|
||||
Et la réponse contient:
|
||||
"""json
|
||||
{
|
||||
"like_type": "automatic_reinforced",
|
||||
"gauge_updates": [
|
||||
{
|
||||
"category": "Cryptomonnaie",
|
||||
"previous_value": 99,
|
||||
"delta": 2,
|
||||
"new_value": 100,
|
||||
"capped": true
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
Et en base de données, la jauge "Cryptomonnaie" de "user123" est à 100%
|
||||
Et la jauge n'a pas dépassé 100%
|
||||
|
||||
Scénario: API respecte la borne minimum 0%
|
||||
Étant donné que l'utilisateur "user123" a une jauge "Politique" à 0.3% en base
|
||||
Et qu'un contenu "content_pol" est tagué "Politique"
|
||||
Quand je POST /api/v1/skip-events
|
||||
"""json
|
||||
{
|
||||
"user_id": "user123",
|
||||
"content_id": "content_pol",
|
||||
"listened_duration_seconds": 3,
|
||||
"total_duration_seconds": 300
|
||||
}
|
||||
"""
|
||||
Alors le statut de réponse est 201
|
||||
Et la réponse contient:
|
||||
"""json
|
||||
{
|
||||
"skip_type": "early",
|
||||
"gauge_updates": [
|
||||
{
|
||||
"category": "Politique",
|
||||
"previous_value": 0.3,
|
||||
"delta": -0.5,
|
||||
"new_value": 0,
|
||||
"capped": true
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
Et en base de données, la jauge "Politique" de "user123" est à 0%
|
||||
Et la jauge n'est pas devenue négative
|
||||
|
||||
Scénario: API respecte borne minimum lors désabonnement
|
||||
Étant donné que l'utilisateur "user123" a une jauge "Économie" à 3% en base
|
||||
Et qu'il est abonné au créateur "creator_eco" qui publie "Économie"
|
||||
Quand je DELETE /api/v1/subscriptions/creator_eco
|
||||
Alors le statut de réponse est 204
|
||||
Et en base de données, la jauge "Économie" de "user123" est à 0% (et non -2%)
|
||||
|
||||
Scénario: API GET retourne toutes les jauges utilisateur
|
||||
Étant donné que l'utilisateur "user123" a les jauges suivantes en base:
|
||||
| catégorie | niveau |
|
||||
| Automobile | 67% |
|
||||
| Voyage | 82% |
|
||||
| Économie | 34% |
|
||||
| Sport | 50% |
|
||||
| Musique | 45% |
|
||||
| Technologie | 71% |
|
||||
Quand je GET /api/v1/users/user123/interest-gauges
|
||||
Alors le statut de réponse est 200
|
||||
Et la réponse contient les 12 catégories avec leurs niveaux:
|
||||
"""json
|
||||
{
|
||||
"user_id": "user123",
|
||||
"gauges": [
|
||||
{"category": "Automobile", "level": 67},
|
||||
{"category": "Voyage", "level": 82},
|
||||
{"category": "Économie", "level": 34},
|
||||
{"category": "Sport", "level": 50},
|
||||
{"category": "Musique", "level": 45},
|
||||
{"category": "Technologie", "level": 71}
|
||||
]
|
||||
}
|
||||
"""
|
||||
|
||||
Scénario: API calcule évolution immédiate (pas de batch différé)
|
||||
Étant donné que l'utilisateur "user123" a une jauge "Voyage" à 50% en base
|
||||
Quand je POST /api/v1/listening-events à 12:00:00
|
||||
"""json
|
||||
{
|
||||
"user_id": "user123",
|
||||
"content_id": "content_travel",
|
||||
"completion_percentage": 85
|
||||
}
|
||||
"""
|
||||
Alors le statut de réponse est 201
|
||||
Quand je GET /api/v1/users/user123/interest-gauges à 12:00:01 (1 seconde après)
|
||||
Alors la jauge "Voyage" est à 52%
|
||||
Et la mise à jour est visible immédiatement
|
||||
|
||||
Scénario: API rejette token JWT invalide
|
||||
Quand je POST /api/v1/listening-events sans token JWT
|
||||
Alors le statut de réponse est 401
|
||||
Et la réponse contient:
|
||||
"""json
|
||||
{
|
||||
"error": "UNAUTHORIZED",
|
||||
"message": "Token JWT manquant ou invalide"
|
||||
}
|
||||
"""
|
||||
|
||||
Scénario: API valide format des données d'entrée
|
||||
Quand je POST /api/v1/listening-events
|
||||
"""json
|
||||
{
|
||||
"user_id": "user123",
|
||||
"content_id": "content456",
|
||||
"completion_percentage": 150
|
||||
}
|
||||
"""
|
||||
Alors le statut de réponse est 400
|
||||
Et la réponse contient:
|
||||
"""json
|
||||
{
|
||||
"error": "VALIDATION_ERROR",
|
||||
"message": "completion_percentage doit être entre 0 et 100"
|
||||
}
|
||||
"""
|
||||
|
||||
Scénario: API gère contenu avec tags inexistants en base
|
||||
Étant donné qu'un contenu "content_new" est tagué "NouvelleCategorie" (non encore en base)
|
||||
Quand je POST /api/v1/listening-events
|
||||
"""json
|
||||
{
|
||||
"user_id": "user123",
|
||||
"content_id": "content_new",
|
||||
"completion_percentage": 90
|
||||
}
|
||||
"""
|
||||
Alors le statut de réponse est 201
|
||||
Et une nouvelle ligne est créée dans la table interest_gauges:
|
||||
| user_id | category | level |
|
||||
| user123 | NouvelleCategorie | 52 |
|
||||
Et l'initialisation démarre à 50% + 2% de like auto = 52%
|
||||
|
||||
Scénario: API persiste historique des modifications de jauges
|
||||
Étant donné que l'utilisateur "user123" a une jauge "Sport" à 50%
|
||||
Quand je POST /api/v1/listening-events qui applique +2%
|
||||
Alors une ligne est insérée dans interest_gauge_history:
|
||||
| user_id | category | previous_value | delta | new_value | event_type | event_id | timestamp |
|
||||
| user123 | Sport | 50 | 2 | 52 | listening_event| <event_uuid> | 2026-02-02T12:00:00 |
|
||||
Et cet historique permet d'auditer les évolutions
|
||||
|
||||
Scénario: API retourne métriques d'évolution utilisateur
|
||||
Étant donné que l'utilisateur "user123" a un historique d'évolution en base
|
||||
Quand je GET /api/v1/users/user123/interest-gauges/evolution?since=7d
|
||||
Alors le statut de réponse est 200
|
||||
Et la réponse contient:
|
||||
"""json
|
||||
{
|
||||
"period": "7d",
|
||||
"evolution": [
|
||||
{
|
||||
"category": "Automobile",
|
||||
"start_value": 60,
|
||||
"end_value": 67,
|
||||
"delta": 7,
|
||||
"events_count": 15
|
||||
},
|
||||
{
|
||||
"category": "Voyage",
|
||||
"start_value": 80,
|
||||
"end_value": 82,
|
||||
"delta": 2,
|
||||
"events_count": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
|
||||
# Architecture backend - Services séparés
|
||||
|
||||
Scénario: Gauge Calculation Service calcule l'ajustement (stateless)
|
||||
Étant donné un événement d'écoute avec 85% de complétion
|
||||
Quand le Gauge Calculation Service calcule l'ajustement
|
||||
Alors le service retourne:
|
||||
"""json
|
||||
{
|
||||
"adjustment_type": "automatic_reinforced",
|
||||
"adjustment_value": 2.0,
|
||||
"reason": "completion_percentage >= 80%"
|
||||
}
|
||||
"""
|
||||
Et le service est stateless (aucune lecture DB)
|
||||
Et le service est testable unitairement
|
||||
|
||||
Scénario: Gauge Update Service applique l'ajustement (stateful)
|
||||
Étant donné qu'un ajustement de +2% a été calculé
|
||||
Et que la jauge "Automobile" de "user123" est à 45%
|
||||
Quand le Gauge Update Service applique l'ajustement
|
||||
Alors la nouvelle valeur est 47% (45 + 2)
|
||||
Et la borne [0, 100] est respectée via fonction clamp
|
||||
Et la mise à jour est persistée en Redis (immédiat)
|
||||
Et la mise à jour est persistée en PostgreSQL (batch async)
|
||||
|
||||
Scénario: Pattern de calcul - Addition de points absolus
|
||||
Étant donné qu'une jauge est à 60%
|
||||
Et qu'un ajustement de +2% est calculé
|
||||
Quand le calcul est effectué
|
||||
Alors la formule est: newValue = currentValue + adjustment
|
||||
Et la formule est: newValue = clamp(newValue, 0.0, 100.0)
|
||||
Et la nouvelle valeur est 62%
|
||||
|
||||
Scénario: Pattern de calcul - Éviter multiplication relative
|
||||
Étant donné qu'une jauge est à 50%
|
||||
Et qu'un ajustement de +2% est calculé
|
||||
Quand le calcul est effectué
|
||||
Alors la formule utilisée est: 50 + 2 = 52
|
||||
Et la formule utilisée n'est PAS: 50 * (1 + 2/100) = 51
|
||||
Car l'ajustement est en points absolus, pas relatifs
|
||||
|
||||
Scénario: Multi-tags - Mise à jour de N jauges simultanément
|
||||
Étant donné qu'un contenu a 3 tags: ["Automobile", "Voyage", "Technologie"]
|
||||
Et qu'un ajustement de +2% est calculé (écoute 85%)
|
||||
Quand le Gauge Update Service applique
|
||||
Alors 3 jauges sont mises à jour:
|
||||
| catégorie | ajustement |
|
||||
| Automobile | +2% |
|
||||
| Voyage | +2% |
|
||||
| Technologie | +2% |
|
||||
Et toutes les mises à jour sont effectuées en une seule transaction
|
||||
|
||||
Scénario: Persistance Redis immédiate (latence <10ms)
|
||||
Étant donné qu'un ajustement doit être persisté
|
||||
Quand le Gauge Update Service écrit en Redis
|
||||
Alors la latence est < 10ms
|
||||
Et la jauge est immédiatement disponible pour recommandations
|
||||
Et Redis sert de cache haute performance
|
||||
|
||||
Scénario: Persistance PostgreSQL asynchrone (batch 5 min)
|
||||
Étant donné que 100 ajustements ont été appliqués en Redis
|
||||
Quand le batch async s'exécute toutes les 5 minutes
|
||||
Alors les 100 ajustements sont écrits en PostgreSQL en batch
|
||||
Et la cohérence finale est garantie
|
||||
Et l'application reste performante (pas de write sync)
|
||||
|
||||
Scénario: Séparation responsabilités - Calculation vs Update
|
||||
Étant donné un événement d'écoute
|
||||
Quand il est traité
|
||||
Alors le Gauge Calculation Service calcule l'ajustement (logique métier pure)
|
||||
Et le Gauge Update Service applique l'ajustement (persistance)
|
||||
Et les deux services sont indépendants
|
||||
Et chaque service a une responsabilité unique (SRP)
|
||||
|
||||
Scénario: Réutilisabilité Calculation Service
|
||||
Étant donné le Gauge Calculation Service
|
||||
Quand il est utilisé pour:
|
||||
| contexte |
|
||||
| Like automatique |
|
||||
| Skip rapide |
|
||||
| Like manuel |
|
||||
| Abonnement créateur |
|
||||
Alors le même service calcule tous les ajustements
|
||||
Et la logique métier est centralisée
|
||||
Et il n'y a pas de duplication de code
|
||||
Reference in New Issue
Block a user