- ภาพรวม 20 Architecture Patterns
- Circuit Breaker ตัดการเรียก Service Resilienceที่กำลังล้มเหลว
- Layered Architecture
- Client-Server
- Microservices
- Event-Driven Architecture
- Pipe-and-Filter
- CQRS
- Event Sourcing
- Saga Pattern
- API Gateway
- Hexagonal Architecture
- Serverless
- Space-Based Architecture
- Service Mesh
- Peer-to-Peer
- Broker Pattern
- Master-Worker
- Sidecar Pattern
- Backend for Frontend (BFF)
- Strangler Fig Pattern
- Circuit Breaker
- Pattern เหล่านี้ใช้ร่วมกันอย่างไร?
- Workshop: ออกแบบ E-Commerce Architecture
- Checklist ก่อนเลือก Architecture Pattern
- สิ่งที่ควรหลีกเลี่ยง: Architecture Pattern Stacking
- สรุป
การออกแบบ Software Architecture ไม่ได้หมายถึงการเลือกเทคโนโลยีที่ใหม่ที่สุด แต่คือการกำหนด โครงสร้าง ความรับผิดชอบ การสื่อสาร และขอบเขตของส่วนประกอบในระบบ ให้เหมาะกับปัญหาที่ต้องแก้
Architecture Pattern เป็นแนวทางที่ใช้ซ้ำได้สำหรับปัญหาที่เกิดขึ้นบ่อยในการออกแบบระบบ อย่างไรก็ตาม Pattern แต่ละแบบมี trade-off ของตัวเอง และหลาย Pattern สามารถอยู่ร่วมกันในระบบเดียวได้
ตัวอย่างเช่น ระบบ Microservices หนึ่งระบบอาจใช้ทั้ง:
Microservices
+
API Gateway
+
Event-Driven Architecture
+
Saga Pattern
+
Service Mesh
+
Circuit Breaker
ดังนั้นคำถามสำคัญจึงไม่ใช่เพียงว่า "Pattern ไหนดีที่สุด?" แต่ควรเป็น "ปัญหาของระบบคืออะไร และ Pattern ใดช่วยแก้ปัญหานั้นโดยมีต้นทุนที่ยอมรับได้?"
#ภาพรวม 20 Architecture Patterns
Pattern แนวคิดหลัก เหมาะกับ
Layered Architecture แบ่งระบบเป็นชั้น Business Application, CRUD
Client-Server Client ขอใช้บริการจาก Web, Mobile, API Server
Microservices แยกระบบเป็นบริการอิสระ ระบบขนาดใหญ่
Event-Driven สื่อสารด้วย Event Async Workflow
Pipe-and-Filter ประมวลผลเป็นลำดับขั้น ETL, Data Pipeline
CQRS แยก Read/Write Model Read-heavy/Complex Domain
Event Sourcing เก็บการเปลี่ยนแปลงเป็น Event Audit, History
Saga Transaction ข้ามหลาย Microservices Service
API Gateway จุดเข้า API กลาง Microservices API
Hexagonal แยก Domain จาก Maintainable Domain Infrastructure System
Serverless ทำงานตาม Event โดยไม่ดูแล Cloud Workload Server โดยตรง
Space-Based กระจาย Processing/Data ใน High Throughput Memory
Service Mesh จัดการ Service-to-Service Large Microservices Traffic
Peer-to-Peer Node Distributed Network สื่อสารกันโดยไม่มีศูนย์กลางหลัก
Broker Broker เป็นตัวกลาง Messaging/RPC
Master-Worker กระจายงานไป Worker Parallel Processing
Sidecar Helper Process ข้าง Container/Kubernetes Application
Backend for Frontend Backend เฉพาะ Frontend Multi-client System
Strangler Fig ค่อย ๆ แทน Legacy System Modernization
#Circuit Breaker ตัดการเรียก Service Resilience ที่กำลังล้มเหลว
#Layered Architecture
Layered Architecture เป็นรูปแบบที่พบได้บ่อยมาก โดยแบ่งระบบออกเป็นชั้นตามความรับผิดชอบ เช่น
Presentation / UI
↓
Business Logic
↓
Data Access
↓
Database
แต่ละ Layer ควรรับผิดชอบงานของตัวเอง เช่น UI จัดการการแสดงผล Business Layer จัดการกฎทางธุรกิจ และ Data Access Layer ติดต่อฐานข้อมูล
#เหมาะกับ
- ระบบ CRUD
- ระบบงานองค์กร
- ระบบที่ Business Logic ไม่ซับซ้อนมาก
- ทีมที่ต้องการโครงสร้างเข้าใจง่าย
#Trade-offs
เมื่อระบบมีขนาดใหญ่มาก Layer อาจผูกกันแน่น การเปลี่ยนแปลงหนึ่งส่วนอาจกระทบหลายชั้น และ request บางชนิดอาจต้องผ่าน Layer จำนวนมากโดยไม่จำเป็น
#Client-Server
Client-Server แยกผู้ร้องขอบริการออกจากระบบที่ประมวลผลคำขอ
Client
↓
Request
↓
Server
↓
Response
↓
Client
ตัวอย่างที่คุ้นเคยคือ Browser เรียก REST API บน Server หรือ Mobile Application ติดต่อ Backend API
#จุดเด่น
Server สามารถควบคุม Business Rules, Authentication และ Data Access จากส่วนกลางได้
#สิ่งที่ต้องระวัง
หากมี Server เพียงตัวเดียว Server อาจกลายเป็น bottleneck หรือ single point of failure จึงอาจต้องใช้ load balancing, replication และ horizontal scaling
#Microservices
Microservices Architecture แบ่งระบบขนาดใหญ่ออกเป็น Service ขนาดเล็กที่รับผิดชอบความสามารถทางธุรกิจเฉพาะด้าน
┌─ Catalog Service
Client → API ───┼─ Order Service
├─ Payment Service
└─ Inventory Service
แต่ละ Service สามารถพัฒนา Deploy และ Scale แยกจากกันได้
#เหมาะกับ
- ระบบขนาดใหญ่
- หลายทีมพัฒนาพร้อมกัน
- ต้องการ Independent Deployment
- Service แต่ละส่วนมี Scaling Requirement ต่างกัน
#Trade-offs
Microservices เปลี่ยนความซับซ้อนจากภายใน Application ไปเป็น Distributed-System Complexity เช่น network failure, observability, distributed transaction, service discovery และ data consistency
ดังนั้นระบบขนาดเล็กไม่จำเป็นต้องเริ่มต้นด้วย Microservices เสมอไป
#Event-Driven Architecture
Event-Driven Architecture ใช้ Event เป็นกลไกสำคัญในการสื่อสาร
Producer
↓
Event Broker
┌─┼─────────┐
↓ ↓ ↓
A B C
ตัวอย่างเช่น เมื่อสร้าง Order สำเร็จ:
OrderCreated
↓
┌───┼───────────┐
↓ ↓ ↓
Stock Payment Notification
Producer ไม่จำเป็นต้องเรียก Consumer ทุกตัวโดยตรง ทำให้เกิด loose coupling
#ต้องออกแบบเพิ่มเติม
- Event Schema
- Retry
- Dead Letter Queue
- Ordering
- Idempotency
- Duplicate Event Handling
- Observability
#Pipe-and-Filter
Pipe-and-Filter แบ่งกระบวนการประมวลผลเป็นหลายขั้น แต่ละ Filter รับข้อมูล แปลงข้อมูล และส่งต่อ
Input
↓
Validate
↓
Clean
↓
Transform
↓
Output
เหมาะอย่างยิ่งกับ ETL, Compiler, Log Processing, Image Processing และ Data Pipeline
ข้อดีคือแต่ละ Filter สามารถทดสอบและนำกลับมาใช้ใหม่ได้ แต่ควรกำหนด Data Contract ระหว่างแต่ละขั้นให้ชัดเจน
#CQRS
CQRS ย่อมาจาก Command Query Responsibility Segregation
แนวคิดคือแยกการเปลี่ยนข้อมูลออกจากการอ่านข้อมูล
Command
↓
Write Model
↓
Write Store
Query
↓
Read Model
↓
Read Store
Read Model สามารถออกแบบเพื่อการ Query โดยเฉพาะ ขณะที่ Write Model เน้น Business Rules และ Data Integrity
#CQRS เหมาะเมื่อ
Read และ Write มีรูปแบบหรือภาระงานแตกต่างกันมาก หรือ Domain มีความซับซ้อนสูง
สำหรับ CRUD Application ทั่วไป CQRS อาจเพิ่ม complexity โดยไม่ได้ให้ประโยชน์เพียงพอ
#Event Sourcing
แทนที่จะเก็บเฉพาะสถานะล่าสุด Event Sourcing เก็บ เหตุการณ์ทุกครั้งที่ทำให้ State เปลี่ยน
AccountCreated
DepositMade
MoneyWithdrawn
MoneyWithdrawn
จาก Event เหล่านี้สามารถ Replay เพื่อสร้าง Current State ได้
Events → Replay → Current State
#ข้อดี
- มี Audit Trail
- Replay State ได้
- วิเคราะห์ประวัติย้อนหลังได้
- ทำงานร่วมกับ CQRS ได้ดี
#ความท้าทาย
ต้องจัดการ Event Schema Evolution, Snapshot, Event Volume และการเปลี่ยนแปลงข้อมูลที่ถูกบันทึกไปแล้ว
#Saga Pattern
เมื่อ Microservices หลายตัวมี Database ของตัวเอง การใช้ Transaction เดียวครอบคลุมทุก Service ทำได้ยาก
Saga แบ่ง Transaction ใหญ่เป็น Local Transaction หลายขั้น
Create Order
↓
Reserve Stock
↓
Process Payment
↓
Confirm Order
หาก Payment ล้มเหลว อาจเกิด Compensation เช่น
Payment Failed
↓
Release Stock
↓
Cancel Order
Saga มีแนวทางสำคัญ เช่น Choreography และ Orchestration
สิ่งสำคัญคือ Compensation ไม่ได้มีความหมายเหมือน Database Rollback เสมอไป จึงต้องออกแบบ Business Compensation อย่างชัดเจน
#API Gateway
API Gateway ทำหน้าที่เป็นจุดเข้าเดียวของระบบ Backend
Clients
↓
API Gateway
┌─┼──────────┐
↓ ↓ ↓
A B C
Gateway สามารถจัดการงาน เช่น:
- Routing
- Authentication
- Authorization
- Rate Limiting
- TLS Termination
- Request Transformation
- API Aggregation
อย่างไรก็ตามไม่ควรย้าย Business Logic จำนวนมากไปไว้ที่ Gateway เพราะอาจทำให้ Gateway กลายเป็น monolith ตัวใหม่
#Hexagonal Architecture
Hexagonal Architecture หรือ Ports and Adapters Architecture มุ่งแยก Business Domain ออกจาก Infrastructure
External Adapter
↓
Port
↓
Core Domain
↓
Port
↓
Infrastructure Adapter
ตัวอย่างเช่น Domain อาจรู้จักเพียง OrderRepository interface
โดยไม่จำเป็นต้องรู้ว่าข้อมูลจริงอยู่ใน PostgreSQL, MongoDB หรือ In-memory Database
#ผลลัพธ์
Core Business Logic สามารถทดสอบได้ง่าย และ Infrastructure สามารถเปลี่ยนได้โดยลดผลกระทบต่อ Domain
#Serverless
Serverless ให้ Developer เขียน Function หรือ Workload แล้วให้ Cloud Platform ดูแล Infrastructure และ Scaling
Event
↓
Function
↓
Managed Service
ตัวอย่าง:
Upload Image
↓
Cloud Function
↓
Resize Image
↓
Object Storage
#เหมาะกับ
- Event Processing
- Scheduled Job
- Webhook
- API บางประเภท
- Workload ที่เกิดเป็นช่วง
#Trade-offs
ต้องพิจารณา cold start, execution limit, observability, vendor constraints และ cost model
#Space-Based Architecture
Space-Based Architecture ลดการพึ่งพาฐานข้อมูลกลาง โดยกระจาย Processing และข้อมูลไปยังหลาย Node และมักใช้ Distributed In-Memory Data Grid
Processing Node
↕
In-Memory Grid
↕
Processing Node
เหมาะกับระบบที่ต้องการ throughput สูงมากและรับ traffic spike เช่น reservation, trading หรือ flash-sale
แต่มีความซับซ้อนด้าน partitioning, consistency, replication และ recovery สูง
#Service Mesh
Service Mesh จัดการ service-to-service communication ในระบบ Microservices
Service A
↓
Proxy
↕
Proxy
↓
Service B
ความสามารถที่พบบ่อย ได้แก่
- mTLS
- Traffic Policy
- Retry
- Telemetry
- Load Balancing
- Traffic Splitting
Service Mesh มีประโยชน์เมื่อจำนวน Service มากและต้องการ Policy ที่สม่ำเสมอ แต่สำหรับระบบขนาดเล็กอาจเป็น operational overhead ที่ไม่จำเป็น
#Peer-to-Peer
Peer-to-Peer หรือ P2P ให้ Node สื่อสารและแบ่งทรัพยากรกันโดยไม่มี Server กลางเป็นศูนย์กลางหลัก
Node ↔ Node
↕ ↕
Node ↔ Node
แต่ละ Node สามารถมีบทบาทเป็นทั้ง Client และ Server
เหมาะกับ decentralized network, distributed file sharing และระบบที่ต้องการลดการพึ่งพาจุดศูนย์กลาง
#Broker Pattern
Broker เป็นตัวกลางระหว่าง Client กับ Provider หรือ Consumer
Client
↓
Broker
↓
Provider
Client ไม่จำเป็นต้องทราบตำแหน่งหรือรายละเอียดของ Provider โดยตรง
แนวคิดนี้พบได้ใน Messaging Middleware, RPC Framework และ Distributed Integration
#Master-Worker
Master หรือ Coordinator แบ่งงานเป็นส่วนย่อยแล้วส่งให้ Worker หลายตัวทำงานพร้อมกัน
┌→ Worker 1
Master ──────┼→ Worker 2
└→ Worker 3
จากนั้นอาจรวบรวมผลกลับมาที่ Coordinator
เหมาะกับ Batch Processing, Parallel Computation, Image Processing และ Job Queue
ต้องออกแบบเรื่อง worker failure, retry, task duplication และ idempotency
#Sidecar Pattern
Sidecar คือ Component ที่รันข้าง Application โดยมี lifecycle ใกล้เคียงกัน
Pod / Host
┌───────────────────────┐
│ Application | Sidecar │
└───────────────────────┘
Sidecar สามารถรับผิดชอบ:
- Logging
- Proxy
- Security
- Secret Management
- Telemetry
- Networking
แนวคิดนี้พบมากใน Container และ Kubernetes
#Backend for Frontend (BFF)
BFF สร้าง Backend แยกสำหรับ Frontend แต่ละประเภท
Mobile ──→ Mobile BFF ──┐
Web ─────→ Web BFF ─────┼→ Services
Desktop ─→ Desktop BFF ─┘
Mobile อาจต้องการ payload ขนาดเล็ก ขณะที่ Web Dashboard อาจต้องการข้อมูลจำนวนมากจากหลาย Service
BFF ช่วยลด over-fetching และลด aggregation logic ที่ Frontend แต่ต้องระวัง Business Logic ซ้ำใน BFF หลายตัว
#Strangler Fig Pattern
Strangler Fig ใช้สำหรับ Modernize Legacy System แบบค่อยเป็นค่อยไป
แทนที่จะ Rewrite ระบบทั้งหมดพร้อมกัน:
Legacy System
↓
ย้าย Module A → New Service
↓
ย้าย Module B → New Service
↓
ย้าย Module C → New Service
Gateway หรือ Router สามารถตัดสินใจว่า Request ใดไป Legacy และ Request ใดไป New System
ข้อดีสำคัญคือช่วยลดความเสี่ยงของ Big-Bang Rewrite
#Circuit Breaker
Circuit Breaker ป้องกันไม่ให้ Application เรียก Downstream Service ที่กำลังล้มเหลวซ้ำ ๆ
โดยทั่วไปมี State สำคัญ:
Closed
↓
failure threshold
↓
Open
↓
wait / probe
↓
Half-Open
↓
success → Closed
failure → Open
เมื่อ Circuit เปิด ระบบสามารถ fail fast หรือใช้ fallback แทนการรอ timeout ทุก Request
Circuit Breaker ควรพิจารณาร่วมกับ:
- Timeout
- Retry
- Backoff
- Fallback
- Bulkhead
- Monitoring
#Pattern เหล่านี้ใช้ร่วมกันอย่างไร?
ระบบจริงมักประกอบด้วยหลาย Pattern
#ตัวอย่าง: Modern Microservices
┌───────────────┐
Web / Mobile ─────────→│ API Gateway │
└───────┬───────┘
│
┌──────────────┼──────────────┐
↓ ↓ ↓
Order Service Payment Service Inventory Service
│ │ │
└──────── Event Broker ───────┘
Service Mesh / Sidecar
Circuit Breaker / Retry
Observability
ใน Architecture นี้:
Microservices ใช้แยก Business Capability
API Gateway เป็น Entry Point
Event-Driven ลด Coupling ระหว่าง Service
Saga ดูแล Business Transaction ข้าม Service
Circuit Breaker ป้องกัน Cascading Failure
Service Mesh จัดการ Service-to-Service Communication
Sidecar ช่วยแยก Infrastructure Concern ออกจาก Application
#Workshop: ออกแบบ E-Commerce Architecture
สมมติว่าต้องออกแบบระบบ E-Commerce ประกอบด้วย:
Catalog
Order
Inventory
Payment
Shipping
Notification
เริ่มต้นจาก Client:
Web / Mobile
↓
API Gateway
↓
Order Service
เมื่อสร้าง Order:
Order Service
↓
OrderCreated Event
↓
Event Broker
┌────┼─────────────┐
↓ ↓ ↓
Stock Payment Notification
สำหรับ Transaction:
Create Order
↓
Reserve Inventory
↓
Process Payment
↓
Confirm Order
หาก Payment ล้มเหลว:
Payment Failed
↓
Release Inventory
↓
Cancel Order
นี่คือการนำ Saga Pattern มาใช้กับ Microservices
ส่วนการเรียก Payment Provider ภายนอกสามารถครอบด้วย Circuit Breaker:
Payment Service
↓
Circuit Breaker
↓
External Payment API
#Checklist ก่อนเลือก Architecture Pattern
ก่อนเลือก Pattern ควรถามคำถามต่อไปนี้
- ระบบต้องรองรับผู้ใช้และ Traffic มากเพียงใด?
- ต้องการ Availability ระดับใด?
- ยอมรับ Eventual Consistency ได้หรือไม่?
- Business Domain ซับซ้อนเพียงใด?
- ต้องการ Independent Deployment หรือไม่?
- มีหลายทีมพัฒนาพร้อมกันหรือไม่?
- ต้องการ Audit History หรือไม่?
- ระบบมี Distributed Transaction หรือไม่?
- Failure ของ Service หนึ่งสามารถกระทบ Service อื่นหรือไม่?
- ทีมมีความพร้อมด้าน CI/CD, Container, Kubernetes และ Observability เพียงใด?
#สิ่งที่ควรหลีกเลี่ยง: Architecture Pattern Stacking
ข้อผิดพลาดที่พบได้คือการนำ Pattern จำนวนมากมาใช้เพียงเพราะเป็นเทคโนโลยีที่ได้รับความนิยม
ตัวอย่าง:
Microservices
+ Kubernetes
+ Service Mesh
+ CQRS
+ Event Sourcing
+ Saga
+ Kafka
Architecture ดังกล่าวอาจเหมาะกับบางระบบ แต่ไม่ใช่ค่าเริ่มต้นสำหรับทุกโครงการ
Pattern ทุกตัวเพิ่มทั้ง Capability และ Complexity
หลักการที่สำคัญคือ:
ใช้ Pattern เมื่อปัญหาที่ Pattern นั้นแก้ไขมีอยู่จริง และประโยชน์มากกว่าต้นทุนด้านความซับซ้อน
#สรุป
Architecture Pattern เป็น vocabulary สำคัญของ Software Architect และ Software Engineer เพราะช่วยให้ทีมสามารถอธิบายโครงสร้างและ trade-off ของระบบด้วยภาษาที่เข้าใจร่วมกัน
ระบบทั่วไปอาจเริ่มจาก:
Layered Architecture
หรือ
Hexagonal Architecture
เมื่อระบบต้องรองรับหลาย Client อาจเพิ่ม:
API Gateway
หรือ
Backend for Frontend
เมื่อระบบขยายเป็น Distributed System:
Microservices
+ Event-Driven
+ Saga
+ Circuit Breaker
และเมื่อจำนวน Service เพิ่มขึ้นมาก อาจพิจารณา:
Service Mesh
+ Sidecar
+ Observability
หัวใจของการออกแบบ Architecture จึงไม่ใช่ "ใช้ Pattern ให้มากที่สุด" แต่คือการเลือก Pattern ที่แก้ปัญหาจริงของระบบ โดยยอมรับ Trade-off ได้อย่างมีเหตุผล
#แนวทางศึกษาต่อ
สำหรับการฝึกปฏิบัติ แนะนำให้ทดลองออกแบบระบบเดียวกันหลายรูปแบบ เช่น Monolith แบบ Layered, Modular/Hexagonal และ Microservices จากนั้นเปรียบเทียบในมิติของ deployment, scalability, coupling, consistency, observability และ operational complexity
การทำ Architecture Decision Record (ADR) ควบคู่ไปด้วยจะช่วยให้ทีมบันทึกว่าเลือก Pattern ใด เพราะเหตุใด มีทางเลือกอะไร และยอมรับผลกระทบใดจากการตัดสินใจนั้น