Context Mapping

Atelier de Cartographie de Contexte : Mapper les Relations Socio-Techniques

Atelier de Cartographie de Contexte

Étape 6 du DDD Starter Modelling Process : “Organise”

(2h à 3h, idéal 8-20 participants)

Contexte : Où sommes-nous dans le DDD Starter Modelling Process ?

Cet atelier intervient après :

  • EventStorming : Vous avez découvert le domaine collaborativement
  • Décomposition en sous-domaines : Vous avez identifié les délimitations naturelles
  • Analyse stratégique : Vous avez identifié vos core domains
  • Domain Message Flow : Vous avez modélisé les flux end-to-end

Maintenant, il s’agit d’organiser les équipes et de clarifier les patterns d’intégration entre contextes. La cartographie de contexte répond à la question :

Carte Context Mapping #1 : Open-host Service

📇 Carte #1 : Open-host Service

Vue Rapide

🎯 Objectif : Un contexte expose une interface commune à plusieurs clients

👥 Relation d’équipe : Upstream/Downstream (asymétrique)

📊 Couplage : Moyen → Bas (dépend de la stabilité de l’interface)


Concept

L’équipe upstream expose une interface (API, événements, etc.) ouverte et publique que tous les clients downstream peuvent utiliser.

L’interface évolue pour accommoder de nouveaux besoins mais reste cohérente et documentée.

Upstream (Open-host Service)
        ↓ (API publique stable)
    Downstream 1
    Downstream 2
    Downstream 3 (clients multiples)

Quand l’Utiliser ? ✅

  • Plusieurs clients downstream avec des besoins similaires
  • ✅ L’upstream peut réussir indépendamment des clients
  • ✅ Vous avez une équipe dédiée pour maintenir l’interface
  • ✅ Les besoins des clients sont génériques et prévisibles
  • ✅ Vous voulez une approche scalable (ajouter de nouveaux clients facilement)

Exemples

  • Stripe API : Interface publique pour les paiements
  • Système de catalogue : Expose une API de consultation
  • Service d’authentification : Interface standardisée pour login

Quand l’Éviter ? ❌

  • ❌ Besoin très spécifique d’un seul client
  • ❌ L’interface change constamment (domaine trop exploratoire)
  • ❌ Les besoins des clients sont radicalement différents
  • ❌ Pas de ressource pour maintenir l’interface

Questions Clés à se Poser 💭

  1. Y a-t-il plusieurs clients qui consomment ce service ?
  2. L’interface peut-elle être stable et générique ?
  3. L’upstream peut-il investir dans la maintenance de l’interface ?
  4. Les clients acceptent-ils de se conformer à l’interface publique ?
  5. Comment versionnez-vous l’API pour ne pas casser les clients ?

Implications pour l’Équipe Upstream

Responsabilités

  • ✓ Concevoir une interface générique et réutilisable
  • Documenter l’interface publique clairement
  • Maintenir la compatibilité (versioning, backward compatibility)
  • Supporter les clients : comprendre leurs besoins
  • Évoluer l’interface pour accueillir de nouveaux cas

Avantages

  • Scale facilement : ajouter de nouveaux clients sans recoder
  • Faible coupling : les clients n’impactent pas la logique upstream
  • Autonomie des clients : ils peuvent évoluer indépendamment

Risques

  • ⚠️ L’interface devient un goulot d’étranglement
  • ⚠️ Les besoins des clients créent une interface trop générique ou trop complexe
  • ⚠️ Maintenance : gérer plusieurs versions de l’API
  • ⚠️ Les clients sont limités à ce que l’interface propose

Implications pour l’Équipe Downstream

Responsabilités

  • Utiliser l’interface telle qu’elle est (pas de négociation)
  • Adapter votre domaine à l’interface upstream
  • Respecter les contrats (versioning, breaking changes)

Avantages

  • Simple d’intégration : pas de traduction complexe
  • Fiabilité : interface bien documentée et stable
  • Pas de dépendance forte : vous pouvez changer sans affecter l’upstream

