🏛️
14-Day Mastery Roadmap

SECURE BY DESIGN DAY 03

เริ่มทำควิซ ⚡
Part 2: Fundamentals | Chapter 3

Core Concepts of Domain-Driven Design

Part 2 Kickoff: DDD Architecture 🏛️
📌 TITLE ANCHOR QUESTION ทำไมบทนี้ถึงชื่อนี้? และเครื่องมือ DDD เกี่ยวข้องกับ Security อย่างไร?

คำตอบและหมุดเชื่อมโยง: คำว่า "Core concepts of Domain-Driven Design" ตั้งขึ้นเพื่อรวบรวม "อิฐบล็อกพื้นฐานในการสร้างซอฟต์แวร์" (Ubiquitous Language, Value Objects, Entities, Aggregates, และ Bounded Contexts)

สาเหตุที่ระบบซอฟต์แวร์ส่วนใหญ่มีช่องโหว่ความปลอดภัย ไม่ใช่เพราะโปรแกรมเมอร์สะเพร่าทางเทคนิคเสมอไป แต่เกิดจาก "การข้ามพรมแดนทางความหมาย (Semantic Boundaries) และโมเดลที่ไม่รัดกุม" การเข้าใจแนวคิดหลักของ DDD ช่วยให้เราสร้างโมเดลที่นิยามขอบเขตของระบบอย่างชัดเจน และเมื่อระบบถูกบีบให้นิยามชัดเจนว่า "ทำอะไรได้บ้าง" สิ่งที่ระบบ "ห้ามทำ" (ซึ่งก็คือช่องโหว่ความปลอดภัย) จะถูกกำจัดออกไปโดยอัตโนมัติ!

วันก่อนหน้า (Recap Days 1 & 2)

Day 1: Security as a Concern (คดีตู้นิรภัย) / Day 2: The Anti-Hamlet (-1 เล่ม) และความสูญเสียจาก Shallow Modeling

ตำแหน่งปัจจุบัน (Where We Are)

Day 3 จาก 14 วัน — เริ่มต้น Part 2: Fundamentals (รากฐานโครงสร้างระดับสถาปัตยกรรมและโค้ด)

เป้าหมายประจำวัน (Core Mission)

เข้าใจอาวุธหลักทั้ง 5 ชิ้นของ DDD เพื่อนำไปใช้สร้างอิฐบล็อกสยบช่องโหว่ความปลอดภัยในโค้ดตั้งแต่วันถัดๆ ไป (Day 4–7)

02

เรื่องราวและมโนทัศน์เชิงลึก (The Denver Airport Case & 5 Core Tools)

✈️ CASE STUDY 2.1 • โครงการระบบจัดการกระเป๋าเดินทางอัตโนมัติ สนามบินเดนเวอร์ (1990) Domain Complexity

📖 เรื่องราวจริงทางประวัติศาสตร์

ในช่วงปี ค.ศ. 1990 สนามบินสากลเดนเวอร์ (Denver International Airport) สหรัฐอเมริกา ทุ่มงบประมาณมหาศาลสร้างระบบจัดการกระเป๋าเดินทางอัตโนมัติ (Automated Baggage System) เพื่อรองรับเที่ยวบินขนาดใหญ่

💥 หายนะที่เกิดขึ้น: ระบบเปิดล่าช้ากว่ากำหนดถึง 1 ปีครึ่ง สร้างความเสียหายทางเศรษฐกิจหลายร้อยล้านดอลลาร์ สาเหตุไม่ได้เกิดจากโปรแกรมเมอร์ปรับ Database Connection Pool ไม่ดี หรืออัลกอริทึมค้นหาช้า แต่เกิดจาก "การขุดไม่ลึกพอในความซับซ้อนของโดเมนการจัดการกระเป๋า (Domain Complexity)"

🧠 ถอดรหัสสู่โลกซอฟต์แวร์และ Security (Mental Model)

⚡ Technical Failure: หากคุณล้มเหลวในการจัดการความซับซ้อนทางเทคนิค ระบบอาจจะแค่ทำงานช้าลง
🎯 Domain Failure: แต่ถ้าคุณล้มเหลวในการเข้าใจโดเมนธุรกิจ ระบบของคุณจะ "ทำงานผิดเรื่องทันที (Doing the wrong thing)"
🛡️ การทำผิดเรื่อง ส่งผลกระทบโดยตรงต่อ Data Integrity และเปิดช่องโหว่ความปลอดภัยระดับร้ายแรง
🏛️ 5 เครื่องมือหลักของ DDD (EXPLICIT TERM EXPLANATIONS & ANALOGIES) Foundations for Security
TOOL 01 Shared Vocabulary

