ข้าม​ไป​ยัง​เนื้อหา

Domain

องค์​ความ​รู้ กิจกรรม และ​ประเด็น​ทั้งหมด​ของ​ธุรกิจ​หนึ่ง ๆ

ใน Domain-Driven Design (DDD) domain คือ “subject area ที่​ผู้​ใช้​นำ​โปรแกรม​ไป​ประยุกต์​ใช้” ตาม​คำ​ของ Eric Evans ผู้​บัญญัติ​ศัพท์​นี้​ไว้​ใน​หนังสือ Domain-Driven Design: Tackling Complexity in the Heart of Software (2003) กล่าว​อีก​แบบ domain คือ​องค์​ความ​รู้ กิจกรรม กฎเกณฑ์ และ​ประเด็น​ทั้งหมด​ที่​เกี่ยวข้อง​กับ​ปัญหา​ทาง​ธุรกิจ​ที่​ซอฟต์แวร์​ถูก​สร้าง​ขึ้น​มา​เพื่อ​รับใช้ ไม่ใช่​ตัว​ซอฟต์แวร์​เอง แต่​เป็น “โลก​จริง” ที่​ซอฟต์แวร์​พยายาม​จำลอง

domain มัก​ซับซ้อน​เกิน​กว่า​จะ​จำลอง​เป็น​หน่วย​เดียว​ได้​อย่าง​มี​ความหมาย ตัวอย่าง​เช่น domain รวม​ของ​ระบบ eCommerce อาจ​เรียก​ได้​ว่า​เป็น “การ​ค้า​ปลีก​ออนไลน์” (online retail) ซึ่ง​ครอบคลุม​ทั้ง​การ​จัดการ​สินค้า การ​ชำระ​เงิน การ​จัด​ส่ง การ​ดูแล​ลูกค้า ฯลฯ — แต่ละ​ส่วน​มี​ภาษา​และ​กฎ​ของ​ตัวเอง

ลักษณะ​สำคัญ​ของ domain ได้แก่

  • Entities — สิ่ง​หลัก​ที่​มี​อยู่​ใน​โลก​ของ​ธุรกิจ เช่น ลูกค้า สินค้า คำ​สั่ง​ซื้อ
  • Rules — กฎ​ที่​กำกับ​พฤติกรรม​และ​ความ​ถูกต้อง​ของ​ข้อมูล​ใน​ธุรกิจ​นั้น
  • Processes — กระบวนการ​ทาง​ธุรกิจ เช่น การ​ประมวล​ผล​คำ​สั่ง​ซื้อ การ​อนุมัติ​สินเชื่อ
  • Domain boundaries — ขอบเขต​ที่​แยก domain หนึ่ง​ออก​จาก​อีก domain หนึ่ง

เพราะ domain มักใหญ่​และ​ซับซ้อน DDD จึง​แนะนำ​ให้​แตก​ออก​เป็น subdomain ย่อย ๆ ที่​จัดการ​ได้​ง่าย​กว่า และ​จัด​ลำดับ​ความ​สำคัญ​ด้วย​แนวคิด Core Domain — พื้นที่​หลัก​ที่​สร้าง​ความ​แตก​ต่าง​เหนือ​คู่แข่ง​และ​ควร​ได้​รับ​ความ​ใส่ใจ​ใน​การ​ออกแบบ​มาก​ที่สุด ส่วน Supporting subdomain และ Generic subdomain มี​ความ​สำคัญ​รอง​ลง​มา (ดู Subdomains)

domain คือ​จุด​เริ่มต้น​ของ DDD ทั้งหมด — ก่อน​จะ​เขียน code สัก​บรรทัด ทีม​ต้อง​ทำความ​เข้าใจ domain ผ่าน​การ​พูด​คุย​กับ domain expert เทคนิค​อย่าง Event Storming หรือ Domain Storytelling ช่วย​ให้​ทีม​สำรวจ domain แบบ​มี​โครงสร้าง​โดย​ไม่​ต้อง​รีบ​ตัดสิน​ใจ​เรื่อง​เทคโนโลยี