Risques

  • ⚠️ L’interface ne vous convient pas parfaitement
  • ⚠️ Adapter votre logique à l’interface plutôt que l’inverse
  • ⚠️ Si l’API change, vous devez vous adapter rapidement

Exemple Concret : Système de Paiement

Contexte Upstream : Payment Service

Interface publique (API REST) :
- POST /payments → créer un paiement
- GET /payments/{id} → récupérer le statut
- POST /refunds → effectuer un remboursement
- Events : PaymentCreated, PaymentSucceeded, PaymentFailed

Contextes Downstream

  • Order Service : Utilise l’API de paiement
  • Subscription Service : Utilise l’API de paiement
  • Invoicing Service : Reçoit les événements PaymentSucceeded

Décisions

  • Une seule interface pour tous les cas
  • Versionning : /v1/payments, /v2/payments si breaking change
  • Documentation : Swagger/OpenAPI pour chaque version

Intégration avec Context Mapping

Relations d’Équipe

Payment Team (Upstream - Open-host Service)
        ↓ (API publique)
    Order Team (Downstream - Conformist)
    Subscription Team (Downstream - Conformist)
    Invoicing Team (Downstream - Conformist)

Patterns Downstream Associés

  • Conformist : Les clients adoptent l’interface telle qu’elle
  • Anticorruption Layer : Un client crée une couche de traduction (optionnel)

Checklist de Mise en Place ✓

  • Vous avez identifié plusieurs clients potentiels
  • L’interface est générique et peut servir plusieurs cas
  • Vous avez une équipe dédiée pour la maintenir
  • L’interface est documentée (Swagger, wiki, etc.)
  • Vous avez une stratégie de versioning claire
  • Les clients savent à quoi s’attendre

Ressources et Lectures


Notes de Facilitation pour l’Atelier

Animation

  • Demandez : “Combien de clients potentiels avez-vous ?”
  • Explorez : “L’interface peut-elle rester stable ?”
  • Validez : “Quelqu’un d’autre que vous peut-il la comprendre et l’utiliser ?”

Pièges Communs

  • ⚠️ Penser que tout est OpenAPI → certains domaines n’y sont pas adaptés
  • ⚠️ Négliger la maintenance → les interfaces dégénèrent
  • ⚠️ Trop générique → personne ne la comprend

Questions Provocatrices

  • “Et si vous aviez 10 clients ? 100 clients ?”
  • “Comment réagiriez-vous si un client dit ‘Votre API ne me convient pas’ ?”

Carte Context Mapping #10 : Mutually Dependent Teams

📇 Carte #10 : Mutually Dependent Teams (Team Relationship)

Vue Rapide

🎯 Objectif : Deux équipes ont besoin l’une de l’autre - même poids politique

💼 Type de relation : Équipes au même niveau hiérarchique

🔗 Nature : Interdépendance inévitable


Concept

Deux équipes où ni l’une ne peut progresser indépendamment de l’autre.

Team A ←→ Team B
  Equal weight
  Mutual need
  Symmetric relationship

Caractéristiques

Ce qui les Définit

  • Même niveau hiérarchique : pas de subordination
  • Codépendance : l’une ne peut pas avancer sans l’autre
  • Poids politique équivalent : les deux ont du poids
  • Besoin mutuel : pas d’asymétrie

Ce qui les Différencie des Autres

VS. Upstream/Downstream:
  → Upstream/Downstream = asymétrique
  → Mutually Dependent = symétrique

VS. Independent:
  → Independent = zéro dépendance
  → Mutually Dependent = dépendance totale

Exemplesmonde réel

Frontend Team ↔ Backend Team (pour un même produit)
Catalog Service ↔ Inventory Service (interconnectés)
Platform ↔ Billing (même valeur critique)
Client Support ↔ Product Management (input/output)

Implications Organisationnelles

Coordination Nécessaire

  • 📅 Sprint planning ensemble
  • 🤝 Dailies synchronisées
  • 🎯 OKRs alignés
  • 📋 Dépendance tracking

Processus de Synchronisation

Decision/Change needed
    ↓
