บริบทที่มีขอบเขตและการทำแผนผังบริบท
แบ่งโดเมนขนาดใหญ่เป็นบริบทที่มีขอบเขตและสื่อสารกันอย่างปลอดภัย
บริบทที่มีขอบเขตและการทำแผนผังบริบท เป็นบทเรียน PHP Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน PHP Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส PHP Academy มีบทเรียนทั้งหมด 4 บทเรียน
DDD เชิงกลยุทธ์
รูปแบบเชิงยุทธวิธีใช้สร้างแบบจำลองออบเจ็กต์ภายในโดเมน ส่วน DDD เชิงกลยุทธ์ใช้ตัดสินใจว่าจะแบ่งระบบขนาดใหญ่ออกเป็นส่วนต่าง ๆ ที่พัฒนาแยกจากกันได้อย่างไร แนวคิดสำคัญคือ บริบทที่มีขอบเขตชัดเจน — ขอบเขตที่ระบุไว้อย่างชัดเจน ซึ่งแบบจำลองโดเมนและภาษาของโดเมนมีความสอดคล้องกัน การทำแผนผังบริบทอธิบายว่าบริบทเหล่านั้นสัมพันธ์กันอย่างไร เรื่องนี้มักส่งผลมากกว่าการออกแบบคลาสใดคลาสหนึ่ง
ภาษาที่ใช้ร่วมกัน
ภายในบริบทที่มีขอบเขตชัดเจน ทีมใช้ ภาษาที่ใช้ร่วมกัน — คำศัพท์ชุดเดียวกันในการสนทนา โค้ด และแบบจำลอง แต่มีข้อควรระวังคือ คำคำหนึ่งอาจมีความหมายต่างกันในแต่ละบริบท Customer ในฝ่ายขาย (ผู้มุ่งหวัง ส่วนลด) ไม่เหมือนกับ Customer ในฝ่ายสนับสนุน (รายการแจ้งปัญหา ข้อตกลงระดับการให้บริการ) บริบทที่มีขอบเขตชัดเจนทำให้เส้นแบ่งนี้ชัดเจน แทนที่จะบังคับให้ใช้แบบจำลองร่วมขนาดใหญ่ที่รวมทุกอย่างไว้
คำเดียวกัน แบบจำลองต่างกัน
แนวคิดทางธุรกิจเดียวกันจะมีแบบจำลองเฉพาะบริบท 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แปลงแบบจำลองจากภายนอกหรือระบบเดิมให้เป็นแบบจำลองที่สะอาดของบริบทคุณ เพื่อไม่ให้แนวคิดจากภายนอกเล็ดลอดเข้ามาภายใน นี่คือการใช้รูปแบบอะแดปเตอร์กับขอบเขตระหว่างบริบท เพื่อปกป้องภาษาที่ใช้ร่วมกันของคุณ
<?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
บริบทกับสถาปัตยกรรม
บริบทที่มีขอบเขตชัดเจนสามารถจับคู่กับหน่วยนำไปใช้งานได้โดยธรรมชาติ ไม่ว่าจะเป็นโมโนลิทแบบแยกส่วนที่มีขอบเขตโมดูลชัดเจน หรือบริการขนาดเล็กที่แยกจากกัน ควรวางขอบเขตรอบความสามารถทางธุรกิจ ไม่ใช่รอบชั้นทางเทคนิค บริการขนาดเล็กที่แยกบริบทเดียวซึ่งผูกโยงกันแน่นออกเป็นหลายส่วน จะกลายเป็นโมโนลิทแบบกระจาย ส่วนขอบเขตบริบทที่สอดคล้องกันอย่างดีจะทำให้ได้บริการที่เปลี่ยนแปลงแยกจากกันได้
เหตุการณ์เป็นรอยต่อ
ในทางปฏิบัติ วิธีที่สะอาดในการให้บริบทต่าง ๆ ผสานรวมกันโดยไม่ใช้แบบจำลองร่วม คือการแลกเปลี่ยนเหตุการณ์ บริบทต้นทางเผยแพร่เหตุการณ์ขนาดเล็กที่เสถียร (ภาษาที่เผยแพร่) ส่วนบริบทปลายทางสมัครรับเหตุการณ์และแปลงเป็นแบบจำลองของตนเอง — โดยไม่เคยนำเข้าคลาสของบริบทต้นทาง
<?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 เชิงกลยุทธ์ บริบทที่มีขอบเขตชัดเจนคือขอบเขตที่แบบจำลองและภาษาที่ใช้ร่วมกันยังคงสอดคล้องกัน ทำให้ทีมไม่ต้องพึ่งแบบจำลองร่วมขนาดใหญ่ที่รวมทุกอย่างไว้ แผนผังบริบทบันทึกความสัมพันธ์ต่าง ๆ ได้แก่ ผู้จัดหาและลูกค้า ผู้ตามแบบ ชั้นป้องกันการแปดเปื้อน แกนกลางร่วม ความร่วมมือ แยกทาง และบริการโฮสต์แบบเปิด/ภาษาที่เผยแพร่ โดยบันทึกทั้งการผสานรวมทางเทคนิคและพลวัตระหว่างทีม ให้วางขอบเขตรอบความสามารถทางธุรกิจ แปลงข้อมูลตรงบริเวณขอบเขต แล้วระบบของคุณจะพัฒนาเป็นส่วนต่าง ๆ ที่นำไปใช้งานแยกจากกันได้
คำถามที่พบบ่อย
บทเรียน “บริบทที่มีขอบเขตและการทำแผนผังบริบท” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “บริบทที่มีขอบเขตและการทำแผนผังบริบท” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส PHP Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส PHP Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “บริบทที่มีขอบเขตและการทำแผนผังบริบท”
แบ่งโดเมนขนาดใหญ่เป็นบริบทที่มีขอบเขตและสื่อสารกันอย่างปลอดภัย คุณปฏิบัติ PHP Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน PHP Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน PHP Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “บริบทที่มีขอบเขตและการทำแผนผังบริบท” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน PHP Academy นี้ได้ไหม
ได้ บทเรียน PHP Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- องค์ประกอบพื้นฐาน DDD: เอนทิตีและออบเจ็กต์ค่า
- แอกกริเกต รีโพซิทอรี และแฟกทอรี
- เหตุการณ์โดเมนและบริการโดเมน
- บริบทที่มีขอบเขตและการทำแผนผังบริบท