System Architecture & Data Modeling
สำหรับแพลตฟอร์ม Grocery POS
จากโครงงานปี 1 ที่สกัดสถิติจากไฟล์ CSV แบบ Static สู่โครงงานปี 2 (1145 204) ที่ทีม 4–5 คนต้องออกแบบระบบ POS ร้านขายของชำครบวงจรด้วยฐานข้อมูลเชิงสัมพันธ์ 3NF, สัญญา API ที่ชัดเจน และความทนทานต่อการใช้งานหน้าร้านพร้อมกันหลายจุด
เส้นทางพัฒนาการชิ้นงาน POS ในหลักสูตร (ปี 1 → ปี 2 → ปี 3)
| ชั้นปี / รายวิชา | เป้าหมายเชิงสถาปัตยกรรม | โครงสร้างข้อมูล (Data Complexity) | ระดับพัฒนาการ |
|---|---|---|---|
| ปี 1 · 1145 103 | สกัดและสรุปยอดขายด้วย Python/Pandas | ไฟล์ CSV / JSON แบบ Static Log (ลบ PII เบื้องต้น) | Reinforced (R) |
| ปี 2 · 1145 204 (สัปดาห์นี้) | พัฒนาระบบ POS หน้าร้าน + คลังสินค้าแบบทีม Agile (Scrum) | ฐานข้อมูลเชิงสัมพันธ์ Relational DB (3NF) + REST API | Practiced (P) |
| ปี 3 · DS / SI Majors | พยากรณ์สต็อกด้วย AI หรือ Microservices + Offline-First KDS | Streaming Transactions / Distributed Event-Driven DB | Mastery (M) |
Grocery POS ซับซ้อนกว่าจุดขายทั่วไปอย่างไร?
ร้านขายของชำและซูเปอร์มินิมาร์ทมีสินค้าหลายพัน SKU ที่ต้องสแกนบาร์โค้ดอย่างรวดเร็ว จัดการสินค้าชั่งน้ำหนัก สินค้ามีวันหมดอายุ และมีแคชเชียร์มากกว่า 1 ช่องทางตัดสต็อกจากคลังเดียวกันในเวลาเดียวกัน
4 โจทย์เฉพาะทางของร้านขายของชำ
ต้องค้นหา EAN-13 / UPC ได้ภายใน < 50ms ต่อการสแกน 1 ครั้ง
จำนวน (quantity) ต้องรองรับทศนิยม (เช่น 0.750 กก.) ไม่ใช่แค่จำนวนเต็ม
แยกตาราง Product ออกจาก Inventory Stock เพื่อรองรับ FIFO/FEFO
แคชเชียร์ 2 จุดขายสินค้าชิ้นสุดท้ายพร้อมกันต้องไม่เกิดสต็อกติดลบ
คลิกเลือกสถานการณ์เพื่อดู Primary & Alternative Courses
สถาปัตยกรรมระบบ Grocery POS แบบ 4 ชั้น (คลิกสำรวจแต่ละส่วน)
แผนภาพที่ดีต้องแสดงขอบเขตความรับผิดชอบและทิศทางของ Dependency อย่างชัดเจน ตามหลัก Dependency Inversion (DIP) ชั้น Domain Policy ต้องไม่ผูกติดกับ SQL หรือฮาร์ดแวร์เครื่องสแกนโดยตรง คลิกที่กล่องในแผนภาพเพื่อดูรายละเอียด
เลือก Modular Monolith สำหรับทีม 4–5 คน (และหลีกเลี่ยง Cyclic Dependency)
ในโครงงานปี 2 ที่มีเวลาพัฒนา 3 Sprints การแยกเป็น Microservices ตั้งแต่วันแรกเพิ่มภาระ Network, Distributed Transaction และ DevOps เกินความจำเป็น สถาปัตยกรรมที่เหมาะสมที่สุดคือ Modular Monolith ที่แบ่งขอบเขตโมดูลชัดเจนพร้อมต่อยอดเป็น Microservices ในปี 3
เปรียบเทียบ 3 รูปแบบสถาปัตยกรรม
| เกณฑ์พิจารณา | Spaghetti Monolith | Modular Monolith | Microservices |
|---|---|---|---|
| ความเร็วในการพัฒนา (3 Sprints) | เร็วช่วงแรก ช้าช่วงท้าย | เร็วและคุมคุณภาพได้ | ช้า (Infra Overhead สูง) |
| ACID Transaction ข้าม Order–Stock | ทำได้ (1 DB) | ทำได้ทันที (1 DB) | ซับซ้อน (ต้องใช้ Saga) |
| การทำงานเป็นทีม 4–5 คน | Code ชนกันบ่อย | แยก Module / PR ชัดเจน | แยก Repo แต่ Debug ยาก |
| การขยายสู่ Cloud ปี 3 | รื้อใหม่ทั้งหมด | แยก Service ทีละโมดูลได้ | รองรับระดับองค์กร |
กติกาจัดวาง Dependency เป็น DAG
ตามหลักวิศวกรรมซอฟต์แวร์ (Robert C. Martin) กราฟการพึ่งพาระหว่าง Package ต้องเป็น Directed Acyclic Graph (DAG) ห้ามอ้างอิงวนกลับไปมา และใช้ Table Data Gateway (TDG) แยก Domain ออกจาก SQL:
↑ OrderGateway / ProductGateway / InventoryGateway (Interfaces)
แนวทางปฏิบัติของทีมปี 2
ห้ามเขียน SQL ใน Controller หรือ Route Handler โดยตรง ให้ผ่าน Gateway/Repository เพื่อให้เขียน Unit Test แบบ In-Memory ได้รวดเร็วไม่ต้องต่อ Database จริงทุกครั้งDatabase Normalization: แปลงตารางใบเสร็จ Grocery สู่ 3NF
ตารางเดียวที่เก็บทุกอย่างปนกันก่อให้เกิด Update Anomaly (แก้ชื่อสินค้าหรือเบอร์ผู้ขายต้องแก้ทุกบรรทัด) และ Delete Anomaly กดเลือกแต่ละขั้นเพื่อดูการแยกโครงสร้างข้อมูลทีละระดับ
Entity-Relationship Diagram (ERD) ของแพลตฟอร์ม Grocery POS
คลิกที่ Entity ใดก็ได้ในแผนภาพ ERD ด้านซ้ายเพื่อตรวจสอบ Primary Key, Foreign Key, Constraints, Indexes และชุดคำสั่ง SQL DDL สำหรับ PostgreSQL ด้านขวา
ตาราง orders
4 หลักการออกแบบข้อมูลสำคัญ: Snapshot, Concurrency, Idempotency, PDPA
ความเสี่ยงทางเทคนิคหลักที่ระบุในรายวิชา 1145 204 คือการตัดสต็อกพร้อมกันจากหลายจุดขายและการคุ้มครองข้อมูลส่วนบุคคล ทดลองจำลอง Race Condition ด้านล่างเพื่อดูความแตกต่างระหว่างโค้ดที่ปลอดภัยกับโค้ดที่มีช่องโหว่
1. Snapshot Data (ห้าม Join ราคาปัจจุบันในอดีต)
ตารางorder_items ต้องคัดลอก unit_price_snapshot และ tax_rate ณ เวลาขาย หากวันพรุ่งนี้ปรับราคานมสดขึ้น ยอดขายย้อนหลังและใบกำกับภาษีเดิมต้องไม่เพี้ยน
2. PDPA & PII Separation
เก็บข้อมูลระบุตัวตนลูกค้า (เบอร์โทร, ชื่อสมาชิก) แยกในตารางcustomers แบบ Hash/Encrypted และส่งออกเฉพาะ customer_id หรือข้อมูลแบบ Anonymous เมื่อนำไปวิเคราะห์ยอดขาย
จำลองแคชเชียร์ 2 เครื่องตัดสต็อกสินค้าชิ้นสุดท้ายพร้อมกัน (คงเหลือ 1 ชิ้น)
-- เลือกโหมดด้านบนเพื่อดูลำดับคำสั่ง SQL และผลลัพธ์ของ Transaction
RESTful API Contracts: สัญญาระหว่าง Frontend POS และ Backend
ทีมพัฒนา 4–5 คนสามารถแยกงาน Frontend และ Backend ทำคู่ขนานใน Sprint 2 ได้ก็ต่อเมื่อตกลง OpenAPI Contract ล่วงหน้าให้ชัดทั้ง Path, HTTP Status Code, Idempotency Header และโครงสร้าง Error Response มาตรฐาน
ตาราง Core Endpoints ของแพลตฟอร์ม Grocery POS (/api/v1)
| Method & Path | หน้าที่ทางธุรกิจ (Use Case) | Headers / Constraints | Status Codes |
|---|---|---|---|
GET /products/barcode/{upc} |
สแกนบาร์โค้ดเพื่อดึงชื่อ ราคา หน่วย และสต็อกคงเหลือ | Authorization: Bearer JWT |
200 404 |
POST /orders |
สร้างคำสั่งซื้อและตัดสต็อกแบบ Atomic Transaction | Idempotency-Key: UUID |
201 409 Conflict 422 |
POST /orders/{id}/payments |
บันทึกการรับชำระเงิน (เงินสด / PromptPay / บัตร) | ตรวจสอบยอดชำระ ≥ ยอดสุทธิ | 200 409 |
PATCH /inventory/{productId}/adjust |
ปรับสต็อกรับเข้า / สินค้าชำรุด (เฉพาะ Manager) | Role: MANAGER + Audit Reason |
200 403 |
paths:
/api/v1/orders:
post:
summary: Create POS order & deduct stock atomically
parameters:
- name: Idempotency-Key
in: header
required: true
schema: { type: string, format: uuid }
responses:
'201': { description: Order created & stock reserved }
'409': { description: Insufficient stock or duplicate key }
'422': { description: Validation error (qty <= 0) }
{
"error": {
"code": "INSUFFICIENT_STOCK",
"message": "สินค้า น้ำดื่ม 1.5L เหลือในคลังไม่เพียงพอ (เหลือ 1 ชิ้น)",
"details": [
{ "product_id": 104, "requested": 2, "available": 1 }
],
"trace_id": "req-9f82a10c"
}
}
ห้องทดลองจำลอง API Contract (Request → Response → DB State)
เลือกสถานการณ์ทดสอบเพื่อดูว่า Payload ที่ส่งเข้า Backend ถูกตรวจสอบ Validation อย่างไร ส่งคืน HTTP Status Code ใด และเปลี่ยนสถานะแถวข้อมูลในฐานข้อมูล 3NF อย่างไรบ้าง
ผลกระทบต่อ Relational Database
กดปุ่ม "ส่งคำขอจำลอง" เพื่อตรวจสอบคำสั่ง SQL Transaction และแถวข้อมูลที่เปลี่ยนแปลงChecklist ส่งมอบงานสัปดาห์ที่ 5 และแบบทดสอบทบทวนความเข้าใจ
ทำเครื่องหมายรายการที่ทีมของคุณออกแบบเสร็จแล้วสำหรับ Sprint 1 (ความคืบหน้าจะถูกบันทึกไว้ให้อัตโนมัติ) และทดสอบความเข้าใจ 3 ข้อท้ายคาบเรียน