Both teams discuss
    ↓
Agree on approach
    ↓
Implement together
    ↓
Verify integration

Escalation

Désaccord?
    ↓
Try to negotiate (48h)
    ↓
If stuck: escalate to common manager
    ↓
Manager arbitrates

Patterns Associés aux Mutual Dependency

La plupart des patterns requièrent cette relation:

  1. Partnership → Mutually Dependent teams

Carte Context Mapping #11 : Upstream/Downstream Teams

📇 Carte #11 : Upstream/Downstream Teams (Team Relationship)

Vue Rapide

🎯 Objectif : Une équipe fournit services à l’autre - asymétrique

💼 Type de relation : Hiérarchie implicite (qui dépend de qui?)

🔗 Nature : Dépendance unilatérale


Concept

Une équipe upstream fournit services à une ou plusieurs équipes downstream.

Upstream Team
    ↓ (provides services)
    ↓
Downstream Team(s)

Les caractéristiques:

  • ✓ Upstream ne dépend PAS du downstream
  • ✓ Downstream dépend d’Upstream
  • ✓ Asymétrique et clair

Différentes Configurations

1. One Upstream, One Downstream

Payment Service (Upstream)
    ↓
Order Service (Downstream)

Payment peut évoluer indépendamment.
Order attend Payment.

2. One Upstream, Many Downstream

Product Catalog (Upstream)
    ↓ ↓ ↓ ↓ ↓
Pricing | Inventory | Search | Recommendation | Analytics
(Downstream services)

Catalog ne connaît pas ses utilisateurs.
Tous dépendent de Catalog.

3. Tiered Upstream/Downstream

Infrastructure (Upstream 1)
    ↓
Core Platform (Upstream 2)
    ↓
Business Services (Downstream)

Patterns Possibles dans Upstream/Downstream

Selon la relation, différents patterns:

Carte Context Mapping #12 : Independent Teams

📇 Carte #12 : Independent Teams (Team Relationship)

Vue Rapide

🎯 Objectif : Deux équipes opèrent indépendamment, zéro dépendance

💼 Type de relation : Aucune (autonome complète)

🔗 Nature : Parallèle, zéro couplage


Concept

Deux équipes qui peuvent progresser complètement indépendamment sans se bloquer.

Team A        Team B
(indépendant) (indépendant)
     ↓ ↓ ↓ ↓ ↓ ↓
    (Zéro couplage)

Caractéristiques

Ce qui les Définit

  • Zéro dépendances : l’une peut évoluer sans l’autre
  • Contextes distincts : domaines totalement séparés
  • Données indépendantes : si partage, c’est via batch/events
  • Autonomie complète : aucune coordination requise

Ce qui les Différencie des Autres

VS. Upstream/Downstream:
  → Upstream/Downstream = dépendance
  → Independent = zéro dépendance

VS. Mutually Dependent:
  → Mutually Dependent = interdépendance
  → Independent = complètement libres

Idéal dans Microservices

Architecture

Service A (Independent)
├─ Own code
├─ Own database
├─ Own API
└─ Owns its fate

Service B (Independent)
├─ Own code
├─ Own database
├─ Own API
└─ Owns its fate

Coordination: Minimal (maybe async events)

Implications Organisationnelles

Avantages

  • Complète autonomie : pas d’attendre l’autre
  • Vitesse : chacun va à son rythme
  • Ownership : claire et motivante
  • Scaling : ajoute équipes sans syncro
  • Failure isolation : équipe A crash pas équipe B

Challenges

  • ⚠️ Duplication : chacun implémente sa version
  • ⚠️ Incohérence : les deux ont des approches différentes
  • ⚠️ Outils différents : pas d’unification possible
  • ⚠️ Learning silos : pas de partage de connaissance
  • ⚠️ Onboarding : chacun a sa culture

Communication: Quand Nécessaire

Pattern 1: Asynchronous Events

Team A does something
    ↓
Publishes event (OrderPlaced)
    ↓
Team B picks it up (async)
    ↓
No blocking, no real-time sync

