0Pricing
PHP Academy · Lezione

Bounded context e context mapping

Suddividete domini complessi in bounded context che comunicano in sicurezza.

Bounded context e context mapping è una lezione PHP Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento PHP Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso PHP Academy include 4 lezioni in totale.

DDD strategico

I pattern tattici modellano gli oggetti all'interno di un dominio; il DDD strategico decide come suddividere un sistema esteso in parti che possano evolvere indipendentemente. Il concetto centrale è il Bounded Context — un confine esplicito all'interno del quale un modello di dominio e il relativo linguaggio sono coerenti. Il Context Mapping descrive le relazioni tra questi contesti. Spesso questo ha un impatto maggiore di qualsiasi singola progettazione di classe.

Il linguaggio ubiquo

All'interno di un Bounded Context, il team condivide un linguaggio ubiquo — gli stessi termini usati nella conversazione, nel codice e nel modello. Il punto è che una parola ha significati diversi in contesti diversi. Un Customer nelle vendite (lead, sconti) non è lo stesso Customer nell'assistenza (ticket, SLA). Un Bounded Context rende esplicito questo confine, invece di imporre un unico modello condiviso e sovraccarico.

Stessa parola, modelli diversi

Lo stesso concetto di business riceve un modello specifico del contesto. Un Product nel Catalogo considera descrizioni e contenuti multimediali; nell'Inventario considera disponibilità e ubicazione. Ogni contesto definisce solo ciò di cui ha bisogno.

<?php
namespace Catalog;
final class Product {
    public function __construct(
        public readonly string $sku,
        public readonly string $description
    ) {}
}

namespace Inventory;
final class Product {
    public function __construct(
        public readonly string $sku,
        public readonly int $onHand
    ) {}
}

namespace App;
$c = new \Catalog\Product('A1', 'Blue mug');
$i = new \Inventory\Product('A1', 42);
echo $c->description, ' / ', $i->onHand, PHP_EOL;

Perché non usare un unico modello esteso

Cercare di far servire ogni team da un unico Customer canonico produce una god class con requisiti in conflitto, contesa tra i team e modifiche fragili. I Bounded Context permettono a ogni team di essere proprietario del proprio modello e linguaggio, di effettuare il deploy in modo indipendente e di tradurre ai confini. Il confine è il punto in cui si paga un piccolo costo di integrazione per evitare un elevato costo di accoppiamento.

Mappe dei contesti

Una Context Map è una rappresentazione di alto livello dei Bounded Context e delle relazioni tra loro. Registra sia l'integrazione tecnica sia la relazione tra team e politica (chi dipende da chi, chi può imporre modifiche). DDD definisce diversi pattern ricorrenti di relazione, che esamineremo ora.

Conformista nel codice

Le relazioni sono spesso direzionali: un contesto upstream influenza uno downstream (Customer/Supplier, Conformist, Anticorruption Layer). Un contesto downstream Conformist non ha potere negoziale, quindi adotta semplicemente il modello dell'upstream così com'è: usa direttamente la struttura esterna, accettando l'accoppiamento.

<?php
// Upstream's shape, used verbatim downstream (Conformist)
final class UpstreamUser {
    public function __construct(public readonly int $userId, public readonly string $login) {}
}
final class Greeter { // conforms: depends directly on upstream type
    public function greet(UpstreamUser $u): string {
        return "Hello {$u->login} (#{$u->userId})";
    }
}
echo (new Greeter())->greet(new UpstreamUser(7, 'jane')), PHP_EOL;

Anticorruption Layer

Un ACL traduce un modello esterno/legacy nel modello pulito del contesto, così i concetti estranei non penetrano mai al suo interno. È il pattern Adapter applicato al confine di un contesto e protegge il linguaggio ubiquo.

<?php
// Our clean domain model
final class Customer {
    public function __construct(public readonly string $id, public readonly string $name) {}
}
// Legacy/external shape we must not let leak in
$legacy = ['CUST_NO' => '0042', 'FULL_NM' => 'Jane Doe'];

final class LegacyCustomerAcl {
    public function toDomain(array $row): Customer {
        return new Customer($row['CUST_NO'], $row['FULL_NM']);
    }
}
$customer = (new LegacyCustomerAcl())->toDomain($legacy);
echo $customer->id, ' ', $customer->name, PHP_EOL;

