The Pattern Language
ถึงตอนนี้คุณตัดสินใจได้แล้วว่า ควรหรือไม่ควร ใช้ microservices ถ้าคำตอบคือใช่ สิ่งที่รออยู่คือรายการ pattern ยาวเหยียด ทั้งกลยุทธ์ decomposition, saga, gateway, circuit breaker, tracing และอีกมาก จนน่าเข้าใจผิดว่าเป็นเมนูลูกเล่นที่หยิบใช้แยกกันได้ แต่ความจริงไม่ใช่ ทุก pattern มีอยู่เพราะการตัดสินใจก่อนหน้าสร้างปัญหาที่ pattern นั้นเข้ามาแก้ มองแบบนี้แล้ว pattern ทั้งหมดจะรวมกันเป็น ภาษา ที่เชื่อมโยงกัน และการเข้าใจความเชื่อมโยงนั้นมีค่ากว่าการท่องรายการชื่อ pattern มาก
คุณจะทำความเข้าใจ pattern หลายสิบตัวได้อย่างไรโดยไม่จมไปเสียก่อน สิ่งที่ต้องมีคือแผนที่ ที่ช่วยให้เห็นว่าทำไม decomposition ถึงคุ้มค่าตั้งแต่แรก และการตัดสินใจครั้งเดียวนั้นกระเพื่อมออกไปเป็นตระกูลปัญหาที่คอร์สที่เหลือพูดถึงได้อย่างไร
เราต้องการสองสิ่ง: โมเดลสำหรับ ทำไมคุณถึงแยก ระบบ และโมเดลสำหรับ การแยกสร้างอะไรขึ้นมา ที่ pattern ทั้งหลายต้องแก้ตามมา
วิธีแก้
หัวข้อที่มีชื่อว่า “วิธีแก้”ทำไมคุณถึงแยก: scale cube
หัวข้อที่มีชื่อว่า “ทำไมคุณถึงแยก: scale cube”วิธีที่มีประโยชน์ในการคิดเรื่อง scaling คือคิดไปตามแกนอิสระสามแกน ซึ่งมักวาดเป็นลูกบาศก์ (cube):
- แกน X — horizontal duplication รันสำเนาแอปพลิเคชันที่เหมือนกันหลายชุดหลัง load balancer นี่คือการ scale แบบคลาสสิกที่ง่ายที่สุด และใช้กับ monolith ได้ด้วย ช่วย scale throughput แต่ไม่ช่วย scale ความซับซ้อน เพราะทุกสำเนายังแบกทั้งระบบไว้เหมือนเดิม
- แกน Y — functional decomposition แยกแอปพลิเคชันตาม สิ่งที่ระบบทำ ออกเป็น service ตาม business capability นี่คือแกนที่นิยามความเป็น microservices และช่วย scale การพัฒนา เพราะทีมกับ component วิวัฒน์แยกกันได้ ไม่ใช่แค่ scale traffic
- แกน Z — data partitioning แยกตาม ข้อมูลชุดไหน ที่ request ไปแตะ แล้วส่งแต่ละ request ไปยัง partition หรือ shard ที่ถือข้อมูลนั้น code เหมือนกันทุกที่ ต่างกันแค่แต่ละ instance ดูแลข้อมูลคนละส่วน
แกน Y คือแกนที่คอร์สนี้พูดถึงเป็นหลัก เพราะ functional decomposition คือสิ่งที่เปลี่ยนแอปพลิเคชันหนึ่งให้กลายเป็น service จำนวนมาก — และการเลือกครั้งเดียวนั้นคือต้นตอของกลุ่มปัญหาอื่น ๆ ทั้งหมดด้านล่าง
flowchart LR Mono[Single Application] --> X[X-axis<br/>Run many identical copies] Mono --> Y[Y-axis<br/>Split by business capability] Mono --> Z[Z-axis<br/>Partition by data] Y --> Decomp[Functional decomposition<br/>= microservices]
การแยกสร้างอะไรขึ้นมา: กลุ่มของ pattern
หัวข้อที่มีชื่อว่า “การแยกสร้างอะไรขึ้นมา: กลุ่มของ pattern”ทันทีที่คุณ decompose ตามแกน Y โซ่ของปัญหาใหม่ก็โผล่ตามมา และปัญหาแต่ละกลุ่มมีตระกูล pattern ของตัวเองคอยแก้ ทั้งหมดเรียงต่อกันมาตามลำดับที่เป็นธรรมชาติ:
flowchart TB Decomp[Decomposition<br/>split into services] --> Data[Data Management<br/>consistency without a shared DB] Data --> Msg[Transactional Messaging<br/>publish events reliably] Msg --> Comm[Communication<br/>how services talk] Comm --> Rel[Reliability<br/>survive partial failure] Rel --> Obs[Observability<br/>see across services] Obs --> Deploy[Deployment and Cross-cutting<br/>ship, run, secure]
อ่านโซ่นี้เป็นเรื่องราว:
- Decomposition แยกระบบออกเป็น service — แต่ตอนนี้ service เหล่านั้นต้องรักษาข้อมูลให้สอดคล้องกัน
- Data Management ฟื้นความสอดคล้องและความสามารถในการ query โดยไม่ต้องมีฐานข้อมูลที่ใช้ร่วมกัน — แต่ความสอดคล้องที่เชื่อถือได้ขึ้นอยู่กับการเผยแพร่ event ในฐานะส่วนหนึ่งของ transaction
- Transactional Messaging ทำให้การเผยแพร่ event นั้นเชื่อถือได้ — แต่ service ก็ยังต้องคุยกันอยู่ดี
- Communication กำหนดว่า service คุยกันอย่างไร ทั้งแบบ synchronous และ asynchronous ผ่าน API และ gateway แต่เครือข่ายที่ใช้คุยกันนั้นล้มเหลวได้แบบเป็นบางส่วนและคาดไม่ถึง
- Reliability ทำให้ระบบยังทำงานต่อได้ผ่าน partial failure เหล่านั้น — แต่คุณแก้สิ่งที่คุณมองไม่เห็นข้ามกองทัพ service ไม่ได้
- Observability ทำให้คุณมองเห็นภาพรวมข้ามทุก service ได้ และสุดท้ายทั้งหมดก็ต้อง ship รัน และรักษาความปลอดภัยบน production
- Deployment and Cross-cutting จัดการช่วงสุดท้ายนั้น
ทุกลูกศรคือปัญหาที่ถูกส่งต่อไปข้างหน้า และนั่นคือเหตุผลที่สิ่งนี้เป็น ภาษา ไม่ใช่แค่รายการ คุณเข้าใจ saga ได้ไม่ครบถ้าไม่รู้จัก data boundary ที่ทำให้ต้องมี saga ตั้งแต่แรก และคุณรัน saga อย่างปลอดภัยไม่ได้ถ้าไม่มี messaging ที่เชื่อถือได้รองรับอยู่ข้างใต้ pattern ทั้งหลายอ้างอิงและพึ่งพากันเป็นทอด ๆ
ผลลัพธ์ที่ตามมา
หัวข้อที่มีชื่อว่า “ผลลัพธ์ที่ตามมา”พอมีแผนที่นี้ คุณก็วางตำแหน่งของ pattern แต่ละตัวได้ เจอ pattern ใหม่เมื่อไร ให้ถามสองข้อว่าอยู่ในกลุ่มไหน และการตัดสินใจก่อนหน้าข้อใดที่สร้างปัญหาซึ่ง pattern นี้เข้ามาแก้ นิสัยเล็ก ๆ ข้อนี้เปลี่ยนแคตตาล็อกที่กระจัดกระจายให้กลายเป็นโครงสร้างที่เดินตามได้ แถมยังบอกด้วยว่าควรเรียนอะไรต่อ เพราะแต่ละกลุ่มต่อยอดกันไปตามลำดับ
จุดเริ่มต้นที่เป็นธรรมชาติในการนำสิ่งนี้ไปใช้คือปัญหาแรกที่ decomposition สร้างขึ้น: การรักษาข้อมูลให้สอดคล้องเมื่อทุก service เป็นเจ้าของ store ของตัวเอง
pattern ที่เกี่ยวข้อง
หัวข้อที่มีชื่อว่า “pattern ที่เกี่ยวข้อง”- What Is Microservices Architecture? — รากฐานที่ทั้งภาษาตั้งอยู่บน
- When to Use Microservices — การตัดสินใจที่จะ decompose ซึ่งเริ่มต้นโซ่นี้ให้เคลื่อนไหว
- Data Management — กลุ่มปัญหาแรกที่ decomposition สร้างขึ้น และเป็นโมดูลถัดไปที่ต้องอ่าน
| ข้อดี | ข้อแลกเปลี่ยน |
|---|---|
| pattern ให้ vocabulary ร่วมกันในทีม — คุยกันเข้าใจเร็วขึ้น | pattern เป็น template ไม่ใช่ recipe — ต้อง adapt ตาม context |
| แต่ละ pattern documented ว่า context ไหนเหมาะ | การรู้ pattern ไม่ได้แปลว่า implement ถูก |
| เรียนจาก collective experience ของอุตสาหกรรม | over-engineering — ใช้ pattern ที่ยังไม่จำเป็น |
| pattern language ช่วย see the big picture ว่า pattern สัมพันธ์กันอย่างไร | pattern อาจ outdated สำหรับ technology stack ปัจจุบัน |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”Pattern Shopping — เลือก pattern เพราะชื่อดังหรือ hype ไม่ใช่เพราะ context เหมาะ
อาการ:
- ใช้ CQRS เพราะอ่านบทความ ไม่ใช่เพราะมีปัญหา read/write asymmetry
- เพิ่ม complexity โดยไม่มี corresponding benefit
- เริ่มจาก problem ก่อนเสมอ — pattern เป็นคำตอบไม่ใช่คำถาม
ใช้ Pattern โดยไม่เข้าใจ Trade-offs — implement pattern ตาม tutorial โดยไม่รู้ว่าจะเสียอะไร
อาการ:
- adopt Saga โดยไม่รู้ว่า compensating transaction คืออะไร
- adopt Event Sourcing โดยไม่รู้ว่า query current state ยากขึ้น
💡 ตัวอย่างจากของจริง
Chris Richardson (microservices.io):
- สร้าง microservices pattern language catalog
- patterns สัมพันธ์กัน — แก้ปัญหาหนึ่งนำไปสู่ปัญหาถัดไปที่ต้องใช้ pattern ใหม่
Martin Fowler & Sam Newman:
- “Microservices” article (2014) นิยาม architectural style
- “Building Microservices” book เป็น reference สำคัญของอุตสาหกรรม