Pattern 2: Read-Only Access

Team A owns data
Team B reads it (if needed)
    ↓
No writes between them
    ↓
Team B can lag behind

Pattern 3: Batch Sync

Team A exports data nightly
    ↓
Team B imports nightly
    ↓
Updates 24h later
    ↓
Acceptable delay

Pattern 4: Complete Separation

Team A: doesn't know B exists
Team B: doesn't know A exists
    ↓
Zero communication

Exemples du Monde Réel

SaaS Platform

Auth Team
├─ Handles user login/security
├─ Owns user DB
└─ Exposes API

Reporting Team
├─ Handles analytics/reports
├─ Owns analytics DB
├─ Reads user data (read-only)
└─ Zero coordination needed

Content Team
├─ Manages blog/docs
├─ Owns content DB
└─ Completely separate

E-commerce

Order Service Team
├─ Orders only
├─ Can scale independently
└─ Publishes OrderPlaced events

Inventory Service Team
├─ Inventory only
├─ Listens to OrderPlaced
├─ Decrements stock asynchronously
└─ No blocking dependency

Analytics Team
├─ Reads events (Order, Inventory)
├─ Processes asynchronously
└─ No impact on live systems

Governance

Decision Making

Team A decides its direction → Done
Team B decides its direction → Done
No vetoes, no blocking

Shared Resources?

If need shared infrastructure:
  → Infrastructure team is independent too
  → Or dedicated team owns it
  → But integration still async/event-based

Conflicts

Conflict between teams?
  → Each goes its own way
  → Or escalate to higher-level alignment

Trade-offs

When It’s Perfect

✓ Service A: Payments
✓ Service B: Marketing/Email
✓ Service C: Analytics

→ These can be completely independent
→ Perfect microservices setup

When It’s Not Possible

✗ Frontend & Backend of same product
  → Too coupled, need Partnership or Shared Kernel

✗ Inventory & Orders
  → Need synchronization, not truly independent

✗ Core Platform & Applications
  → Core is needed by apps, Upstream/Downstream better

Cost Analysis

Infrastructure

Benefit: Can scale each independently
Cost: More infrastructure, more databases
Trade-off: Worth it for high-scale systems

Development

Benefit: Teams move fast, no waiting
Cost: Potential duplication, less sharing
Trade-off: Speed > DRY principle (in microservices)

Operational

Benefit: Failure isolated
Cost: More systems to monitor
Trade-off: Worth it for reliability

Indicators

Independence Healthy ✅

✓ Teams deploy independently
✓ No blocking on each other
✓ Different tech stacks OK
✓ Minimal communication meetings
✓ Each owns their metrics

Independence Problematic ❌

❌ Frequent cross-team meetings
❌ Waiting on each other
❌ Duplication becoming costly
❌ Incohesive systems
❌ Can't deploy independently

When to Choose Independence

Right Fit

  • Small, focused services
  • High-scale systems
  • Different business domains
  • Different maturity levels
  • Different technology choices needed

Wrong Fit

  • Tightly coupled features
  • Need real-time consistency
  • Shared data models
  • Young team (need learning)
  • Not enough scale to justify overhead

Checklist per Independent Teams ✓

  • Completely separate code/data/deployment
  • Communication plan (events, async, batch)
  • Monitoring of each service independently
  • Failure scenarios handled independently
  • No hidden dependencies (audit for coupling)
  • Teams feel autonomous (survey culture)

Transitioning to Independence

From Dependent to Independent

Mutually Dependent
    ↓ (too slow)
Try Partner → Still coupled
    ↓
Extract: one becomes independent
    → Shared Kernel of critical shared data only
    → Events for everything else
    → Now mostly Independent

From Monolith to Independent

Monolith (all one team)
    ↓ (slow to scale)
Strangler Pattern:
    ├─ Extract Service A
    ├─ Service A becomes Independent
    ├─ Extract Service B
    ├─ Service B becomes Independent
    ├─ ...repeat...
    └─ Monolith eventually sunset

