Dependency Breakers: Identifier et Briser les Dépendances Problématiques

🔗 Dependency Breakers: Identifier et Briser les Dépendances Problématiques

Introduction

Toute architecture complexe accumule des dépendances. Mais pas toutes les dépendances sont bonnes. Certaines deviennent problématiques : elles ralentissent, bloquent, créent du risque, ou violent l’autonomie des équipes.

Ce guide vous aide à :

  1. Identifier les dépendances problématiques
  2. Comprendre pourquoi elles posent problème
  3. Appliquer des patterns pour les “briser” (dependency breakers)

Partie 1: Diagnostiquer les Dépendances Problématiques

Qu’est-ce qu’une Dépendance Problématique?

Une dépendance est problématique si elle a une ou plusieurs de ces caractéristiques:

🔴 CRITÈRE 1: Trop Fréquente
   └─ Appels synchrones constants
   └─ Blocage : "A attend B"
   └─ Exemple: API appelée 100x par jour

🔴 CRITÈRE 2: Non Documentée
   └─ Personne ne sait vraiment qu'elle existe
   └─ Découverte à la production
   └─ Exemple: Lecture directe de la DB d'une autre équipe

🔴 CRITÈRE 3: Unidirectionnelle Implicite
   └─ Il y a une hiérarchie cache (qui dépend de qui?)
   └─ Pas de gouvernance claire
   └─ Exemple: "On appelle le legacy quand on a besoin"

🔴 CRITÈRE 4: Synchrone & Critique
   └─ Si la dépendance casse, tout casse
   └─ Pas de fallback
   └─ Exemple: "Si Catalog n'est pas up, rien ne marche"

🔴 CRITÈRE 5: Risque Élevé
   └─ Changements in dépendance cassent tout
   └─ Long cycle de troubleshooting
   └─ Exemple: Changement model upstream = jours de debugging

🔴 CRITÈRE 6: Equipe Bloquée
   └─ Une équipe ne peut pas progresser sans l'autre
   └─ Calendriers forcés de se synchroniser
   └─ Exemple: Deploy impossible sans approval de l'autre équipe

Matrice de Sévérité

Classifiez chaque dépendance sur 2 axes:

            Impact Élevé    |  Impact Moyen   |  Impact Bas
Fréquence  |   CRITIQUE      |   ÉLEVÉ         |  ACCEPTABLE
Élevée     |                 |                 |
-----------|-----------------|-----------------|------------
Fréquence  |   ÉLEVÉ        |   MOYEN         |  ACCEPTABLE
Moyenne    |                 |                 |
-----------|-----------------|-----------------|------------
Fréquence  |   MOYEN        |   MOYEN         |  ACCEPTABLE
Basse      |                 |                 |
-----------|-----------------|-----------------|------------

CRITICAL = Dépendance synchrone, fréquente, non documentée
           = HIGHEST PRIORITY pour un dependency breaker

ÉLEVÉ = Fréquente OU impactful
        = À adresser rapidement

ACCEPTABLE = Peut exister comme est

Exercice: Audit de Vos Dépendances

Pour chaque paire d’équipes, posez-vous:

1. Existe-t-il une dépendance?
   └─ OUI → Continuer
   └─ NON → Rien à faire

2. C'est synchrone ou asynchrone?
   └─ Synchrone (blocage immédiat) = PLUS problématique
   └─ Asynchrone (peut attendre) = MOINS problématique

3. Combien de fois par jour?
   └─ >50 fois = Très fréquent
   └─ 10-50 fois = Fréquent
   └─ <10 fois = Pas très souvent

4. Qu'arrive-t-il si la dépendance casse?
   └─ Tout casse = CRITIQUE
   └─ Service degraded = Élevé
   └─ Quelques users affectés = Acceptable

5. Comment la dépendance est documentée?
   └─ Bien documentée = Bon
   └─ Pas documentée = ROUGE FLAG

6. Y a-t-il une équipe qui attend l'autre?
   └─ OUI = Problème d'équipe
   └─ NON = Problème seulement technique

Partie 2: Les Types de Dependency Breakers

Type 1: Le “Decoupling Pattern”

Objectif: Transformer dépendance synchrone → asynchrone

Pattern: Event-Driven Communication

AVANT (synchrone, bloquant):
  Order Service
      ↓ (HTTP call)
      ↓ (wait for response)
  Inventory Service