🗣️ Ubiquitous Language

ภาษาที่ถูกตกลงและใช้ร่วมกันอย่างเคร่งครัดโดยทุกคนในทีม ทั้ง Domain Experts, Developers, Testers, ในเอกสาร, ซอร์สโค้ด, Database และบนหน้าจอ UI

🩺 Analogy: เหมือน "ศัพท์แพทย์ในห้องผ่าตัด" หมอและพยาบาลไม่พูดว่า "เอาไอ้นั่นตัดตรงนี้" แต่ใช้ชื่อเฉพาะ เพราะความคลุมเครือหมายถึงชีวิต
🛡️ Security Dimension: หากเรียก Quantity บ้าง Amount บ้าง Volume บ้าง ความสับสนนี้จะกลายเป็นรอยแตกร้าวทางตรรกะที่แฮกเกอร์ใช้เจาะ (เช่น กรณี Anti-Hamlet)
TOOL 02 Defined by Value

🧱 Value Objects

วัตถุที่ ไม่มี Identity (ไม่มี ID) นิยามความมีตัวตนด้วย "มูลค่า/ค่าของมันเอง" สองวัตถุที่ค่าเท่ากันถือว่าเป็นวัตถุเดียวกัน และ ต้อง Immutable เสมอ

💵 Analogy: "ธนบัตร 20 บาท" แลกใบ 20 บาทกับเพื่อน เราไม่รู้สึกว่าเสียอะไร เพราะเราสนใจแค่มูลค่า $20 ไม่ได้สนใจว่าเป็นธนบัตรใบไหน
🛡️ Security Dimension: ปรับเปลี่ยนค่าไม่ได้ (Immutable) ปลอดภัยจากการแอบแก้ไขค่าข้าม Threads ("No locking, no blocking")
TOOL 03 Continuous Identity

🆔 Entities

วัตถุที่มี Identity ชัดเจนและต่อเนื่องตลอด Life Cycle แม้ Attributes อื่นๆ ภายในจะถูกแก้ไขเปลี่ยนแปลงไปตามกาลเวลาก็ตาม (Mutable State)

🪪 Analogy: "บัตรประชาชนของพลเมือง" สมชายเปลี่ยนชื่อ นามสกุล ที่อยู่ ย้อมผม แต่อัตลักษณ์ยังคงเดิมผ่าน "เลขบัตรประชาชน 13 หลัก"
🛡️ Security Dimension: ทำหน้าที่เป็นผู้ควบคุมและจัดระเบียบ (Coordinator) วัตถุภายในทั้งหมด ห้ามเปิดให้ภายนอกแอบแก้ค่าตรงๆ
TOOL 04 Boundary Gateway

📦 Aggregates & Roots

ขอบเขตเชิงมโนทัศน์ (Conceptual Boundary) ที่รวม Entities และ Value Objects เข้าด้วยกัน มี Aggregate Root เป็นประตูทางเข้าเดียวที่ภายนอกอ้างอิงได้

🚗 Analogy: "รถยนต์ (Car)" เป็น Root ส่วน Engine และ Wheel คือวัตถุภายใน จะขับรถต้องสั่งผ่าน car.steer() ห้ามเดินไปฉีดน้ำมันเข้าห้องเผาไหม้เอง!
🛡️ Security Dimension: ทำหน้าที่เป็น Integrity Boundary ป้องกันไม่ให้โค้ดภายนอกแอบเจาะแก้ไขข้อมูลลูกภายในโดยตรง
TOOL 05 Semantic Boundary

🗺️ Bounded Context & Semantic Boundary

ขอบเขตที่กำหนดว่า Ubiquitous Language และโมเดลมีความหมายสมบูรณ์และถูกต้องอยู่แค่ภายในพื้นที่นั้น เมื่อก้าวข้าม Bounded Context ความหมายของคำจะเปลี่ยนไปทันที

📦 Analogy คำว่า "Package":
- แผนกจัดส่ง (Shipping Context) ➔ "กล่องพัสดุสีน้ำตาลติดเทป"
- แผนกไอที (IT Context) ➔ "กลุ่มไฟล์ซอร์สโค้ด .jar"
การฝืนสร้างคลาส Package รวมทั้งสองเรื่องเข้าด้วยกันจะนำไปสู่ความหายนะ
⚠️ Security Risk:

"Data crossing a semantic boundary is a major security risk" การส่งข้อมูลข้าม Bounded Context โดยไม่มี Translation Layer มักทำให้กฎความปลอดภัยเล็ดลอดและเกิดการแฮกเชิงตรรกะ

