🎭
14-Day Mastery Roadmap

SECURE BY DESIGN DAY 02

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

Intermission: The Anti-Hamlet

Case Study: Business Integrity ⚠️
📌 TITLE ANCHOR QUESTION ทำไมบทนี้ถึงชื่อนี้? และคำว่า Anti-Hamlet หมายความว่าอย่างไร?

คำว่า "Anti-Hamlet": มาจากการเปรียบเปรยกับคำว่า Anti-matter (ปฏิสสาร) ในทางฟิสิกส์ หากหนังสือ Hamlet เล่มปกติ 1 เล่มมีราคา +$39 (มีมวลและมูลค่าเป็นบวก) หนังสือ Anti-Hamlet (-1 เล่ม) ก็คือ "ปฏิสสารทางธุรกิจ" ที่มีมูลค่าติดลบ -$39!

คำตอบและหมุดเชื่อมโยง: เมื่อผู้ใช้สั่งซื้อ Anti-Hamlet เข้ามา มูลค่าติดลบของมันจะเข้าไป "หักลบและกลืนกิน" ยอดราคารวมในตะกร้าให้ลดลง หรือแม้กระทั่งบังคับให้ระบบบัญชี "สั่งจ่ายเงินคืนให้แก่ลูกค้า" และทำให้ระบบคลังสินค้า "เสกหนังสือเล่มใหม่ขึ้นมาเองจากความว่างเปล่า" (เพราะ \(15 - (-1) = 16\)) ผู้เขียนตั้งชื่อบทนี้เพื่อใช้เป็นอุทาหรณ์เตือนสติว่า การออกแบบโมเดลแบบตื้นเขิน (Shallow Modeling) ที่ใช้ Primitive Type (int) โดยไม่มี Invariants จะสร้างช่องโหว่ความปลอดภัยที่ดูดเงินบริษัทไหลออกตลอดหลายเดือนโดยที่ ไม่มี Alert ใดๆ แจ้งเตือนเลยแม้แต่ตัวเดียว!

วันก่อนหน้า (Recap Day 1)

Security as a Concern (คดีตู้นิรภัย Öst-Götha Bank), Username Domain Invariants และ Billion Laughs XML Defense-in-depth

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

Day 2 จาก 14 วัน — ยังอยู่ใน Part 1: บทแทรกละครชีวิตจริงกรณีศึกษา Anti-Hamlet

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

เข้าใจรากของปัญหา Shallow Modeling vs. Deep Modeling และเห็นปฏิกิริยาโดมิโนข้ามระบบเมื่อกฎธุรกิจถูกละเมิด

02

เรื่องราวและมโนทัศน์เชิงลึก (The 3 Acts & System Chain Reaction)

🎭 THE 3 ACTS • เรื่องราวของ JOE TESTER และคดีสั่งซื้อหนังสือติดลบ (-1 HAMLET) True Case Study
🎬 ฉากที่ 1: การสอบทานที่ไร้รอยต่อ

บริษัทขายหนังสือออนไลน์ข้ามชาติว่าจ้างทีม Security Audit เข้ามาเจาะระบบ Production จริง ทีมงานยิงแพ็กเกจขยะใส่ Firewall, สแกน OS Port, เจาะ Session/Cookie, ยิง SQLi/XSS... ผลคือ "โครงสร้างพื้นฐานแน่นหนามาก" ไม่พบช่องโหว่ดั้งเดิมเลยแม้แต่น้อย!

🎬 ฉากที่ 2: การทดลองของ Joe Tester

Joe Tester ขยับมาทดสอบฟอร์มสั่งซื้อตรงช่อง Quantity หนังสือ Hamlet เล่มละ $39 Joe ยิง JS ➔ ไม่รัน, ยิง SQLi ➔ ปฏิเสธ... สุดท้าย Joe เกิดความสงสัย จึงลองกรอก -1 ผลคือ: ระบบสั่งซื้อผ่าน, ตัดบัตรเครดิตผ่าน, และส่งอีเมลยืนยันทันที!

🎬 ฉากที่ 3: หญิงสาวจากฝ่ายบัญชี