Ressources

  • Building Microservices par Sam Newman - Team Topology
  • Team Topologies par Matthew Skelton - X-as-a-Service
  • Release It! par Michael Nygard - Microservice Coordination
  • DDD Crew - Context Mapping

Notes de Facilitation pour l’Atelier

Animation

  • Demandez : “Êtes-vous vraiment indépendants ?”
  • Testez : “Qu’arrive-t-il si Service X casse ?”
  • Documentez : “Quelles sont vos vraies dépendances ?”

Pièges Communs

  • ⚠️ Dépendances cachées : “Pensaient-ils être indépendants, mais…”
  • ⚠️ Trop de duplication : coûteux à maintenir
  • ⚠️ Inconsistences : données divergent
  • ⚠️ Organisation tue architecture : réorgé casse l’indépendance

Questions Provocatrices

  • “Si je change Service A, affecte-t-ça Service B ?”
  • “Combien de personnes doivent se synchroniser ?”
  • “Est-ce vraiment de l’indépendance ou du chaos ?”
  • “Pourriez-vous déployer Service A sans toucher Service B ?”

Carte Context Mapping #13 : Matrice de Sélection des Patterns

📇 Carte #13 : Matrice de Sélection des Patterns

Vue Rapide

🎯 Objectif : Choisir le bon pattern selon votre situation

📊 Type : Guide de décision


Arbre de Décision

Q1: Les deux contextes dépendent-ils l'un de l'autre?

