Skip to content

MaxiCorrea/java-customer-supplier

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Customer-Supplier | DDD Strategic Pattern

Pattern

Que es Customer-Supplier

Customer-Supplier es un patron estrategico de Domain-Driven Design que define la relacion entre dos Bounded Contexts cuando uno de ellos (el Supplier/Upstream) provee capacidades que el otro (el Customer/Downstream) necesita para funcionar.

A diferencia de otros patrones de integracion como Shared Kernel o Conformist, Customer-Supplier establece una relacion donde ambos equipos tienen poder de negociacion: el Supplier no impone unilateralmente su modelo, y el Customer puede influir en la interfaz que consume. Existe un acuerdo formal entre ambas partes.

Caracteristicas clave

  • Upstream (Supplier): Define y publica una interfaz estable. Tiene la responsabilidad de no romper el contrato con el downstream. Sus cambios internos no deben afectar al consumidor mientras la interfaz se mantenga.
  • Downstream (Customer): Consume la interfaz publicada por el upstream. Puede solicitar cambios o nuevas capacidades al supplier. No accede directamente al modelo interno del upstream.
  • Interfaz negociada: El contrato entre ambos contextos se define de forma colaborativa. El supplier expone solo lo necesario a traves de una Facade o un servicio de aplicacion, protegiendo su modelo de dominio.
  • Autonomia de modelos: Cada Bounded Context mantiene su propio Ubiquitous Language y su modelo de dominio independiente. No hay acoplamiento estructural entre los modelos internos.

Cuando usar este patron

  • Cuando dos equipos trabajan en Bounded Contexts que tienen una dependencia funcional clara (uno necesita datos o comportamiento del otro).
  • Cuando existe una relacion de colaboracion real entre los equipos — el upstream esta dispuesto a dar soporte al downstream.
  • Cuando se quiere evitar el acoplamiento fuerte que implica un Shared Kernel, pero se necesita mas coordinacion que en un modelo Conformist.

Cuando NO usar este patron

  • Si el upstream no tiene interes en dar soporte al downstream, el patron real es Conformist (el downstream se adapta sin negociacion).
  • Si no hay relacion entre los contextos, se usa Separate Ways.
  • Si ambos contextos estan tan acoplados que comparten modelo, se usa Shared Kernel.

Estructura del proyecto

src/main/java/
├── payments/                         # Bounded Context: Payments (Customer/Downstream)
│   ├── domain/
│   │   └── Payment.java              # Entidad de dominio
│   └── application/
│       └── PaymentService.java       # Servicio de aplicacion — consume la Facade
│
└── accounting/                       # Bounded Context: Accounting (Supplier/Upstream)
    ├── domain/
    │   ├── Money.java                # Value Object
    │   ├── JournalEntry.java         # Entidad de dominio (asiento contable)
    │   ├── LadgerLine.java           # Linea del libro mayor
    │   └── LedgerType.java           # DEBIT / CREDIT
    └── application/
        └── port/
            ├── PaymentAccountingFacade.java       # Interfaz publica (contrato)
            ├── PaymentAccountingFacedeImpl.java    # Implementacion del contrato
            └── JournalRepository.java             # Puerto de persistencia

Como se aplica el patron en este codigo

1. El Supplier expone una Facade

El contexto accounting publica la interfaz PaymentAccountingFacade como punto de entrada controlado. Esta interfaz es el contrato negociado entre ambos contextos:

public interface PaymentAccountingFacade {
    void registerPayment(
        String paymentId,
        String fromAccount,
        String toAccount,
        BigDecimal amount,
        String currency);
}

La firma usa tipos primitivos — no expone Money, JournalEntry, ni ningun otro objeto del modelo interno de accounting. Esto es intencional: el Customer no necesita conocer ni depender del modelo de dominio del Supplier.

2. El Customer consume la Facade

El contexto payments depende unicamente de la interfaz, nunca de la implementacion ni del modelo interno:

public final class PaymentService {

    private final PaymentAccountingFacade facade;

    public void processPayment(final Payment payment) {
        // Payment logic
        facade.registerPayment(
            payment.getId(),
            payment.getDebtorAccount(),
            payment.getCreditorAccount(),
            payment.getAmount(),
            payment.getCurrency());
    }
}

PaymentService no importa nada de accounting.domain. Su unica dependencia hacia el upstream es la interfaz PaymentAccountingFacade.

3. El Supplier protege su modelo

La implementacion PaymentAccountingFacedeImpl traduce los parametros primitivos a objetos de su propio dominio (Money, JournalEntry) y ejecuta su logica interna:

public void registerPayment(...) {
    Money money = new Money(amount, currency);
    JournalEntry entry = JournalEntry.forPayment(paymentId, currency, toAccount, money);
    entry.validateBalance();
    journalRepository.save(entry);
}

El Supplier puede refactorizar Money, cambiar como se construye un JournalEntry, o modificar la validacion de balance sin afectar al Customer, siempre que la firma de la Facade se mantenga.

Diagrama de relacion

┌─────────────────────────┐          ┌─────────────────────────┐
│   payments (Customer)   │          │  accounting (Supplier)  │
│                         │          │                         │
│  PaymentService ────────┼── usa ──►│  PaymentAccountingFacade│
│                         │          │          │              │
│  Payment (dominio)      │          │          ▼              │
│                         │          │  PaymentAccountingImpl  │
│                         │          │          │              │
│                         │          │          ▼              │
│                         │          │  JournalEntry, Money    │
│                         │          │  LadgerLine, LedgerType │
└─────────────────────────┘          └─────────────────────────┘

         Downstream ──────────────────────► Upstream
         (depende de la interfaz)           (publica la interfaz)

Tecnologias

  • Java (sin frameworks)
  • Maven

Releases

No releases published

Packages

 
 
 

Contributors

Languages