0Pricing
PHP Academy · 课时

限界上下文与上下文映射

将大型领域拆分为能够安全通信的限界上下文。

限界上下文与上下文映射 是 CoddyKit 上的免费 PHP Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 PHP Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 PHP Academy 课程共包含 4 节课。

战略 DDD

战术模式用于在领域内部建立对象模型;战略 DDD决定如何将大型系统拆分成能够独立演进的部分。其核心概念是限界上下文——一个明确的边界,在此范围内领域模型及其语言保持一致。上下文映射描述这些上下文之间的关系。这通常比任何单个类的设计都更具影响力。

通用语言

在一个限界上下文内部,团队共享一套通用语言——对话、代码和模型使用相同的术语。关键在于:同一个词在不同上下文中可能有不同含义。销售部门中的Customer(潜在客户、折扣)与支持部门中的Customer(工单、服务级别协议)并不是同一个概念。限界上下文明确划出了这条边界,而不是强迫所有人使用一个臃肿的共享模型。

同一个词,不同的模型

同一个业务概念会拥有特定于上下文的模型。目录中的Product关注描述和媒体资源;库存中的Product关注库存数量和位置。每个上下文只定义自身所需的内容。

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

为什么不使用一个大模型

试图让一个规范的Customer服务所有团队,会产生一个包含相互冲突需求的上帝类,导致团队之间争抢资源,并使变更变得脆弱。限界上下文让每个团队拥有自己的模型和语言,可以独立部署,并在边界处进行转换。边界处只需付出少量集成成本,就能避免高昂的耦合成本。

上下文映射

上下文映射是限界上下文及其相互关系的高层次图景。它既记录技术集成,也记录团队/政治关系(谁依赖谁,谁能够决定变更方向)。DDD 为反复出现的关系模式定义了若干名称,接下来我们将逐一介绍。

代码中的遵奉者

关系通常具有方向性——一个上游上下文会影响一个下游上下文(客户/供应商、遵奉者、防腐层)。下游的遵奉者没有谈判筹码,因此只能原样采用上游的模型:直接消费外部模型的形态,并接受由此产生的耦合。

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

防腐层

ACL将外部/遗留模型转换为您上下文中的清晰模型,使外部概念永远不会向内leak。它是在上下文边界处应用的适配器模式,用于保护您的通用语言。

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

代码中的共享内核

  • 共享内核:两个上下文共享一小部分共同维护的内容(下方是一个共用的Money类型),只有达成一致后才能修改。
  • 合作关系:两个团队共同成功或共同失败。
  • 各行其是:集成成本不值得付出。
  • 开放主机服务 / 发布语言:上游为众多消费者提供稳定且有文档说明的协议。
<?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'); }

在 PHP 中集成上下文

具体来说,上下文通过定义清晰的契约进行集成:可以是转换方法、封装发布语言的接口客户端,或消息。接收方将外部数据传输对象映射为自己的模型,使耦合止于边界。

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

上下文与架构

限界上下文可以自然地对应到部署单元:具有清晰模块边界的模块化单体,或彼此独立的微服务。边界应围绕业务 capability划分,而不是围绕技术层次划分。将单个紧密耦合的上下文拆成多个微服务,会创建一个分布式单体;合理对齐的上下文边界则能形成可以独立变更的服务。

以事件作为接缝

在实践中,上下文之间无需共享模型即可进行清晰集成的一种方式,是交换事件。上游发布一个小型且稳定的事件(发布语言);下游订阅该事件并将其映射到自己的模型中——绝不导入上游的类。

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

快速检查

上下文关系。

回顾

您已经从战术 DDD 过渡到了战略 DDD。限界上下文是模型及其通用语言保持一致的边界,使团队不再受一个臃肿共享模型的束缚。上下文映射记录了各种关系——客户/供应商、遵奉者、防腐层、共享内核、合作关系、各行其是、开放主机服务/发布语言——同时呈现技术集成和团队动态。围绕业务 capability 划分边界,在边界处进行转换,系统就能演进为可独立部署的各个部分。

常见问题解答

「限界上下文与上下文映射」课时是免费的吗?

是的 — 「限界上下文与上下文映射」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 PHP Academy 课程的其余内容,请升级到 CoddyKit PRO。 PHP Academy 课程共包含 4 节课。

「限界上下文与上下文映射」这节课中我会学到什么?

将大型领域拆分为能够安全通信的限界上下文。 你通过在浏览器中直接运行的动手代码来练习 PHP Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 PHP Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 PHP Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「限界上下文与上下文映射」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 PHP Academy 课中编写并运行代码吗?

能。每节 PHP Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. DDD 构建模块:实体与值对象
  2. 聚合、仓储与工厂
  3. 领域事件与领域服务
  4. 限界上下文与上下文映射
← 返回 PHP Academy