├─ NON, zéro dépendance
│  └─ SEPARATE WAYS ✓ (ou Independent Teams)
│
└─ OUI, il y a dépendance
   │
   ├─ Q2: Est-ce une dépendance mutuelle (symétrique)?
   │  │
   │  ├─ OUI, mutuelle
   │  │  │
   │  │  ├─ Q3: Vous voulez partager du code?
   │  │  │  ├─ OUI → SHARED KERNEL ✓
   │  │  │  └─ NON → PARTNERSHIP ✓
   │  │  │
   │  │  └─ (Relation d'équipe: Mutually Dependent)
   │  │
   │  └─ NON, asymétrique (Upstream/Downstream)
   │     │
   │     ├─ Q3: Combien de downstream?
   │     │  │
   │     │  ├─ Beaucoup (3+)
   │     │  │  └─ PUBLISHED LANGUAGE ✓
   │     │  │
   │     │  └─ Peu (1-2)
   │     │     │
   │     │     ├─ Q4: Collaborer sur l'interface?
   │     │     │  ├─ OUI → CUSTOMER/SUPPLIER DEVELOPMENT ✓
   │     │     │  └─ NON
   │     │     │     │
   │     │     │     ├─ Q5: Le modèle upstream convient?
   │     │     │     │  ├─ OUI → CONFORMIST ✓
   │     │     │     │  └─ NON → ANTICORRUPTION LAYER ✓
   │     │     │
   │     │     └─ (Relation d'équipe: Upstream/Downstream)
   │
   └─ SPÉCIAL: Découvrir un Big Ball Of Mud?
      └─ BIG BALL OF MUD = symptôme (stratégie: Strangler)
         Puis appliquer les patterns au nouveau code

Matrice Décisionnelle

Par Type de Relation d’Équipe

Relation Patterns Possibles Couplage Avantages Risques
Independent Separate Ways Aucun Vitesse, Autonomie Duplication
Mutually Dependent Shared Kernel, Partnership Haut/Moyen Collaboration, Cohésion Synchronisation lente
Upstream/Downstream Published Language, Customer/Supplier, Conformist, ACL Moyen-Bas Clarté, Scalabilité Blocking sur upstream

Par Situation

Situation 1: Legacy System + Nouveau Projet

Q: Pouvez-vous modifier le legacy?
├─ NON, intouchable
│  └─ ANTICORRUPTION LAYER
│     (Bubble Context protégeant le nouveau)
│
└─ OUI, progressif
   └─ SEPARATE WAYS + Strangler Pattern
      (Extraire nouveau, laisser legacy coexister)

Situation 2: Plateforme Core + Multiples Services

Q: Core tient-il le poids?
├─ NON, trop changements
│  └─ SEPARATE WAYS
│     (Chacun sa version)
│
└─ OUI, stable et bon
   ├─ Peu de consumers
   │  └─ CUSTOMER/SUPPLIER DEVELOPMENT
   │
   └─ Beaucoup de consumers
      └─ PUBLISHED LANGUAGE
         (Spec stable, chacun sa traduction)

Situation 3: Deux Équipes, Même Produit (Frontend/Backend)

Q: Avez-vous du code réellement partagé?
├─ OUI (domain models, value objects)
│  └─ SHARED KERNEL + PARTNERSHIP
│
└─ NON, juste interfaces
   └─ PARTNERSHIP
      (API négociée, chacun son code)

Situation 4: Données Critiques Partagées

Q: Temps-réel synchronisation requise?
├─ OUI, toujours sync
│  ├─ Même équipe/code
│  │  └─ SHARED KERNEL (literal)
│  │
│  └─ Équipes différentes
│     └─ PARTNERSHIP + synchrone
│        (Risque: tightly coupled)
│
└─ NON, batch/async OK
   └─ SEPARATE WAYS + Events
      (Broadcast events, each reacts asynchronously)

Par Critères Techniques

Critère: Modèle Upstream Compatible?

Compatible?
├─ OUI, parfait fit
│  └─ CONFORMIST
│
└─ NON, beaucoup diffère
   └─ ANTICORRUPTION LAYER

Critère: Interface Complexité

Traduction simple?
├─ OUI (champs directs)
│  └─ CONFORMIST ou ACL simple
│
└─ NON (calculs, agrégation)
   └─ ACL complexe
      ou chercher alternative (Published Language?)

Critère: Scalabilité

Combien de consumers?
├─ 1-2
│  └─ Upstream/Downstream simple OK
│
├─ 3-5
│  └─ Published Language commence
│
└─ 5+ ou communauté
   └─ Published Language obligatoire
      (ou découpler vers Independent)

Par Coût d’Intégration

Coût TRÈS haut?
├─ OUI (complexe, risqué)
│  └─ Réévaluer dépendance
│  └─ Considérer SEPARATE WAYS
│  └─ Ou créer ACL (isolation)
│
└─ NON, acceptable
   └─ Choisir selon la relation d'équipe

Anti-patterns à Éviter

❌ Anti-pattern 1: Partnership Sans Communication

"On va faire de la partnership!"
→ Pas de réunions régulières
→ Changements unilatéraux
→ Dépendances cassées

Correction: Ajouter governance (réunions, process)
Ou revenir à Upstream/Downstream plus clair

❌ Anti-pattern 2: Shared Kernel Sans Propriétaire

"On partage le code!"
→ Personne ne le maintient
→ Divergence progessive
→ Chacun ajoute ses trucs

Correction: Nommer responsables du kernel
Ou réduire à vraiment partagé

❌ Anti-pattern 3: Trop d’Upstream/Downstream

"Platform est upstream de 50 services"
→ Platform bottleneck
→ Trop lent, trop tendu

Correction: Migrer vers Published Language
Ou découpler (services Independent)

❌ Anti-pattern 4: Oublier la Team Relationship

"On applique Shared Kernel"
→ Mais équipes ne communiquent jamais
→ Chaos prévisible

Correction: Pattern compatible avec relation d'équipe!

Feuille de Décision Rapide

Remplissez:

Question 1: Dépendance mutuelle ou asymétrique?

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 💭

  1. Le modèle upstream pollue-t-il notre domaine ?
  2. Pouvons-nous nous permettre de créer une couche de traduction ?
  3. La traduction est-elle complexe ou simple ?
  4. Comment maintenons-nous la synchronisation entre les deux modèles ?
  5. 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 :

Carte Context Mapping #3 : Conformist

📇 Carte #3 : Conformist

Vue Rapide

🎯 Objectif : L’équipe downstream adopte le modèle upstream sans traduction

👥 Relation d’équipe : Upstream/Downstream (asymétrique)

📊 Couplage : Haut (adhérence au modèle upstream)


Concept

L’équipe downstream accepte simplement le modèle et les conventions de l’équipe upstream.

Upstream (modèle de référence)
    ↓ (pas de traduction)
Downstream (adopte le même modèle)

La philosophie : “Ce que vous donnez, nous l’utilisons tel quel”


Quand l’Utiliser ? ✅

  • ✅ Le modèle upstream est suffisamment bon pour votre besoin
  • ✅ Créer une ACL serait trop complexe ou non rentable
  • ✅ L’upstream est stable et bien conçu
  • ✅ Vous avez une dépendance forte et c’est acceptable
  • ✅ L’équipe upstream a du poids politique ou est essentielle

Exemples

  • API publique stable : Adopter directement une API bien conçue
  • Plateforme core : Tous les services acceptent le modèle core
  • Standard industrie : Utiliser un standard reconnu (ISO, RFC, etc.)

Quand l’Éviter ? ❌

  • ❌ Le modèle upstream est incompatible avec votre domaine
  • ❌ L’upstream change fréquemment sans coordination
  • ❌ Vous avez besoin de dépendances croisées (Partner pattern est meilleur)
  • ❌ C’est une dépendance temporaire (better: Anticorruption Layer)
  • ❌ Le modèle upstream est mal conçu (Big Ball Of Mud)

Questions Clés à se Poser 💭

  1. Est-ce que le modèle upstream nous convient vraiment ?
  2. Allons-nous devoir le modifier plus tard ?
  3. Quels sont les risques de cette adhérence ?
  4. Comment restons-nous informés des changements ?
  5. Qui décide des évolutions du modèle shared ?

Implications pour l’Équipe Downstream

Responsabilités

  • Accepter le modèle tel qu’il est
  • ✓ Communiquer rapidement si le modèle pose problème
  • Collaborer avec upstream pour améliorations
  • Supporter les changements d’upstream

Avantages

  • Simple : pas de couche de traduction
  • Rapide à intégrer : implémentation directe
  • Couplage intentionnel : c’est du domaine partagé
  • Moins de bugs : une seule source de vérité

Risques

  • ⚠️ Pollina votre modèle : compromis sur votre pureté
  • ⚠️ Couplage fort : difficile à défaire
  • ⚠️ Bloqué par upstream : changements lents
  • ⚠️ Conflit de visions : deux domaines, une structure

Implications pour l’Équipe Upstream

Responsabilités

  • Maintenir une API stable : les downstream dépendent de vous
  • Communicer les changements : informer rapidement
  • Respecter la compatibilité : ou avoir un processus de migration
  • Écouter les besoins downstream

Avantages

  • Influence : votre modèle devient référence
  • Couplage maîtrisé : par design

Risques

  • ⚠️ Responsabilité : you break it, you own all the consequences
  • ⚠️ Évolution lente : devoir négocier avec tous les conformists

Exemples de Conformist Patterns

1. Shared Business Model

Upstream Team (Orders Domain)
    ├── Order { id, customerId, items, status }
    ├── OrderItem { productId, quantity, price }
    └── Status enum

Downstream Team (Invoicing)
    └── Adopte exactement le même modèle
        ├── Invoice utilise Order directement
        ├── InvoiceItem utilise OrderItem
        └── Respecte Status enum

2. API Publique Standard

Upstream: REST API (JSON well-known)
    {
      "id": "...",
      "name": "...",
      "type": "...",
      "metadata": { ... }
    }

Downstream Services:
    └── Tous utilisent exactement cette structure
        Pas de traduction

3. Industrie Standard (XML/JSON Schema)

Standard: UBL Invoice
    Upstream (supplier): génère UBL
    Downstream (customer): consomme UBL
    → Pas de traduction

Exemple Concret : Plateforme E-commerce

Contexte

Vous avez une équipe Product Core qui gère l’essai central.

Carte Context Mapping #4 : Shared Kernel

📇 Carte #4 : Shared Kernel

Vue Rapide

🎯 Objectif : Deux équipes partagent du code et un modèle commun

👥 Relation d’équipe : Mutuellement Dépendant

📊 Couplage : Très haut (code partagé)


Concept

Deux contextes partagent du code source et un modèle de domaine commun.

Shared Kernel (Code + Model)
    ↙         ↘
Team A      Team B

Le noyau partagé n’appartient à aucun contexte, il est gardé par les deux.


Quand l’Utiliser ? ✅

  • ✅ Deux équipes très dépendantes l’une de l’autre
  • ✅ Créer une interface prendrait plus de temps qu’un code partagé
  • ✅ Les équipes veulent vraiment collaborer
  • ✅ Le code partagé est stable et bien défini
  • ✅ C’est une zone de frontière claire (pas du fouilli)

Exemples

  • Domain Entities partagées : Customer, Product (tous les services en ont besoin)
  • Value Objects : Money, EmailAddress (immuables, réutilisables)
  • Shared Policies : Règles métier communes
  • Shared Algorithms : Calculs complexes partagés

Quand l’Éviter ? ❌

  • ❌ Les équipes ne se font pas confiance
  • ❌ Le code partagé change fréquemment
  • ❌ Vous pouvez le dupliquer (plus simple)
  • ❌ Le code partagé n’est pas vraiment partagé (distinct par contexte)
  • ❌ Les équipes sont géographiquement éloignées (communication difficile)

Questions Clés à se Poser 💭

  1. Qu’est-ce qui est vraiment partagé ? (vs. similaire)
  2. Comment gérons-nous les changements du noyau ?
  3. Qui est responsable de maintenir le Shared Kernel ?
  4. Qu’arrive-t-il si les équipes divergent dans leurs besoins ?
  5. Comment versionnons-nous ce code partagé ?

Implications pour les Deux Équipes

Responsabilités Communes

  • Maintenir ensemble le Shared Kernel
  • Tester à fond : les changements affectent tous les contextes
  • Documenter clairement : quoi et pourquoi c’est partagé
  • Communiquer avant changement

Avantages

  • Efficacité : pas de duplication ou traduction
  • Cohérence : une seule source de vérité
  • Collaboration : force les équipes à travailler ensemble
  • Évolution facile : tout le monde évolue en même temps

Risques

  • ⚠️ Couplage très fort : changement = impacte les 2 contextes
  • ⚠️ Synchronisation lente : besoin de coordination
  • ⚠️ Conflits : si les besoins divergent
  • ⚠️ Cycles de dépendance : chaque équipe attend l’autre

Structure du Shared Kernel

Option 1 : Bibliothèque Partagée

shared-kernel/ (repository/package dédié)
├── domain-entities/
│   ├── Customer.ts
│   └── Product.ts
├── value-objects/
│   ├── Money.ts
│   └── EmailAddress.ts
└── policies/
    └── PricingPolicy.ts

Team A → imports shared-kernel
Team B → imports shared-kernel

Option 2 : Code Partagé dans Sous-Dossier

monorepo/
├── services/team-a/
│   ├── src/
│   └── shared/ (lien vers shared-kernel)
├── services/team-b/
│   ├── src/
│   └── shared/ (lien vers shared-kernel)
└── shared-kernel/
    ├── entities/
    ├── value-objects/
    └── policies/

Exemple Concret : E-commerce Shared Entities

Contexte

Deux équipes : Catalog et Inventory

Carte Context Mapping #5 : Partnership

📇 Carte #5 : Partnership

Vue Rapide

🎯 Objectif : Deux équipes avec besoin mutuel s’engagent à se coordonner

👥 Relation d’équipe : Mutuellement Dépendant

📊 Couplage : Élevé (interfaces négociées)


Concept

Deux contextes aussi importants l’un que l’autre s’engagent à :

  • Collaborer sur les interfaces
  • Se consulter avant changements majeurs
  • Synchroniser leurs efforts
Team A (contexte équivalent)
    ↔ Partnership ↔
Team B (contexte équivalent)

La philosophie : “Nous avons besoin l’un de l’autre, donc on se coordonne”