0Pricing
PHP Academy · Lekcja

Konteksty ograniczone i mapowanie kontekstów

Proszę dzielić duże domeny na bezpiecznie komunikujące się konteksty ograniczone.

Konteksty ograniczone i mapowanie kontekstów to bezpłatna lekcja PHP Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej PHP Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs PHP Academy zawiera 4 lekcji w sumie.

Strategiczne DDD

Wzorce taktyczne modelują obiekty wewnątrz domeny; strategiczne DDD określa, jak podzielić duży system na części, które mogą ewoluować niezależnie. Centralnym pojęciem jest bounded context — wyraźnie określona granica, w obrębie której model domeny i jego język pozostają spójne. Mapowanie kontekstów opisuje relacje między tymi kontekstami. Ma to często większy wpływ niż projekt pojedynczej klasy.

Wszechobecny język

W obrębie bounded context zespół posługuje się wspólnym wszechobecnym językiem — tych samych terminów używa w rozmowach, kodzie i modelu. Problem polega na tym, że słowo może znaczyć coś innego w różnych kontekstach. Customer w dziale Sales (leady, rabaty) nie oznacza tego samego co Customer w dziale Support (zgłoszenia, SLA). Bounded context wyraźnie wyznacza tę granicę, zamiast wymuszać jeden, przeładowany wspólny model.

To samo słowo, różne modele

Ta sama koncepcja biznesowa otrzymuje model specyficzny dla kontekstu. Product w Catalog uwzględnia opisy i multimedia, natomiast w Inventory — stan magazynowy i lokalizację. Każdy kontekst definiuje tylko to, czego potrzebuje.

<?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;

Dlaczego nie jeden duży model

Próba utworzenia jednego kanonicznego Customer dla każdego zespołu prowadzi do powstania klasy-boga o sprzecznych wymaganiach, konfliktów między zespołami i kruchych zmian. Bounded contexts pozwalają każdemu zespołowi posiadać własny model i język, wdrażać je niezależnie oraz tłumaczyć dane na granicach. Granica to miejsce, w którym ponosi się niewielki koszt integracji, aby uniknąć dużego kosztu sprzężenia.

Mapy kontekstów

Mapa kontekstów to wysokopoziomowy obraz bounded contexts i relacji między nimi. Rejestruje zarówno integrację techniczną, jak i relację między zespołami oraz polityczną (kto od kogo zależy i kto może narzucić zmianę). DDD wyróżnia kilka powtarzających się wzorców relacji, które omówimy teraz.

Conformist w kodzie

Relacje często mają kierunek — kontekst upstream wpływa na kontekst downstream (Customer/Supplier, Conformist, Anticorruption Layer). Zależny kontekst typu Conformist nie ma możliwości wywierania wpływu, więc po prostu przyjmuje model upstreamu bez zmian: bezpośrednio korzysta z obcego kształtu, akceptując sprzężenie.

<?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

ACL tłumaczy zewnętrzny lub starszy model na czysty model Państwa kontekstu, dzięki czemu obce pojęcia nigdy nie przenikają do środka. Jest to wzorzec Adapter zastosowany na granicy kontekstu, chroniący Państwa wszechobecny język.

<?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 w kodzie

  • Shared Kernel: dwa konteksty współdzielą niewielki, wspólnie utrzymywany podzbiór (poniżej wspólny typ Money) — zmiany wprowadza się wyłącznie za zgodą obu stron.
  • Partnership: dwa zespoły odnoszą sukces albo ponoszą porażkę wspólnie.
  • Separate Ways: integracja nie jest warta poniesionego kosztu.
  • Open Host Service / Published Language: upstream udostępnia stabilny, udokumentowany protokół dla wielu odbiorców.
<?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'); }

Integracja kontekstów w PHP

W praktyce konteksty integrują się za pomocą precyzyjnie zdefiniowanych kontraktów: metody tłumaczącej, klienta API opakowującego Published Language albo komunikatów. Strona odbierająca mapuje obcy DTO na własny model, dzięki czemu sprzężenie kończy się na granicy.

<?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

Konteksty i architektura

Bounded contexts naturalnie odwzorowują jednostki wdrożeniowe: monolit modułowy z wyraźnymi granicami modułów albo osobne mikrousługi. Granicę należy wyznaczać wokół zdolności biznesowej, a nie warstw technicznych. Mikrousługi dzielące jeden silnie sprzężony kontekst tworzą monolit rozproszony; dobrze dopasowane granice kontekstów pozwalają tworzyć serwisy zmieniające się niezależnie.

Zdarzenia jako punkt styku

W praktyce dobrym sposobem integracji kontekstów bez współdzielenia modeli jest wymiana zdarzeń. Upstream publikuje małe, stabilne zdarzenie (Published Language), a downstream subskrybuje je i mapuje na własny model — nigdy nie importując klas upstreamu.

<?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;

Szybki test

Relacje między kontekstami.

Podsumowanie

Przeszli Państwo od taktycznego do strategicznego DDD. Bounded context to granica, w obrębie której model i jego wszechobecny język pozostają spójne, uwalniając zespoły od jednego, przeładowanego wspólnego modelu. Mapa kontekstów dokumentuje relacje — Customer/Supplier, Conformist, Anticorruption Layer, Shared Kernel, Partnership, Separate Ways, Open Host Service/Published Language — uwzględniając zarówno integrację techniczną, jak i dynamikę zespołów. Należy wyznaczać granice wokół zdolności biznesowych i tłumaczyć dane na granicach, aby system mógł ewoluować w postaci niezależnie wdrażanych części.

Często zadawane pytania

Czy lekcja „Konteksty ograniczone i mapowanie kontekstów” jest bezpłatna?

Tak — pełny tekst „Konteksty ograniczone i mapowanie kontekstów” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu PHP Academy, przejdź na CoddyKit PRO. Kurs PHP Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Konteksty ograniczone i mapowanie kontekstów”?

Proszę dzielić duże domeny na bezpiecznie komunikujące się konteksty ograniczone. Ćwiczysz PHP Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć PHP Academy?

Nie wymagamy żadnego doświadczenia. PHP Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.

Ile czasu zajmuje lekcja „Konteksty ograniczone i mapowanie kontekstów”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji PHP Academy?

Tak. Każda lekcja PHP Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Elementy DDD: encje i obiekty wartości
  2. Agregaty, repozytoria i fabryki
  3. Zdarzenia domenowe i usługi domenowe
  4. Konteksty ograniczone i mapowanie kontekstów
← Powrót do PHP Academy