The Monolith Is Rarely the Enemy (Monolith แทบไม่เคยเป็นศัตรู)

แม้ว่า ผมได้กล่าวไว้แล้วตั้งแต่ต้นเล่มว่าสถาปัตยกรรมแบบ monolithic รูปแบบหนึ่งสามารถเป็นทางเลือกที่ใช้ได้อย่างสมบูรณ์ แต่ก็ควรย้ำอีกครั้งว่าสถาปัตยกรรม monolithic นั้นไม่ได้ แย่ โดยธรรมชาติ และไม่ควรถูกมองว่าเป็นศัตรู อย่ามุ่งเน้นไปที่ "การไม่มี monolith" แต่มุ่งเน้นไปที่ประโยชน์ที่คุณคาดหวังว่าการเปลี่ยนแปลงสถาปัตยกรรมของคุณจะนำมาให้แทน

เป็นเรื่องปกติที่สถาปัตยกรรม monolithic ที่มีอยู่จะยังคงอยู่หลังจากการเปลี่ยนไปสู่ microservices แม้จะมักมีขนาดเล็กลงก็ตาม ยกตัวอย่างเช่น การเปลี่ยนแปลงเพื่อปรับปรุงความสามารถของแอปพลิเคชันในการรับ load ที่มากขึ้นอาจพอใจได้ด้วยการเอาฟังก์ชันการทำงาน 10% ที่กำลังเป็น bottleneck อยู่ในปัจจุบันออกไป โดยเหลืออีก 90% ไว้ในระบบ monolithic

หลายคนพบว่าความจริงที่ monolith กับ microservices อยู่ร่วมกันนั้น "ยุ่งเหยิง" แต่สถาปัตยกรรมของระบบที่รันอยู่จริงในโลกจริงไม่เคยสะอาดหรือสมบูรณ์แบบ ถ้าคุณอยากได้สถาปัตยกรรมที่ "สะอาด" ก็เชิญเคลือบพลาสติกภาพพิมพ์ของสถาปัตยกรรมระบบในอุดมคติที่คุณอาจมีได้ ถ้าเพียงแต่คุณมีวิสัยทัศน์ที่สมบูรณ์แบบและเงินทุนไม่จำกัด สถาปัตยกรรมระบบจริงเป็นสิ่งที่พัฒนาอยู่ตลอดเวลา ซึ่งต้องปรับตัวตามความต้องการและความรู้ที่เปลี่ยนแปลงไป ทักษะอยู่ที่การทำความคุ้นเคยกับแนวคิดนี้ ซึ่งผมจะกลับมาพูดถึงอีกครั้งใน Chapter 16

การทำให้การย้ายไปสู่ microservices ของคุณเป็นการเดินทางแบบค่อยเป็นค่อยไป ทำให้คุณสามารถค่อย ๆ ทลายสถาปัตยกรรม monolithic ที่มีอยู่ ส่งมอบการปรับปรุงไปพร้อม ๆ กัน และที่สำคัญคือรู้ว่าเมื่อไรควรหยุด

ในสถานการณ์ที่หายากอย่างน่าประหลาดใจ การล้มเลิก monolith อาจเป็นข้อกำหนดที่จำเป็นต้องทำ จากประสบการณ์ของผม สิ่งนี้มักจำกัดอยู่แค่สถานการณ์ที่ monolith ที่มีอยู่สร้างขึ้นบนเทคโนโลยีที่ตายแล้วหรือกำลังจะตาย ผูกติดกับ infrastructure ที่ต้องเลิกใช้ หรืออาจเป็นระบบจากบุคคลที่สามที่มีราคาแพงที่คุณอยากเลิกใช้ แม้ในสถานการณ์เหล่านี้ แนวทางแบบค่อยเป็นค่อยไปในการแบ่งย่อยก็ยังสมควรใช้อยู่ ด้วยเหตุผลที่ผมได้อธิบายไปแล้ว

The Dangers of Premature Decomposition (อันตรายของการแบ่งย่อยก่อนเวลาอันควร)

มี อันตรายในการสร้าง microservices เมื่อคุณมีความเข้าใจ domain ที่ไม่ชัดเจน ตัวอย่างของปัญหาที่สิ่งนี้อาจก่อให้เกิดขึ้นมาจากบริษัทเก่าของผมเอง Thoughtworks หนึ่งในผลิตภัณฑ์ของบริษัทคือ Snap CI ซึ่งเป็นเครื่องมือ continuous integration และ continuous delivery แบบ hosted (เราจะพูดถึงแนวคิดเหล่านี้ใน Chapter 7 ) ทีมงานเคยทำงานกับเครื่องมือที่คล้ายกันมาก่อน คือ GoCD ซึ่งตอนนี้เป็นเครื่องมือ continuous delivery แบบ open source ที่สามารถ deploy ในเครื่องได้แทนที่จะต้องโฮสต์บนคลาวด์

แม้จะมีการใช้โค้ดซ้ำกันบ้างในช่วงแรกระหว่างโปรเจกต์ Snap CI และ GoCD แต่ในท้ายที่สุด Snap CI ก็กลายเป็น codebase ใหม่ทั้งหมด กระนั้นก็ตาม ประสบการณ์ก่อนหน้าของทีมใน domain ของเครื่องมือ CD ก็ทำให้พวกเขากล้าที่จะเคลื่อนไหวเร็วขึ้นในการระบุขอบเขตและสร้างระบบของตัวเองเป็นชุดของ microservices

แต่หลังจากผ่านไปสองสามเดือน ก็เริ่มชัดเจนว่า use case ของ Snap CI นั้นแตกต่างไปมากพอที่แนวทางเริ่มต้นของขอบเขต service นั้นไม่ค่อยถูกต้องนัก สิ่งนี้นำไปสู่การเปลี่ยนแปลงมากมายที่ต้องทำข้าม service ต่าง ๆ และต้นทุนของการเปลี่ยนแปลงที่สูงตามมา ในที่สุดทีมก็รวม service กลับเข้าเป็นระบบ monolithic เดียว ให้เวลาสมาชิกทีมได้เข้าใจให้ดีขึ้นว่าขอบเขตควรอยู่ตรงไหน หนึ่งปีต่อมา ทีมสามารถแยกระบบ monolithic นี้ออกเป็น microservices ได้ ซึ่งขอบเขตของมันพิสูจน์แล้วว่ามีเสถียรภาพมากกว่ามาก นี่ไม่ใช่ตัวอย่างเดียวของสถานการณ์แบบนี้ที่ผมเคยเห็น การแบ่งย่อยระบบเป็น microservices ก่อนเวลาอันควรอาจมีต้นทุนสูง โดยเฉพาะถ้าคุณยังใหม่ต่อ domain นั้น ในหลาย ๆ แง่มุม การมี codebase ที่มีอยู่แล้วที่คุณต้องการแบ่งย่อยเป็น microservices นั้นง่ายกว่าการพยายามไปสู่ microservices ตั้งแต่เริ่มต้นมาก ด้วยเหตุผลนี้เอง