PROBLÈME:
  ❌ Order Service bloquée si Inventory n'est pas up
  ❌ Inventory bottleneck
  ❌ Tightly coupled

APRÈS (event-driven, asynchrone):
  Order Service
      ↓ (publie event: OrderPlaced)
      ↓
  Event Queue (Kafka)
      ↓
  Inventory Service (écoute asynchrone)

BÉNÉFICES:
  ✓ Order Service pas bloquée
  ✓ Inventory peut être down, va rattraper
  ✓ Loosely coupled
  ✓ Chacun peut évoluer indépendamment

Pattern à appliquer: Published Language avec events


Pattern: Cache & Async Sync

AVANT (synchrone):
  Recommendation Service
      ↓ (appelle Catalog à chaque request)
  Catalog Service

PROBLÈME:
  ❌ 1000 calls/min si 1000 users
  ❌ Latence: Chaque reco attendait Catalog
  ❌ Catalog surchargé

APRÈS (cache + async sync):
  Recommendation Service
      ├─ Cache local de Product data
      ├─ Répond depuis cache (instant!)
      └─ Sync background thread met à jour le cache
                ↓
           Catalog publishes ProductUpdated events
           Recommendation recharge le cache

BÉNÉFICES:
  ✓ 0 latency pour reco
  ✓ Pas de load sur Catalog
  ✓ Eventual consistency acceptable

Quand utiliser:

  • Données qui changent lentement (products, config)
  • Eventual consistency acceptable (reco peut être 1h old)
  • Lecture intensive

Pattern: Batch Processing

AVANT (synchrone):
  Analytics Service
      ↓ (pulls data from every service)
  10 services

PROBLÈME:
  ❌ Centaines de queries par jour
  ❌ Touts les services affectés
  ❌ Trop de dépendances

APRÈS (batch):
  10 services
      ↓ (nightly batch export)
      ↓
  Data Lake
      ↓ (Analytics lit le next day)
  Analytics Service

BÉNÉFICES:
  ✓ Prévisible (tous les soirs)
  ✓ Bulk efficient
  ✓ Services indépendants pendant le jour
  ✓ Analytics peut être en maintenance

Quand utiliser:

  • Reporting/Analytics (delay acceptable)
  • Batch operations
  • Heavy data imports

Type 2: Le “Bubble Context” (Isolation Layer)

Objectif: Protéger votre contexte de dépendance external/legacy

AVANT (exposé au chaos):
  Your Service (propre)
      ↓ (appelle directement)
  Legacy System (Big Ball Of Mud)

PROBLÈME:
  ❌ Legacy peut casser votre service
  ❌ Vous devez gérer la complexité legacy
  ❌ Vous ne pouvez pas évoluer indépendamment

APRÈS (bubble context):
  Your Service (propre)
      ↓ (API propre)
  Bubble Context (adapts your model ↔ legacy)
      ├─ ACL (Anticorruption Layer)
      ├─ Traduction
      └─ Abstraction des détails
      ↓
  Legacy System (Big Ball Of Mud)

BÉNÉFICES:
  ✓ Votre code reste propre
  ✓ Legacy isolé
  ✓ Vous pouvez remplacer legacy sans impact
  ✓ Progression possible

Pattern à appliquer: Anticorruption Layer


Type 3: Le “Domain Decoupling”

Objectif: Si deux domaines sont trop couplés, séparer

AVANT (couplé):
  Order Context = Order + Billing entrelacées
      ├─ Create Order
      ├─ Create Invoice
      ├─ Process Payment
      └─ Update Shipment
      
PROBLÈME:
  ❌ Si Payment change, Order casse
  ❌ Si Invoice format change, Order impact
  ❌ Complexité monolithe

APRÈS (séparation):
  Order Context
      ├─ Order aggregate
      ├─ Publishe events: OrderPlaced, OrderPaid
      └─ Zéro connaissance du Billing
  
  Billing Context
      ├─ Invoice aggregate
      ├─ Écoute OrderPlaced
      ├─ Crée la facture
      └─ Zéro couplage avec Order logic
  
  Payment Context
      ├─ Payment aggregate
      └─ Asynchrone

BÉNÉFICES:
  ✓ Contextes indépendants
  ✓ Chacun peut évoluer
  ✓ Testable indépendamment
  ✓ Réutilisable (Payment pour autres contextes)

Pattern à appliquer: Separate Ways ou event-driven