เมื่อ​เข้าใจ domain แล้ว งาน​ออกแบบ​ใน DDD แบ่ง​เป็น​สอง​ระดับ:

  1. Strategic Design (Strategic Design) — มอง​ภาพ​ใหญ่ ว่า domain ควร​ถูก​แบ่ง​เป็น subdomain อะไร​บ้าง และ​แต่ละ subdomain ควร​สอดคล้อง​กับ Bounded Context ใด พร้อม​ทำ Context Mapping เพื่อ​บันทึก​ความ​สัมพันธ์​ระหว่าง context เหล่า​นั้น
  2. Tactical Design (Tactical Design) — ลง​รายละเอียด​ภายใน​แต่ละ Bounded Context ด้วย pattern เช่น Entity, Value Object, Aggregate เพื่อ​สร้าง Domain Model ที่​สะท้อน​กฎ​ของ domain จริง

ทีม​และ domain expert ร่วม​กัน​สร้าง Ubiquitous Language — ภาษา​กลาง​ที่​ใช้​เรียก​แนวคิด​ใน domain อย่าง​สอดคล้อง​กัน​ทั้ง​ใน​บทสนทนา เอกสาร และ code เพราะ​คำ​เดียวกัน​อาจ​มี​ความหมาย​ต่าง​กัน​ใน domain หรือ Bounded Context ต่าง​กัน (เช่น​คำ​ว่า “Account” ใน​บริบท​บัญชี​ผู้​ใช้ กับ “Account” ใน​บริบท​บัญชี​การเงิน)

Vaughn Vernon ใน Implementing Domain-Driven Design เน้น​ย้ำ​ว่าการ​ลงทุน​เวลา​ทำความ​เข้าใจ domain ให้​ลึก​คือ​สิ่ง​ที่​แยก DDD ออก​จาก​การ​ออกแบบ​ซอฟต์แวร์​ทั่วไป เพราะ model ที่​ดี​ต้อง​ผ่าน​การ​ทำซ้ำ (iterate) ร่วม​กับ domain expert ไม่ใช่​เดา​เอา​จาก requirement document เพียง​อย่าง​เดียว

สมมติ​บริษัท Fabrikam ทำ​ธุรกิจ​ส่ง​พัสดุ​ด้วย​โด​รน domain รวม​ของ​บริษัท​คือ “การ​จัด​ส่ง​ด้วย​โด​รน” ซึ่ง​เมื่อ​วิเคราะห์​แล้ว​แตก​เป็น​หลาย subdomain: Shipping และ Drone Management เป็น Core subdomain เพราะ​เป็น​จุด​ที่​สร้าง​ความ​ได้​เปรียบ ส่วน Invoicing เป็น Supporting subdomain และ User Accounts กับ Call Center เป็น Generic subdomain ที่​อาจ​ใช้​ระบบ​สำเร็จรูป​แทน​ได้

graph TD
    Domain[Domain: Drone Delivery]
    Core1[Core: Shipping]
    Core2[Core: Drone Management]
    Supporting[Supporting: Invoicing]
    Generic1[Generic: User Accounts]
    Generic2[Generic: Call Center]
    BC1[Bounded Context: Shipping]
    BC2[Bounded Context: Accounts]
    UL[Ubiquitous Language]

    Domain --> Core1
    Domain --> Core2
    Domain --> Supporting
    Domain --> Generic1
    Domain --> Generic2
    Core1 --> BC1
    Generic1 --> BC2
    BC1 --> UL
    BC2 --> UL

code ด้าน​ล่าง​แสดง​ว่าการ​แบ่ง domain และ subdomain ไม่ใช่​แค่​แนวคิด​บน​กระดาน แต่​สะท้อน​ลง​มา​ถึง​โครงสร้าง namespace และ​ตำแหน่ง​ที่​กฎ​ของ domain (“domain logic”) อยู่​ใน code จริง

