Carte Context Mapping #2 : Anticorruption Layer
📇 Carte #2 : Anticorruption Layer (ACL)
Vue Rapide
🎯 Objectif : L’équipe downstream crée une couche d’isolation pour protéger son modèle
👥 Relation d’équipe : Upstream/Downstream (asymétrique)
📊 Couplage : Bas (isolation complète)
Concept
L’équipe downstream crée une couche de traduction (ACL) qui :
- Traduit le modèle upstream en modèle downstream
- Isole le domaine downstream des changements upstream
- Protège l’indépendance du downstream
Upstream (modèle compliqué/différent)
↓
Anticorruption Layer (translation)
↓
Downstream (modèle propre et indépendant)
Quand l’Utiliser ? ✅
- ✅ Les modèles upstream et downstream sont radicalement différents
- ✅ Vous voulez protéger votre domaine des pollutions upstream
- ✅ L’upstream change fréquemment ou est mal conçu
- ✅ Vous avez besoin d’indépendance maximale
- ✅ L’interface upstream est imposée et immuable
Exemples
- Legacy System Integration : Intégrer un vieux système avec ACL
- Third-party API : Adapter une API externe à votre domaine
- Big Ball Of Mud : Isoler votre domaine du chaos upstream
Quand l’Éviter ? ❌
- ❌ L’interface upstream est simple et stable
- ❌ Vous pouvez vous permettre d’adopter le modèle upstream (Conformist)
- ❌ La complexité de traduction est excessive
- ❌ Vous avez besoin de synchronisation temps-réel très serrée
Questions Clés à se Poser 💭
- Le modèle upstream pollue-t-il notre domaine ?
- Pouvons-nous nous permettre de créer une couche de traduction ?
- La traduction est-elle complexe ou simple ?
- Comment maintenons-nous la synchronisation entre les deux modèles ?
- Où plaçons-nous l’ACL : au niveau de l’équipe ou du service ?
Implications pour l’Équipe Downstream
Responsabilités
- ✓ Concevoir l’ACL : mapper upstream → downstream
- ✓ Maintenir l’ACL : gérer les évolutions upstream
- ✓ Documenter les mappings : pourquoi cette traduction ?
- ✓ Tester l’ACL : validation des conversions
Avantages
- ✓ Indépendance totale : votre domaine est protégé
- ✓ Flexibilité : vous pouvez changer sans affecter l’upstream
- ✓ Clarté : votre code est clair, la traduction est centralisée
- ✓ Évolutivité : remplacer upstream ne casse pas votre logique
Risques
- ⚠️ Complexité : maintenir une couche de traduction
- ⚠️ Performance : la traduction peut avoir un coût
- ⚠️ Synchronisation : gérer les changements upstream
- ⚠️ Duplication : code de mapping qui peut devenir lourd
Patterns de Traduction Courants
1. Mapping Simple
Upstream: Order { items: [], total: 0 }
↓
ACL: convertOrderToOurModel()
↓
Downstream: PurchaseOrder { lineItems: [], grossAmount: 0 }
2. Enrichissement
Upstream: minimal data
↓
ACL: enrichir avec contexte (user, country, etc.)
↓
Downstream: complete domain object
3. Agrégation
Upstream 1: User data
Upstream 2: Address data
↓
ACL: combiner les sources
↓
Downstream: Customer aggregate
4. Transformation
Upstream: Legacy format
↓
ACL: parser, validator, transformer
↓
Downstream: Modern format
Exemple Concret : Integration d’un Legacy System
Contexte Downstream : Nouvelle Commande Service
Votre domaine clair et moderne :
class Order {
orderId: uuid
customer: Customer
items: OrderItem[]
status: OrderStatus
createdAt: Timestamp
}
Contexte Upstream : Vieux Système (Big Ball Of Mud)
LEGACY_ORD {
ORD_ID: string (format bizarre)
ORD_CUST: string (mélange nom/email)
ORD_ITEMS: delimited string
ORD_STAT: numeric code (0=pending, 1=confirmed...)
ORD_DATE: yyyymmdd
}
Anticorruption Layer
class LegacyOrderTranslator {
toNewOrder(legacyOrder: LEGACY_ORD): Order {
return new Order(
orderId: parseUuid(legacyOrder.ORD_ID),
customer: parseCustomer(legacyOrder.ORD_CUST),
items: parseItems(legacyOrder.ORD_ITEMS),
status: mapLegacyStatus(legacyOrder.ORD_STAT),
createdAt: parseDate(legacyOrder.ORD_DATE)
)
}
}
Emplacement de l’ACL
Option 1 : Dans le Service Downstream
Downstream Service
├── Controllers
├── Domain
├── Application
└── Adapters
└── LegacyOrderTranslator (ACL)
Option 2 : Service Dédié (Strangler Pattern)
Upstream (Legacy)
↓
ACL Service (Adapter)
↓
Downstream Service
Intégration avec Context Mapping
Relations d’Équipe
Legacy System Team (Upstream)
↓ (interface imposée et sale)
Anticorruption Layer (gérée par notre équipe)
↓ (propre et prévisible)
New Service Team (Downstream - indépendant)
Stratégies Connexes
- Strangler Pattern : Remplacer progressivement le legacy
- Bubble Context : Isoler pendant la migration
Checklist de Mise en Place ✓
- Vous avez clairement identifié ce qui doit être traduit
- La complexité de traduction est acceptable
- Vous avez une équipe dédiée pour maintenir l’ACL
- Les mappings sont documentés avec justifications
- Vous avez des tests pour valider les conversions
- Vous avez une stratégie pour les changements upstream
Ressources et Lectures
- Domain-Driven Design par Eric Evans - Anticorruption Layer
- Refactoring at Scale - Strangler Pattern
- DDD Crew - Context Mapping
Notes de Facilitation pour l’Atelier
Animation
- Demandez : “Pourriez-vous vivre avec le modèle upstream directement ?”
- Explorez : “Qu’est-ce qui vous gêne le plus ?”
- Proposez : “Et si on créait une couche intermédiaire ?”
Pièges Communs
- ⚠️ Sous-estimer la complexité du mapping
- ⚠️ Oublier que l’ACL elle-même devient un domaine à maintenir
- ⚠️ Performance : la traduction peut devenir lente
- ⚠️ Duplication de logique entre upstream et downstream
Questions Provocatrices
- “Et si l’upstream disparaît demain ? Qu’arrive-t-il à votre ACL ?”
- “Combien de temps consacrez-vous à maintenir cette traduction ?”
- “Pourriez-vous juste adopter le modèle upstream ?”