Cap Bounded Context viu aïllat. En un sistema real, els contextos necessiten col·laborar: el de Subscripció consumeix dades del de Vendes, el de Facturació reacciona a les pòlisses subscrites, etcètera. El Mapatge de Contextos (Context Mapping) és la disciplina del DDD que descriu com es relacionen i s'integren els diferents Bounded Contexts i, sobretot, quin tipus de relació de poder, dependència i traducció existeix entre ells. Aquesta lliçó tanca el mòdul connectant el disseny estratègic amb la realitat organitzativa: els patrons de mapatge no només descriuen integracions tècniques, sinó també relacions entre equips. Comprendre'ls et permetrà dissenyar integracions sanes i protegir-te de models aliens que podrien contaminar el teu.
Contingut
- Què és un Context Map i per què importa?
- Patrons de relació entre contextos
- L'Anti-Corruption Layer (ACL) en detall
- L'Open Host Service i el Published Language
- Dibuixar un Context Map d'exemple
- Què és un Context Map i per què importa?
Un Context Map és una representació —normalment un diagrama— de tots els Bounded Contexts d'un sistema i les relacions entre ells. No descriu el detall intern de cada context (això és el disseny tàctic), sinó les fronteres i els punts de contacte.
El seu valor és doble:
- Tècnic: mostra quin context depèn de quin, per on flueixen les dades i on calen traduccions.
- Organitzatiu: les relacions entre contextos solen reflectir relacions entre equips. Un context "riu amunt" (upstream) imposa el seu model; un "riu avall" (downstream) s'hi ha d'adaptar. Saber qui és a dalt i qui a baix evita conflictes.
Dos conceptes transversals que apareixen en tots els patrons:
- Upstream (riu amunt): el context que proveeix, del qual altres depenen. Té més "poder": els seus canvis afecten els altres.
- Downstream (riu avall): el context que consumeix, que depèn del de dalt i s'ha d'adaptar als seus canvis.
- Patrons de relació entre contextos
El DDD cataloga diversos patrons de relació. Aquests són els més importants:
| Patró | Relació de poder | Descripció | Quan usar-lo |
|---|---|---|---|
| Partnership (associació) | Igualitària | Dos contextos/equips depenen mútuament i coordinen els seus canvis de manera conjunta. Èxit o fracàs compartits. | Equips que han d'evolucionar alhora i es comuniquen bé |
| Shared Kernel (nucli compartit) | Igualitària | Comparteixen una porció del model i codi (un mòdul comú). Canviar-lo requereix acord d'ambdós. | Subdomini comú molt estable entre dos equips propers |
| Customer-Supplier (client-proveïdor) | Upstream/Downstream | El proveïdor (upstream) atén les necessitats del client (downstream); el client pot influir en el pla del proveïdor. | L'upstream està disposat a prioritzar les necessitats del downstream |
| Conformist (conformista) | Upstream/Downstream | El downstream adopta el model de l'upstream tal com és, sense traduir-lo, perquè no té capacitat d'influir. | L'upstream no negocia (ex. un sistema extern gran) i el seu model és acceptable |
| Anti-Corruption Layer (ACL) | Upstream/Downstream | El downstream construeix una capa de traducció que aïlla i converteix el model aliè al seu propi. | El model de l'upstream és dolent o aliè i no vols que contamini el teu |
| Open Host Service (OHS) | Upstream | L'upstream publica una API/protocol ben definit perquè molts consumidors s'integrin de manera estàndard. | Molts clients consumeixen el mateix context |
La diferència clau entre Conformist i ACL és crucial:
- Conformist: "M'empasso el teu model tal com és, amb els seus defectes, perquè em surt més barat que traduir."
- ACL: "No vull el teu model dins de casa meva; poso una capa que el tradueix al meu i em protegeix dels teus canvis."
- L'Anti-Corruption Layer (ACL) en detall
L'Anti-Corruption Layer és probablement el patró més útil en sistemes que s'integren amb programari heretat o extern. La seva missió és impedir que el model d'un altre context es filtri i corrompi el nostre.
Imagina que el teu context de Subscripció ha de consultar un vell sistema de scoring creditici extern que retorna dades crues i amb un model molt diferent del teu:
// Model CRU que retorna el sistema extern (no volem això al nostre domini)
public class RespuestaScoringExterno {
public int cod_riesgo; // 1, 2, 3... què signifiquen?
public String flag_moroso; // "S" / "N"
public double pct; // de què?
}Aquest model extern és lleig: codis numèrics sense significat, flags amb cadenes, noms críptics. Si el deixem entrar tal com és, contamina tot el nostre domini.
// ACL: tradueix el model extern al NOSTRE model net
public class ScoringCrediticioAcl {
private final ClienteSistemaExterno externo; // el sistema heretat
public ScoringCrediticioAcl(ClienteSistemaExterno externo) {
this.externo = externo;
}
public PerfilCrediticio obtenerPerfil(IdAsegurado id) {
RespuestaScoringExterno raw = externo.consultar(id.valor());
// TRADUCCIÓ: del model aliè al nostre, net i amb significat
NivelRiesgo nivel = traducirNivel(raw.cod_riesgo);
boolean moroso = "S".equals(raw.flag_moroso);
return new PerfilCrediticio(nivel, moroso); // objecte del NOSTRE domini
}
private NivelRiesgo traducirNivel(int cod) {
switch (cod) {
case 1: return NivelRiesgo.BAJO;
case 2: return NivelRiesgo.MEDIO;
default: return NivelRiesgo.ALTO;
}
}
}El que aconseguim amb l'ACL:
- El sistema extern i el seu model lleig queden encapsulats darrere de
ScoringCrediticioAcl. La resta del nostre domini no veu maiRespuestaScoringExterno. - La traducció converteix
cod_riesgo(unintsense significat) en unNivelRiesgo(un concepte clar del nostre domini) i el flag"S"/"N"en unboolean. - El nostre domini rep un
PerfilCrediticionet, expressat en el nostre Llenguatge Ubic. - Si el sistema extern canvia el seu format, només canviem l'ACL; la resta del domini queda intacta. Aquesta és la protecció clau.
graph LR
subgraph Nuestro[Bounded Context: Subscripcio]
D[Domini net]
ACL[Anti-Corruption Layer]
end
subgraph Externo[Sistema extern heretat]
E[Model lleig / cru]
end
D --> ACL
ACL --> EL'ACL actua com una membrana: cap endins parla el nostre idioma; cap enfora, el del sistema extern.
- L'Open Host Service i el Published Language
Quan un context upstream té molts consumidors, no és raonable adaptar-se a cadascun. En lloc d'això, publica un Open Host Service (OHS): una API estable i documentada que qualsevol pot consumir de manera estàndard. Al costat de l'OHS sol anar un Published Language: un format d'intercanvi ben definit i versionat (per exemple, un esquema JSON o un contracte OpenAPI).
# Published Language: contracte de l'esdeveniment publicat per l'OHS de Polisses
PolizaSuscritaV1:
type: object
required: [idPoliza, idAsegurado, fechaEfecto, primaAnual]
properties:
idPoliza: { type: string, format: uuid }
idAsegurado: { type: string, format: uuid }
fechaEfecto: { type: string, format: date }
primaAnual:
type: object
properties:
importe: { type: number }
moneda: { type: string, example: "EUR" }Per què aquest contracte és un bon Published Language:
- És explícit i versionat (
PolizaSuscritaV1): els consumidors saben exactament què esperar, i una futuraV2no trenca els qui usen laV1. - Defineix els camps obligatoris (
required) i els seus tipus: és un acord formal, no una estructura que canvia sense avisar. - Està expressat en un format neutral (esquema tipus JSON/OpenAPI), independent de la tecnologia interna del context que el publica.
Amb un OHS i un Published Language, el context de Pòlisses pot tenir desenes de consumidors (Facturació, Notificacions, Reassegurança...) sense acoblar-se a cap: tots parlen el llenguatge publicat.
- Dibuixar un Context Map d'exemple
Posem junts els patrons al Context Map de la nostra asseguradora:
graph TD
Vendes -->|Customer-Supplier| Subscripcio
Subscripcio -->|ACL| ScoringExterno[Scoring Crediticio EXTERN]
Subscripcio -->|publica esdeveniments OHS| Polisses
Polisses -->|Open Host Service| Facturacio
Polisses -->|Open Host Service| Notificacions
Polisses <-->|Partnership| SinistresLectura del mapa i justificació de cada relació:
- Vendes → Subscripció (Customer-Supplier): Vendes és upstream i proveeix els leads; Subscripció és downstream i pot demanar a Vendes que inclogui certes dades. Hi ha diàleg entre equips.
- Subscripció → Scoring Extern (ACL): el sistema de scoring és extern i el seu model no ens agrada, així que l'aïllem darrere d'una capa anticorrupció.
- Pòlisses → Facturació / Notificacions (Open Host Service): Pòlisses té diversos consumidors, així que publica una API/esdeveniments estàndard per a tots.
- Pòlisses ↔ Sinistres (Partnership): ambdós evolucionen junts i depenen mútuament (un sinistre necessita la pòlissa vigent; la pòlissa reflecteix la sinistralitat), per la qual cosa els seus equips coordinen els canvis de manera conjunta.
Aquest mapa permet a l'organització veure d'un cop d'ull on són les dependències crítiques, on cal protecció (ACL) i on convé estabilitzar contractes (OHS).
Errors Comuns i Consells
- No tenir Context Map. Sense ell, les integracions creixen de manera caòtica i ningú sap qui depèn de qui. Dibuixa'l i mantén-lo actualitzat.
- Ser Conformist per mandra quan el model aliè és dolent. Adoptar tal com és un model defectuós contamina el teu. Si el model extern és lleig o inestable, inverteix en un ACL.
- Compartir base de dades entre contextos. És el pitjor "patró": acobla els contextos per la BD i trenca les seves fronteres. Integra'ls per API o esdeveniments, mai per taules compartides.
- Shared Kernel massa gran. Com més comparteixes, més coordinació necessites. Mantén el nucli compartit mínim i molt estable, o no l'usis.
- No versionar el Published Language. Si canvies el contracte sense versió, trenques tots els consumidors alhora. Versiona sempre (V1, V2...).
- Consell: les relacions del Context Map són tant tècniques com organitzatives. Abans de triar un patró, pregunta't quin equip té el poder i la disposició a col·laborar; això sol decidir entre Customer-Supplier, Conformist o ACL.
Exercicis
Exercici 1. El teu context s'ha d'integrar amb l'API d'un proveïdor de pagaments extern, gran i que no adaptarà res a tu, però el model del qual és raonablement net. Quin patró tries i per què? I si el model fos caòtic?
Exercici 2. Dos equips comparteixen un mòdul de "càlcul d'impostos" que ambdós modifiquen constantment i que provoca conflictes freqüents. Identifica quin patró estan usant i proposa una alternativa més sana.
Exercici 3. Per a cada relació, indica quin és el context upstream i quin el downstream: (a) un context d'Informes que llegeix dades del context de Vendes; (b) un Open Host Service de Catàleg consumit per Comandes.
Solucions
Solució 1. Si el model del proveïdor és net i no negocia, el patró natural és Conformist: adoptes el seu model tal com és perquè és acceptable i traduir-lo no compensaria. Si el model fos caòtic o inestable, el correcte és un Anti-Corruption Layer que aïlli el teu domini d'aquest model i et protegeixi dels seus canvis.
Solució 2. Estan usant un Shared Kernel (nucli compartit) que és massa gran i volàtil, d'aquí els conflictes constants. Alternatives més sanes: convertir el càlcul d'impostos en un context propi amb un Open Host Service que ambdós consumeixin, o assignar la propietat a un equip (upstream) i que l'altre el consumeixi com a Customer-Supplier. Així s'elimina la necessitat de modificar alhora un codi compartit.
Solució 3. (a) Vendes és upstream (proveeix les dades); Informes és downstream (en depèn). (b) Catàleg és upstream (publica l'OHS); Comandes és downstream (consumeix el servei).
Conclusió
Amb aquesta lliçó tanquem el mòdul de Disseny Dirigit pel Domini. Hem vist que el Context Map revela com es relacionen els Bounded Contexts i que aquestes relacions són alhora tècniques i organitzatives. Hem estudiat els patrons clau —Partnership, Shared Kernel, Customer-Supplier, Conformist, ACL i Open Host Service— i la diferència decisiva entre conformar-se amb un model aliè (Conformist) i protegir-se'n amb una capa de traducció (ACL). Finalment, hem compost un Context Map complet que integra tots els patrons.
Amb els quatre pilars del mòdul —conceptes fonamentals, disseny estratègic, disseny tàctic i mapatge de contextos— disposes ja d'un marc complet per abordar dominis complexos. El següent pas natural al curs d'Arquitectura d'Aplicacions és veure com aquests contextos i models es materialitzen en estils arquitectònics concrets, com l'arquitectura hexagonal i les arquitectures dirigides per esdeveniments, que porten a la pràctica tot allò après aquí.
Curs d'Arquitectura d'Aplicacions
Mòdul 1: Fonaments de l'Arquitectura d'Aplicacions
- Què és l'Arquitectura d'Aplicacions?
- El Rol de l'Arquitecte de Programari
- Atributs de Qualitat i Requisits No Funcionals
- Decisions Arquitectòniques i Compromisos (Trade-offs)
- Documentació d'Arquitectura: Vistes i el Model C4
Mòdul 2: Principis i Tàctiques de Disseny
- Acoblament, Cohesió i Separació de Responsabilitats
- Principis SOLID Aplicats a l'Arquitectura
- DRY, KISS, YAGNI i Altres Principis de Disseny
- Tàctiques Arquitectòniques per als Atributs de Qualitat
- Gestió del Deute Tècnic
Mòdul 3: Estils i Patrons Arquitectònics
- Arquitectura Monolítica
- Arquitectura en Capes (N-Tier)
- Arquitectura Client-Servidor
- Arquitectura Hexagonal (Ports i Adaptadors)
- Arquitectura Neta i Ceba (Clean & Onion)
Mòdul 4: Arquitectures Distribuïdes i Microserveis
- Introducció als Sistemes Distribuïts
- Arquitectura de Microserveis
- Descomposició de Serveis i Bounded Contexts
- API Gateway, Service Discovery i Comunicació entre Serveis
- Patrons de Resiliència: Circuit Breaker, Retry i Bulkhead
- El Teorema CAP i la Consistència de Dades
Mòdul 5: Arquitectures Dirigides per Esdeveniments i Missatgeria
- Fonaments de l'Arquitectura Orientada a Esdeveniments
- Missatgeria Asíncrona: Cues i Brokers
- Patrons d'Esdeveniments: Event Sourcing i CQRS
- Gestió de Transaccions Distribuïdes: Patró Saga
- Streaming de Dades en Temps Real
Mòdul 6: Disseny Dirigit pel Domini (DDD)
- Conceptes Fonamentals del DDD
- Disseny Estratègic: Bounded Contexts i Llenguatge Ubic
- Disseny Tàctic: Entitats, Agregats i Repositoris
- Mapatge de Contextos (Context Mapping)
Mòdul 7: Dades i Persistència
- Estratègies de Persistència: SQL vs NoSQL
- Patrons d'Accés a Dades: Repository, Unit of Work i DAO
- Base de Dades per Servei i Gestió de Dades Distribuïdes
- Cau i Estratègies d'Invalidació
Mòdul 8: Arquitectura al Núvol i Desplegament
- Fonaments del Cloud Computing (IaaS, PaaS, SaaS)
- Contenidors i Orquestració amb Docker i Kubernetes
- Arquitectura Serverless
- Patrons de Disseny Cloud-Native
- Infraestructura com a Codi (IaC)
Mòdul 9: Qualitat, Seguretat i Observabilitat
- Escalabilitat: Horitzontal vs Vertical i Balanceig de Càrrega
- Alta Disponibilitat i Tolerància a Fallades
- Seguretat per Disseny i Autenticació/Autorització
- Observabilitat: Logging, Mètriques i Traçabilitat
- Rendiment i Proves de Càrrega