// Core subdomain: การจัดส่งคือหัวใจของธุรกิจ ต้องจำลองอย่างละเอียดและดูแลใกล้ชิดที่สุด
namespace Fabrikam.Shipping.Domain
{
public class DeliveryOrder
{
public Guid Id { get; }
public DroneAssignment Assignment { get; private set; }
public DeliveryOrder(Guid id)
{
Id = id;
}
// กฎของ domain (domain rule) ถูกเก็บไว้ในตัว Entity เอง
// ไม่ใช่กระจัดกระจายอยู่ใน service หรือ controller ภายนอก
public void AssignDrone(Drone drone)
{
if (!drone.IsAvailable)
{
throw new InvalidOperationException("โดรนลำนี้ไม่ว่างสำหรับงานจัดส่ง");
}
Assignment = new DroneAssignment(drone.Id, DateTime.UtcNow);
}
}
public record DroneAssignment(Guid DroneId, DateTime AssignedAtUtc);
public class Drone
{
public Guid Id { get; }
public bool IsAvailable { get; private set; } = true;
public Drone(Guid id) => Id = id;
}
}
// Generic subdomain: การจัดการบัญชีผู้ใช้ไม่ใช่จุดต่างของธุรกิจ
// จึงเรียบง่ายกว่ามาก และอาจแทนที่ด้วยบริการสำเร็จรูป (เช่น identity provider) ได้
namespace Fabrikam.Accounts.Domain
{
public class UserAccount
{
public Guid Id { get; }
public string Email { get; private set; }
public UserAccount(Guid id, string email)
{
Id = id;
Email = email;
}
}
}

สังเกต​ว่า Fabrikam.Shipping.Domain มี invariant และ business rule ที่​ซับซ้อน สม​กับ​เป็น Core subdomain ใน​ขณะ​ที่ Fabrikam.Accounts.Domain เป็น​เพียง data holder ง่าย ๆ เพราะ​เป็น Generic subdomain — นี่​คือ​วิธี​ที่​การ​เข้าใจ domain อย่าง​ถูกต้อง​นำ​ไป​สู่​การ​ตัดสิน​ใจ​ลงทุน​ความ​พยายาม​ใน​การ​ออกแบบอย่าง​เหมาะสม

  • Domain vs. Subdomain — domain และ subdomain เป็น​คำ​สัมพัทธ์ (relative term) เดียวกัน ต่าง​กัน​แค่​ระดับ: เมื่อ​เรียก​บาง​สิ่ง​ว่า subdomain หมายความ​ว่า​มัน​เป็น​ส่วน​ย่อย​ของ domain ที่​ใหญ่​กว่า​ซึ่ง​เรา​กำลัง​พูด​ถึง​อยู่ ดู Subdomains
  • Domain vs. Bounded Context — domain/subdomain อยู่​ใน “problem space” (พื้นที่​ปัญหา​ทาง​ธุรกิจ) ส่วน Bounded Context อยู่​ใน “solution space” (พื้นที่​คำ​ตอบ​ที่​ทีม​ออกแบบ) โดย​อุดมคติ​แล้ว​แต่ละ subdomain ควร​ถูก​จับ​คู่​กับ Bounded Context หนึ่ง​เดียว แต่​ใน​ทาง​ปฏิบัติ​ความ​สัมพันธ์​อาจ​ไม่​ตรง​กัน​เป๊ะ ดู Bounded Context
  • Domain vs. Domain Model — domain คือ​ความ​รู้​และ​ความ​เป็น​จริง​ทาง​ธุรกิจ ส่วน Domain Model คือ​ตัวแทน​เชิง​ซอฟต์แวร์​ของ​ความ​รู้​นั้น​ที่​ทีม​สร้าง​ขึ้น​และ​วิวัฒน์​ไป​พร้อม​กับ​ความ​เข้าใจ​ที่​ลึก​ขึ้น
  • Domain vs. Ubiquitous LanguageUbiquitous Language คือ​ภาษา​ที่​ทีม​และ domain expert ใช้​ร่วม​กัน​เพื่อ​อธิบาย domain นั้น​ให้​ตรง​กัน​ทั้ง​ใน​คำ​พูด​และ code
  • Core Domain vs. Shared Kernel — เมื่อ​หลาย Bounded Context ต้อง​ใช้​แนวคิด​ร่วม​กัน​จาก domain เดียวกัน อาจ​เลือก​ทำ Shared Kernel เพื่อ share model บาง​ส่วน​อย่าง​ระมัดระวัง