03

แบบฝึกหัดปฏิบัติตามสถานการณ์จริง (Hands-on Refactoring)

Before: Anemic Domain Model (เสี่ยงช่องโหว่) Public Mutable Collection
// โค้ดเดิม: Customer เป็นเพียงถุงใส่ข้อมูล ไร้ขอบเขต Aggregate
public class Customer {
    public String id;
    public String name;
    // ช่องโหว่ใหญ่: เปิด Public Collection ให้ภายนอกแอบแก้!
    public List<Address> addresses = new ArrayList<>(); 
}

public class OrderService {
    public void changeShippingAddress(Customer customer, Address newAddress) {
        // แอบแก้ไข Address ใน Customer จากภายนอกโดยไม่ผ่าน Invariants!
        customer.addresses.clear();
        customer.addresses.add(newAddress);
    }
}
⚠️ จุดพังของโค้ด: Customer กลายเป็นโครงร่างไร้ชีวิต (Anemic) โค้ดภายนอกสั่ง customer.addresses.clear() ลบที่อยู่ทิ้งได้โดยที่คลาส Customer ไม่สามารถคัดค้านได้เลย
After: DDD Secure Aggregate Root Encapsulated Invariants & Unmodifiable
// 1. Value Object: Address เป็น Immutable และ Conceptual Whole
public final class Address {
    private final String street;
    private final String zipCode;
    private final String city;

    public Address(String street, String zipCode, String city) {
        this.street = notEmpty(street, "Street required");
        this.zipCode = notEmpty(zipCode, "ZipCode required");
        this.city = notEmpty(city, "City required");
    }
    // มีแต่ getters เท่านั้น ไม่มี setters!
}

// 2. Aggregate Root: Customer ปกป้อง Invariants ควบคุมทางเดียว
public class Customer {
    private final CustomerId id; // Identity
    private String name;
    private final List<Address> addresses = new ArrayList<>();

    public Customer(CustomerId id, String name, Address primaryAddress) {
        this.id = notNull(id);
        this.name = notEmpty(name);
        this.addresses.add(notNull(primaryAddress));
    }

    // Encapsulated Domain Operation แทนการเปิด List ให้แก้
    public void updatePrimaryAddress(Address newAddress) {
        notNull(newAddress, "New address cannot be null");
        this.addresses.set(0, newAddress);
    }

    // ส่งออกเฉพาะ Unmodifiable List ป้องกันภายนอกแอบแก้ไข
    public List<Address> addresses() {
        return Collections.unmodifiableList(addresses);
    }
}
🛡️ จุดเปลี่ยนสำคัญ: โค้ดภายนอกไม่สามารถสั่ง addresses.clear() ได้อีกต่อไป เพราะคืนค่าเป็น unmodifiableList และการอัปเดตต้องสั่งผ่าน updatePrimaryAddress() ของ Aggregate Root เท่านั้น!
04

ชุดควิซประเมินความรู้ประจำวัน

ตอบปุ๊บ รู้ผลเฉลยทันที พร้อมคำอธิบายและหลอดพลังงาน Energy Charge

Energy Charge
0 / 10
📌 CLOSING TITLE CONNECTION WRAP-UP สรุปหมุดเชื่อมโยงกลับหาหัวข้อบท

สรุปการเชื่อมโยงกลับสู่ Chapter 3 — Core concepts of Domain-Driven Design

เครื่องมือทั้ง 5 ชิ้น (Ubiquitous Language, Value Objects, Entities, Aggregates, และ Bounded Contexts) ในบทนี้ ล้วนตอบคำถามหัวข้อบทอย่างชัดเจนว่า การเข้าใจแนวคิดหลักของ DDD คือหัวใจของการสร้างระบบที่ปลอดภัย เพราะเมื่อเราแบ่งขอบเขตด้วย Bounded Context, ใช้ Ubiquitous Language สื่อสารอย่างตรงไปตรงมา, ปกป้องสถานะด้วย Aggregate Root, และล็อกค่าด้วย Value Objects ตัวโครงสร้างการออกแบบเหล่านี้เองที่จะทำหน้าที่เป็นเกราะคุ้มกันความปลอดภัยที่ทนทานที่สุดให้แก่ซอฟต์แวร์ของเราครับ!

พร้อมก้าวสู่เครื่องมือระดับโค้ดในบทถัดไปแล้วหรือยัง? Next: Day 4 — Chapter 4: Code constructs promoting security (Immutability & Pipeline) ➔