การออกแบบ 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 ใด เพราะเหตุใด มีทางเลือกอะไร และยอมรับผลกระทบใดจากการตัดสินใจนั้น