Type 4: Le “Organizational Alignment”

Objectif: Aligner la structure d’équipe avec les contextes

AVANT (misaligned):
  Backend Team (Order + Billing + Inventory)
      ↓ (3 domaines, 1 équipe)
  Frontend Team (UI)
      ↓ (depends strongly on Backend)

PROBLÈME:
  ❌ Backend bottleneck (3 domaines complexes)
  ❌ Frontend bloquée par Backend
  ❌ Pas d'ownership clair

APRÈS (aligned):
  Order Team owns Order Service
      ↓
  Billing Team owns Billing Service
      ↓
  Inventory Team owns Inventory Service
      ↓
  Frontend Team (consomme APIs)

  Dépendance: Frontend ← Order/Billing/Inventory
  (Mais Frontend ne connaît que les APIs, pas l'implémentation)

BÉNÉFICES:
  ✓ Ownership clair
  ✓ Chaque équipe pas surchargée
  ✓ Frontend peut avancer parallèlement
  ✓ Faster deployment cycles

Pattern à appliquer: Team Topologies + alignment


Type 5: Le “API Versioning & Stability”

Objectif: Briser la dépendance à “breaking changes”

AVANT (breaking changes):
  V1 of Catalog API
      ↓
  3 consumers, tous cassés si Catalog change

PROBLÈME:
  ❌ Pas de stabilité
  ❌ Coordination ncessaire pour chaque change
  ❌ Lent à déployer

APRÈS (versioning):
  V1 of Catalog API (deprecated in 3 months)
  V2 of Catalog API (new)
      ↓
  Consumers migrer progressivement
      ↓
  Each consumer peut choisir quand migrer

  Timing:
  - Month 1: V2 launched, V1 still working
  - Month 2: V2 recommended, V1 still works
  - Month 3: V2 required, V1 EOL

BÉNÉFICES:
  ✓ Consumers pas forcés
  ✓ Graduelle migration
  ✓ Breaker des breaking changes
  ✓ More autonomy per team

Pattern à appliquer: Published Language avec versioning


Type 6: Le “Strangler Pattern”

Objectif: Briser les dépendances progressivement du Legacy

AVANT (tightly coupled au Legacy):
  Legacy Monolith
      ↓ (everything inside)
      ↓ (hard to extract)

APRÈS (Strangler):
  Year 1:
    └─ Extract Service A → Strangler routes A → New Service
       Legacy still handles B, C, D, E
  
  Year 2:
    ├─ Extract Service B
    ├─ Extract Service C
    └─ Legacy now handles D, E
  
  Year 3:
    ├─ Extract Service D
    ├─ Extract Service E
    └─ Legacy completely replaced!

BÉNÉFICES:
  ✓ Graduelle, no big bang
  ✓ Low risk
  ✓ Continuous value delivery
  ✓ Lernen along the way

Pattern à appliquer: Separate Ways + Anticorruption Layer


Partie 3: Sélectionner le Bon Dependency Breaker

Decision Tree

Q1: La dépendance est synchrone ou asynchrone?

├─ SYNCHRONE (bloquante)
│  └─ Q2: Peut-elle devenir asynchrone?
│     ├─ OUI → Event-Driven (Type 1)
│     │         ou Batch (Type 1)
│     │
│     └─ NON (vraiment besoin synchrone)
│        └─ Q3: C'est un appel fréquent ou rare?
│           ├─ FRÉQUENT → Cache + Async Sync (Type 1)
│           └─ RARE → Acceptable, laisser synchrone
│
└─ ASYNCHRONE (ok)
   └─ Q2: C'est du chaos ou du chaos isolé?
      ├─ CHAOS GLOBAL (Big Ball Of Mud)
      │  └─ Bubble Context + ACL (Type 2)
      │
      └─ CHAOS ISOLÉ (Legacy, specific service)
         └─ ACL ou Strangler (Type 2 + 6)

Partie 4: Mise en Pratique - Exemples Complets

Example 1: E-commerce - Réduire Load Catalog

Situation:

  • Catalog Service surcharges (5000 req/min)
  • Pricing, Inventory, Search, Recommendation tous appellent Catalog synchrone
  • Latency: 500ms par request

Diagnostic:

Dépendance: Synchrone, très fréquente, critique
Sévérité: CRITIQUE
Cause: Tout appelle Catalog directement

Dependency Breaker: Cache + Event Sync (Type 1)

Avant:
  Pricing Service → [HTTP] → Catalog (5000 req/min)
  Inventory Service → [HTTP] → Catalog
  Recommendation Service → [HTTP] → Catalog
  Search Service → [HTTP] → Catalog

Après:
  Pricing Service
    ├─ Cache local de Products
    ├─ Consulte cache (instant!)
    └─ Background thread écoute ProductUpdated events

  Inventory Service
    ├─ Cache local de Products
    └─ Async sync via events

  Recommendation Service
    ├─ Cache local de Products
    └─ Lazy refresh

  Catalog Service
    ├─ Publie ProductUpdated events
    └─ Load reduit de 80%!

Résultats:
  ✓ Catalog: 5000 → 1000 req/min
  ✓ Latency: 500ms → 0ms (cache hit)
  ✓ Resilience: Si Catalog down, tout continue

Example 2: Frontend Blockade Breaking

Situation:

  • Frontend Team bloquée par Backend Team
  • Chaque feature Frontend attend Backend API
  • Deploy impossible sans coordination

Diagnostic:

Dépendance: Synchrone, fréquente, organizational blocker
Sévérité: ÉLEVÉ + ORGANIZATIONAL
Cause: Tight coordination requirement

Dependency Breaker: Organizational Alignment (Type 4)

BEFORE:
  Frontend Team → Waits → Backend Team (Order+Billing+Inventory)
                              ↓ 
                         Backend overloaded (3 domains)
                              ↓
                         Frontend blocked

AFTER:
  Frontend Team → Consumes APIs from:
    ├─ Order Team (Order Service)
    ├─ Billing Team (Billing Service)
    └─ Inventory Team (Inventory Service)

  Each Backend Team:
    ├─ Owns ONE domain
    ├─ Deploys independently
    └─ Faster iterations

  Dependency still exists (Frontend needs Order),
  but it's not a blocker anymore (Order Service API stable, versioned)

Example 3: Legacy System Strangling

Situation:

  • 10 year old monolith
  • Everything tightly coupled
  • Want to extract services progressively

Diagnostic:

Dépendance: Everything depends on Legacy
Sévérité: CRITICAL (but known, not emergency)
Cause: Monolith over time

Dependency Breaker: Strangler + ACL (Type 2 + 6)

PHASE 1 (Month 1-3):
  Identify Service A (e.g., Payment Processing)
  Create Payment Service (new, clean)
  Create Strangler (router):
    ├─ New requests → Payment Service
    └─ Old requests → Legacy
  
  Deploy new architecture
  Monitor, verify

PHASE 2 (Month 4-6):
  Extract Service B (e.g., Catalog)
  Same pattern: New Service + Strangler
  
PHASE 3 (Month 7-12):
  Extract Service C, D, E...
  
END STATE:
  All services extracted
  Legacy completely bypassed
  Old monolith = archived data only

Partie 5: Checklist d’Implementation

Avant d’Implémenter un Dependency Breaker

Diagnostic
├─ [ ] Identifié la dépendance problématique
├─ [ ] Mesuré: fréquence, impact, sévérité
├─ [ ] Compris la racine cause
├─ [ ] Impliqué l'équipe dépendante
└─ [ ] Documenté le problème

Design
├─ [ ] Sélectionné le dependency breaker (type 1-6)
├─ [ ] Validé avec les deux équipes
├─ [ ] Estimé l'effort et la complexité
├─ [ ] Identifié les risques
└─ [ ] Planifié les étapes

Implementation
├─ [ ] Créé un prototype
├─ [ ] Testé avec un petit sous-ensemble
├─ [ ] Vérifié la performance améliorée
├─ [ ] Mesuré l'impact réel
└─ [ ] Documenté pour les mainteneurs

Rollout
├─ [ ] Migré progressivement (pas big bang)
├─ [ ] Gardé l'ancienne dépendance en fallback
├─ [ ] Monitored la stabilité
├─ [ ] Alertes en place
└─ [ ] Support team éducated

Post-Implementation
├─ [ ] Mesuré les améliorations (latency, throughput, autonomy)
├─ [ ] Collecté le feedback des équipes
├─ [ ] Documenté les leçons apprises
├─ [ ] Célébré le succès!
└─ [ ] Planifié le prochain dependency breaker

Ressources


Créé pour: Architectes et facilitateurs aidant à briser des dépendances problématiques
Version: 1.0
Licence: CC-BY-SA