Shared Kernel nel codice

  • Shared Kernel: due contesti condividono un piccolo sottoinsieme gestito congiuntamente (qui sotto, un tipo Money comune): lo si modifica solo di comune accordo.
  • Partnership: due team hanno successo o falliscono insieme.
  • Separate Ways: l'integrazione non vale il costo.
  • Open Host Service / Published Language: l'upstream offre un protocollo stabile e documentato per molti consumer.
<?php
namespace Shared; // small, jointly-owned kernel
final class Money {
    public function __construct(public readonly int $cents, public readonly string $cur) {}
    public function format(): string { return number_format($this->cents / 100, 2) . ' ' . $this->cur; }
}

namespace Billing;          // depends on the shared kernel
use Shared\Money;
function invoiceTotal(): Money { return new Money(4999, 'USD'); }

namespace Payroll;          // also depends on the SAME shared kernel
use Shared\Money;
function salary(): Money { return new Money(500000, 'USD'); }

Integrazione dei contesti in PHP

In concreto, i contesti si integrano tramite contratti ben definiti: un metodo di traduzione, un client API che incapsula una Published Language oppure messaggi. Il lato ricevente mappa il DTO esterno nel proprio modello, così l'accoppiamento si arresta al confine.

<?php
// Published Language DTO from an upstream Open Host Service
final class PricingDto {
    public function __construct(public readonly string $sku, public readonly int $cents) {}
}
// Our downstream model
final class CatalogPrice {
    public function __construct(public readonly string $sku, public readonly float $amount) {}
}
final class PricingTranslator {
    public function translate(PricingDto $dto): CatalogPrice {
        return new CatalogPrice($dto->sku, $dto->cents / 100);
    }
}
$p = (new PricingTranslator())->translate(new PricingDto('A1', 1599));
echo $p->amount, PHP_EOL; // 15.99

Contesti e architettura

I Bounded Context si mappano naturalmente sulle unità di deployment: un monolite modulare con confini chiari tra moduli oppure microservizi separati. Il confine dovrebbe essere tracciato attorno alla business capability, non ai layer tecnici. I microservizi che dividono un unico contesto fortemente accoppiato creano un monolite distribuito; confini di contesto ben allineati producono servizi che cambiano indipendentemente.

Gli eventi come punto di collegamento

In pratica, un modo pulito per integrare i contesti senza condividere modelli consiste nello scambiarsi eventi. L'upstream pubblica un evento piccolo e stabile (una Published Language); il downstream si iscrive e lo mappa nel proprio modello, senza mai importare le classi dell'upstream.

<?php
// Published Language: a minimal stable contract
final class OrderPlacedEvent {
    public function __construct(public readonly string $orderId, public readonly int $cents) {}
}
// Downstream (Shipping context) maps it to its own model
final class Shipment {
    public function __construct(public readonly string $forOrder) {}
}
final class ShippingListener {
    public function on(OrderPlacedEvent $e): Shipment {
        return new Shipment($e->orderId); // ignores fields it doesn't need
    }
}
$shipment = (new ShippingListener())->on(new OrderPlacedEvent('o1', 1300));
echo 'shipment for ', $shipment->forOrder, PHP_EOL;

Verifica rapida

Relazioni tra contesti.

Riepilogo

È passato dal DDD tattico a quello strategico. Un Bounded Context è il confine all'interno del quale un modello e il suo linguaggio ubiquo rimangono coerenti, liberando i team da un unico modello condiviso e sovraccarico. Una Context Map documenta le relazioni — Customer/Supplier, Conformist, Anticorruption Layer, Shared Kernel, Partnership, Separate Ways, Open Host Service/Published Language — registrando sia l'integrazione tecnica sia le dinamiche tra i team. Tracci i confini attorno alle capacità di business, traduca ai margini e il sistema potrà evolvere in componenti distribuibili in modo indipendente.

Domande Frequenti

La lezione «Bounded context e context mapping» è gratuita?

Sì — il testo completo di «Bounded context e context mapping» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso PHP Academy, passa a CoddyKit PRO. Il corso PHP Academy include 4 lezioni in totale.

Cosa imparerò in «Bounded context e context mapping»?

Suddividete domini complessi in bounded context che comunicano in sicurezza. Eserciti PHP Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare PHP Academy?

Non è richiesta alcuna esperienza precedente. PHP Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.

Quanto tempo richiede la lezione «Bounded context e context mapping»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione PHP Academy?

Sì. Ogni lezione PHP Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Blocchi fondamentali del DDD: entità e oggetti valore
  2. Aggregati, repository e factory
  3. Eventi e servizi di dominio
  4. Bounded context e context mapping
← Torna a PHP Academy