บ่ายวันถัดมา พนักงานบัญชีเดินเข้ามาถามทีมว่า "มีใครรู้จักคนชื่อ Joe Tester ไหมคะ? ระบบบัญชีลูกหนี้พิมพ์เช็คสั่งจ่ายเงิน $39 ส่งไปให้เขา แต่พอจะใส่ซอง พบว่าที่อยู่ของ Joe คือสำนักงานใหญ่ของบริษัทเราเองค่ะ!"

⚡ THE CHAIN REACTION • ปฏิกิริยาโดมิโนข้าม 4 ระบบย่อยเมื่อตัวเลข -1 ไหลผ่าน Domino Effect
1. Billing System -$39

รับยอด -$39 เข้ามา โมดูลตัดบัตรเครดิตรองรับเฉพาะยอดบวก เมื่อเจอยอดติดลบ มันคิดว่า "ไม่มีเงินต้องเรียกเก็บ" จึงปล่อยผ่านรายการไปเงียบๆ โดยไม่ตัดเงินบัตร Joe

2. Accounts Receivable หนี้ -$39

ระบบบัญชีมีหลักการว่า Balance ติดลบหมายถึง "ร้านค้าเป็นหนี้ลูกค้า $39" เมื่อรัน Batch Job ตอนดึก ระบบจึง พิมพ์เช็คสั่งจ่ายเงิน $39 ส่งไปให้ Joe ฟรีๆ!

3. Inventory System 15 - (-1) = 16

ขายปกติสต็อกลด \(15 - 1 = 14\) แต่พอสั่ง -1 เล่ม ระบบคำนวณ \(15 - (-1) = 16\)! การขาย Anti-Hamlet ส่งผลให้ สต็อกในระบบเพิ่มขึ้นเอง 1 เล่มจากความว่างเปล่า!

4. Shipping System Exception

เจอรายการสั่งซื้อจำนวน -1 ชิ้น จัดส่งไม่ได้ จึงโยน RuntimeException ทิ้งลงใน System Log (ซึ่งไม่มีใครเปิดอ่าน) แล้วปล่อยคำสั่งซื้อผ่านไปเงียบๆ

CONCEPT 2.3.1

👻 Systems Living the Same Lie

ปรากฏการณ์ที่ระบบ IT หลายระบบบันทึกข้อมูลเท็จ แต่ตัวเลขทางคณิตศาสตร์ข้ามระบบดัน "หักลบดุลกันเป๊ะพอดี":

📦 คลังคิดว่ามี 16 เล่ม (+1 เล่ม = +$39)
💰 บัญชีคิดว่าติดหนี้ลูกค้า (-$39)
📊 งบไตรมาสดุลเป๊ะ! ไม่มี Alert ใดๆ เด้งขึ้นมาเลย

ความจริงเปิดเผยตอนนับสต็อกสิ้นปี (End-of-year inventory) เมื่อของหาย ผู้บริหารคิดว่าพนักงานขโมยของ จนถึงขั้นส่งพนักงานไปอบรมจริยธรรม!

CONCEPT 2.3.2

🎟️ Do-It-Yourself Discount Vouchers

การนำช่องโหว่ Anti-book มาแอบใช้เป็น "คูปองส่วนลดที่สร้างเองได้ตามใจชอบ" โดยใส่สินค้าติดลบเข้าไปในตะกร้าเพื่อลดราคารวม:

ยอดซื้อปกติ: $246
+ Anti-Hamlet (-1 เล่ม): -$39
ยอดจ่ายจริงเหลือเพียง: $207

ข่าวลือการลดราคานี้แพร่สะพัดเงียบๆ ทำให้บริษัทสูญเสียเงินมหาศาลตลอดหลายเดือนโดยระบบจับไม่ได้

CONCEPT 2.3.3

⛏️ Shallow vs. Deep Modeling

Shallow Modeling (ตื้นเขิน): มุ่งเน้นแค่ "จะเขียนโค้ดยังไงดี?" จึงจับคู่ Quantity เข้ากับ int ซึ่งรับค่าได้ตั้งแต่ -2.1 พันล้าน ถึง +2.1 พันล้าน เปิดช่องให้ค่าติดลบทะลุผ่าน
Deep Modeling (เชิงลึก): คุยกับ Domain Expert ทำสิ่งที่แฝง (Implicit) ให้ชัดเจน (Explicit) สร้างคลาส Quantity ที่ล็อก Invariants ว่าต้องเป็น 1 ถึง 240 เท่านั้น
03

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

Before: Shallow Model (Primitive Obsession) ยอมรับตัวเลขติดลบ
// โค้ดเดิม: มองทุกอย่างเป็น Primitive Types
class Book {
    String title;
    String isbn;
    double price; // WARNING: ห้ามใช้ float/double เก็บเงิน!
}

class Order {
    // ใช้ int รับ quantity เปิดโอกาสให้ส่งค่าติดลบ (-1) เข้ามาได้
    void addOrderLine(Book book, int quantity) {
        // ไม่มี Validation เช็กค่าติดลบ!
        OrderLine line = new OrderLine(book, quantity);
        this.orderLineList.add(line);
    }
}
⚠️ จุดพังของโค้ด: คอมไพเลอร์มองว่า int quantity = -1 เป็นตัวเลขที่ถูกต้องตามไวยากรณ์ภาษา โค้ดจึงทำงานผ่านฉลุยและสร้างตัวเลข -$39 ส่งต่อไปทำลายระบบบัญชีและคลังสินค้า
After: Deep Model (Quantity Domain Primitive) Invariants Valid on Creation
// 1. สร้าง Domain Primitive สำหรับ Quantity ลบล้างค่าติดลบตั้งแต่แรก
public final class Quantity {
    private final int value;

    public Quantity(int value) {
        // บังคับกฎ Invariants ทันทีใน Constructor (Fail-Fast)
        isTrue(value > 0, "Quantity must be positive");
        isTrue(value <= 240, "Cannot exceed box capacity of 240");
        this.value = value;
    }
    public int value() { return value; }

    public Quantity add(Quantity addend) {
        notNull(addend, "Addend cannot be null");
        return new Quantity(this.value + addend.value);
    }
}

// 2. ปรับปรุง Order Class ให้รับเฉพาะ Quantity Type เท่านั้น
public class Order {
    public void addOrderLine(Book book, Quantity quantity) {
        this.orderLineList.add(new OrderLine(notNull(book), notNull(quantity)));
    }
}
🛡️ จุดเปลี่ยนสำคัญ: โค้ดใหม่ปฏิเสธค่าติดลบตั้งแต่ตอนสร้าง new Quantity(-1) คอมไพเลอร์และ Runtime จะไม่อนุญาตให้วัตถุ Anti-Hamlet มีตัวตนอยู่ในระบบได้เลยแม้แต่วินาทีเดียว!
04

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

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

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

สรุปการเชื่อมโยงกลับสู่ Chapter 2 — Intermission: The anti-Hamlet

เรื่องราวของ Joe Tester, เช็คสั่งจ่ายเงินฝั่งบัญชี, สต็อกที่เพิ่มขึ้นเองในคลัง, และพฤติกรรม DIY Discount Vouchers ทั้งหมดนี้ ล้วนเป็นผลพวงมาจากวัตถุติดลบที่เรียกว่า "Anti-Hamlet" ซึ่งสะท้อนให้เห็นอย่างชัดเจนว่า หากเราออกแบบโมเดลแบบตื้นเขิน (Shallow Modeling) ปล่อยให้ Primitive Types อย่าง int เพ่นพ่านในระบบโดยไม่มีการทำ Deep Model ผลลัพธ์ของ Anti-Hamlet จะสร้างความสูญเสียทางธุรกิจมหาศาลโดยไม่มีเตือนภัยใดๆ เด้งขึ้นมาเลยครับ!

พร้อมก้าวสู่รากฐานสถาปัตยกรรมระดับถัดไปแล้วหรือยัง? Next: Day 3 — Chapter 3: Core concepts of Domain-Driven Design (DDD) ➔