สำรวจมุมมองปฏิบัติของ Martin Fowler เกี่ยวกับสถาปัตยกรรม: รูปแบบ การรีแฟคเตอร์ และสถาปัตยกรรมเชิงวิวัฒนาการ ที่ยืนยาวกว่าสแต็กที่มาเป็นเทรนด์และลดความเสี่ยงระยะยาว

เฟรมเวิร์กใหม่ บริการคลาวด์แวววับ หรือ “สแต็กมาตรฐาน” ที่บริษัทฮอตๆ ใช้อาจทำให้รู้สึกว่าเป็นทางลัดไปสู่คุณภาพ แต่การคิดแบบยึดสแต็กก่อนมักสับสนระหว่าง เครื่องมือ กับ โครงสร้าง คุณอาจสร้างระบบที่รกและเปลี่ยนยากด้วยเทคโนโลยีล้ำสมัยที่สุด หรือสร้างระบบที่สะอาดและปรับตัวได้ด้วยตัวเลือกที่น่าเบื่อและเป็นที่รู้จักดี
การเลือกสแต็กก่อนจะผลักทีมไปสู่การตัดสินใจที่ดูน่าประทับใจบนสไลด์ แต่ไม่ตอบคำถามที่แท้จริง:
เมื่อการเลือกเทคโนโลยีเป็นผู้นำ สถาปัตยกรรมจะกลายเป็นผลพลอยได้โดยบังเอิญ—ส่งผลให้เกิดการเชื่อมโยงแน่น การทำซ้ำตรรกะ และการพึ่งพาที่ทำให้การเปลี่ยนแปลงง่ายๆ กลายเป็นงานแพง
นี่คือเหตุผลที่คำว่า “เราใช้ไมโครเซอร์วิส” (หรือ “ตอนนี้เราเป็น serverless”) ไม่ถือเป็นสถาปัตยกรรม แต่เป็นแนวทางการ deploy และเครื่องมือจริงๆ สถาปัตยกรรมคือวิธีที่ส่วนต่างๆ ของระบบร่วมมือกัน การตัดสินใจจำกัดงานในอนาคตอย่างไร และผลิตภัณฑ์สามารถวิวัฒน์ได้ง่ายแค่ไหน
ความหมายเชิงปฏิบัติ: เครื่องมือช่วยเร่งการส่งมอบได้ แต่ไม่มาแทนการคิดด้านสถาปัตยกรรม ถึงแม้จะใช้วิธีการสร้างและทำซ้ำอย่างรวดเร็วผ่านการแชท แต่อีกฝ่ายยังต้องตอบคำถามเดิม ทีมที่ได้ผลดีที่สุดยังคงยอมให้ขอบเขต ความเป็นเจ้าของ และความสามารถในการเปลี่ยนแปลงเป็นข้อกังวลระดับหนึ่ง (ไม่ใช่สิ่งที่ framework จะแก้ให้โดยปาฏิหาริย์) อย่างเช่นแพลตฟอร์มอย่าง Koder.ai สามารถเร่งการสร้างเว็บ แบ็กเอนด์ และแอปมือถือได้อย่างมาก แต่ทีมที่ได้ผลดียังคงให้ความสำคัญกับขอบเขตและความเปลี่ยนแปลง
งานเขียนของ Martin Fowler มักดึงความสนใจกลับไปที่สิ่งสำคัญ: การออกแบบที่ชัดเจนเหนือชิ้นส่วนที่เป็นเทรนด์ ข้อแลกเปลี่ยนที่ปฏิบัติได้เหนืออุดมคติ และความสามารถในการวิวัฒน์ระบบเมื่อเรียนรู้ งานของเขามองว่าสถาปัตยกรรมคือสิ่งที่คุณปรับปรุงอย่างต่อเนื่อง—ไม่ใช่ความสำเร็จครั้งเดียวแล้วจบ
คาดหวังธีมซ้ำสามอย่าง: ใช้รูปแบบเป็นเครื่องมือที่เลือกได้ (ไม่ใช่กฎตายตัว), รีแฟคเตอร์เป็นนิสัยประจำ, และสถาปัตยกรรมเชิงวิวัฒนาการ—สร้างเพื่อการเปลี่ยนแปลง ไม่ใช่เพื่อความแน่นอน
ถ้าคุณเป็นผู้นำด้านวิศวกรรม เทคลีด หรือทีมผลิตภัณฑ์ที่พยายามส่งของให้เร็วยิ่งขึ้นโดยไม่ให้คุณภาพพัง นี่เหมาะกับคุณ เป้าหมายไม่ใช่เลือกสแต็กที่ “สมบูรณ์แบบ” แต่คือการตัดสินใจที่ทำให้ซอฟต์แวร์เปลี่ยนแปลงได้ง่ายเมื่อโรดแมปเปลี่ยนแปลง
สถาปัตยกรรมซอฟต์แวร์คือชุดการตัดสินใจที่กำหนดรูปร่างระบบในทางที่ยาก (และแพง) หากจะแก้ไขทีหลัง
คำนิยามนี้ตั้งใจให้เรียบง่าย ไม่จำเป็นต้องมีไดอะแกรมพิเศษหรือใช้ตำแหน่งชื่อ “architect” มันคือเรื่องของการเลือกที่กำหนดวิธีการเติบโตของซอฟต์แวร์ วิธีที่ทีมทำงานร่วมกัน และค่าใช้จ่ายในการดูแลรักษา
เฟรมเวิร์ก เครื่องมือ และสไตล์การเขียนโค้ดสำคัญ—แต่ส่วนใหญ่เปลี่ยนได้ง่ายเมื่อเทียบกับการตัดสินใจด้านสถาปัตยกรรมจริงๆ
สถาปัตยกรรมใกล้เคียงกับโครงสร้างและขอบเขตมากกว่า: ส่วนต่างๆ ของระบบสื่อสารกันอย่างไร ข้อมูลเก็บที่ไหน จัดการความล้มเหลวอย่างไร และการเปลี่ยนแปลงใดต้องการการประสานงานข้ามทีม
ไม่มีสถาปัตยกรรมที่ “ดีที่สุด” ทั่วไป การตัดสินใจแต่ละอย่างเพิ่มประสิทธิภาพด้านหนึ่งแต่ทำให้ด้านอื่นเสียเปรียบ:
สถาปัตยกรรมที่ดีทำให้ข้อแลกเปลี่ยนเหล่านี้ชัดเจน แทนที่จะเป็นผลบังเอิญ
การตัดสินใจเชิงสถาปัตยกรรม: “เราจะแยก billing ออกเป็นบริการที่ deploy ได้แยกต่างหาก มีฐานข้อมูลของตัวเอง และระบบอื่นๆ จะรวมผ่านเหตุการณ์แบบอะซิงโครนัส”
สิ่งนี้ส่งผลต่อการ deploy, การเป็นเจ้าของข้อมูล, โหมดความล้มเหลว, การมอนิเตอร์ และการประสานงานของทีม
การเลือกไลบรารี: “เราจะใช้ไลบรารี X เพื่อสร้าง PDF”
มีประโยชน์ แต่โดยปกติเปลี่ยนได้และผลกระทบจำกัด
ถ้าการย้อนกลับการตัดสินใจต้องใช้เวลาหลายสัปดาห์ของงานประสาน มันน่าจะเป็นสถาปัตยกรรม
รูปแบบการออกแบบควรถูกมองเป็น ทางแก้ที่ใช้ซ้ำสำหรับปัญหาที่เกิดซ้ำ ไม่ใช่คำสั่งตายตัว มุมมองของ Fowler คือปฏิบัติได้: รูปแบบมีประโยชน์เมื่อช่วยให้การออกแบบชัดเจน และเป็นโทษเมื่อมาทดแทนการคิด
ใช้อย่างเหมาะสม รูปแบบให้คำศัพท์กลางกับทีม การพูดว่า “strategy” หรือ “repository” ช่วยย่นคำอธิบายยาวๆ เป็นคำเดียว ทำให้การรีวิวเร็วขึ้นและลดความเข้าใจผิด
รูปแบบยังทำให้พฤติกรรมระบบคาดเดาได้มากขึ้น รูปแบบที่คุ้นเคยกำหนดความคาดหวังเกี่ยวกับตำแหน่งตรรกะ การร่วมมือของอ็อบเจ็กต์ และการเปลี่ยนแปลงที่อาจกระทบออกไป ความคาดเดาได้นี้ช่วยลดความประหลาดใจในโปรดักชันและลดคำถามของสมาชิกใหม่ในทีม
โหมดล้มเหลวคือ cargo-culting: ใช้รูปแบบเพราะมันดัง เพราะมีคนเขียนไว้ หรือเพราะ “ที่นี่ทำกันแบบนี้” ซึ่งมักนำไปสู่การโอเวอร์เอนจิเนียริ่ง—เลเยอร์เพิ่มขึ้น การอ้อมทาง และนามธรรมที่ไม่คุ้มค่า
กับดักอีกแบบคือ “มีรูปแบบสำหรับทุกอย่าง” เมื่อทุกปัญหาเล็กๆ ได้รับการตั้งชื่อเป็นรูปแบบ ฐานโค้ดอาจกลายเป็นพิพิธภัณฑ์ความเจ๋งแทนที่จะเป็นเครื่องมือสำหรับส่งมอบและบำรุงรักษา
เริ่มจากปัญหา ไม่ใช่รูปแบบ
ถามตัวเอง:
แล้วเลือกรูปแบบที่เรียบที่สุดที่เหมาะและยังเปิดทางเลือกไว้ ถ้าจำเป็นต้องมีโครงสร้างมากขึ้นในภายหลัง ให้เพิ่มแบบค่อยเป็นค่อยไป—มักถูกขับเคลื่อนโดยความเจ็บปวดจริงและยืนยันโดยการรีแฟคเตอร์ แทนการเดาล่วงหน้า
รีแฟคเตอร์คือการปรับปรุงการออกแบบภายในของซอฟต์แวร์โดยไม่เปลี่ยนพฤติกรรมการทำงานของมัน ผู้ใช้ไม่ควรสังเกตเห็นความแตกต่างหลังรีแฟคเตอร์—นอกจากการที่การเปลี่ยนแปลงในอนาคตทำได้ง่าย ปลอดภัย และเร็วขึ้น
ประเด็นของ Martin Fowler ไม่ใช่แค่ “ให้โค้ดสวย” แต่มันคือสถาปัตยกรรมไม่ใช่ไดอะแกรมครั้งเดียวที่วาดตอนเริ่มต้น สถาปัตยกรรมคือชุดการตัดสินใจที่กำหนดความง่ายในการเปลี่ยนแปลง และรีแฟคเตอร์คือวิธีที่คุณป้องกันไม่ให้การตัดสินใจนั้นแข็งตัวเป็นข้อจำกัด
เมื่อเวลาผ่านไป แม้ระบบที่ออกแบบดีจะเริ่มล่องลอย ฟีเจอร์ใหม่ถูกเพิ่มภายใต้แรงกดดัน แก้ไขด่วนกลายเป็นถาวร และขอบเขตเริ่มเบลอ รีแฟคเตอร์คือวิธีที่คุณฟื้นฟูการแยกหน้าที่ที่ชัดเจนและลดความซับซ้อนโดยไม่ตั้งใจ เพื่อให้ระบบยังคง เปลี่ยนแปลงได้
สถาปัตยกรรมที่แข็งแรงคือที่ที่:
รีแฟคเตอร์เป็นงานประจำวันเพื่อรักษาคุณสมบัติเหล่านี้
คุณไม่ได้ตั้งเวลาสำหรับรีแฟคเตอร์เพราะปฏิทิน แต่เพราะโค้ดเริ่มต่อต้าน:
เมื่อสิ่งเหล่านี้ปรากฏ สถาปัตยกรรมได้รับผลกระทบ—รีแฟคเตอร์คือการซ่อมแซม
การรีแฟคเตอร์อย่างปลอดภัยพึ่งพานิสัยบางอย่าง:
ทำแบบนี้ รีแฟคเตอร์จะกลายเป็นการบำรุงรักษารายวัน—รักษาระบบให้พร้อมสำหรับการเปลี่ยนแปลงถัดไป แทนที่จะเปราะบางหลังงานล่าสุด
หนี้ทางเทคนิคคือ ต้นทุนในอนาคตที่เกิดจากทางลัดวันนี้ มันไม่ใช่ “โค้ดไม่ดี” ในแง่ศีลธรรม แต่มันคือการเทรดออฟที่คุณทำ (บางครั้งโดยรู้ตัว) ที่เพิ่มราคาของการเปลี่ยนแปลงในอนาคต มุมมองของ Martin Fowler มีประโยชน์ที่นี่: หนี้เป็นปัญหาเมื่อคุณหยุดติดตามมันและเริ่มแกล้งทำเป็นไม่มี
หนี้ที่ตั้งใจ ถูกยอมรับโดยรู้ตัว: “เราจะส่งเวอร์ชันที่เรียบง่ายก่อน แล้วแข็งให้ในสปรินต์หน้า” นั่นอาจสมเหตุสมผล—ถ้าคุณวางแผนการชำระคืน
หนี้โดยไม่ตั้งใจ เกิดเมื่อทีมไม่รู้ว่ากำลังยืม: การพึ่งพาที่รกแทรกซึม โมเดลโดเมนไม่ชัด หรือวิธีแก้แบบด่วนกลายเป็นมาตรฐาน หนี้โดยไม่ตั้งใจมักแพงกว่าเพราะไม่มีใครเป็นเจ้าของ
หนี้เพิ่มขึ้นผ่านแรงกดดันปกติ:
ผลลัพธ์คาดเดาได้: ฟีเจอร์ช้าลง บั๊กเพิ่ม และการรีแฟคเตอร์กลายเป็นความเสี่ยงแทนจะเป็นกิจวัตร
คุณไม่จำเป็นต้องมีโปรแกรมใหญ่เพื่อเริ่มชำระหนี้:
ถ้าคุณทำให้การตัดสินใจเรื่องหนี้มองเห็นได้ (เช่น บันทึกการตัดสินใจด้านสถาปัตยกรรม) คุณจะเปลี่ยนต้นทุนที่ซ่อนอยู่ให้กลายเป็นงานที่จัดการได้
สถาปัตยกรรมคือชุดการตัดสินใจที่ยากและแพงถ้าจะย้อนกลับทีหลัง เช่น ขอบเขต ความเป็นเจ้าของข้อมูล วิธีการรวมระบบ และการจัดการเมื่อเกิดความล้มเหลว。
สแต็กเทคโนโลยีเป็นเครื่องมือที่ใช้เพื่อให้การตัดสินใจเหล่านั้นเกิดขึ้น (ฟราเมิร์ก ไลบรารี ผลิตภัณฑ์คลาวด์) คุณสามารถเปลี่ยนเครื่องมือหลายๆ อย่างได้โดยมีผลกระทบน้อย แต่การเปลี่ยนขอบเขตหรือการไหลของข้อมูลมักต้องการงานประสานหลายสัปดาห์
วิธีทดสอบที่ดีคือความย้อนกลับ: ถ้าการยกเลิกการตัดสินใจจะใช้เวลาหลายสัปดาห์และต้องการการประสานงานของหลายทีม นั่นคือสถาปัตยกรรม。
ตัวอย่าง:
ใช้รูปแบบเมื่อมันแก้ปัญหาซ้ำได้จริงๆ ไม่ใช่เพื่อทำให้การออกแบบดู ‘มืออาชีพ’ เท่านั้น。
เช็คลิสต์สั้นๆ:
ถ้าคุณตั้งคำถามของปัญหาไม่ได้ชัด อย่าเพิ่มรูปแบบตอนนี้
มองว่าการรีแฟคเตอร์เป็นการบำรุงรักษารายวัน ไม่ใช่โปรเจ็กต์ทำความสะอาดครั้งเดียว。
สัญญาณทั่วไปที่บอกว่าถึงเวลารีแฟคเตอร์:
รักษาความปลอดภัยด้วยเทส ก้าวเล็กๆ และการรีวิวโค้ดที่เข้มงวด
ติดตามหนี้ทางเทคนิคเหมือนต้นทุน ไม่ใช่ความอับอาย。
แนวทางที่เป็นรูปธรรม:
ทำให้การตัดสินใจเรื่องหนี้ชัดเจน เช่น เขียนบันทึกการตัดสินใจเบาๆ
หมายถึงออกแบบเพื่อให้เปลี่ยนทิศทางได้อย่างปลอดภัยขณะเรียนรู้ แทนที่จะเดิมพันกับการทำนายระยะยาว。
ส่วนประกอบทั่วไป:
เป้าหมายคือความสามารถในการปรับตัว ไม่ใช่พิมพ์เขียวที่สมบูรณ์แบบตั้งแต่แรก
ฟังก์ชันความฟิตคือเกราะป้องกันอัตโนมัติที่รักษาเป้าหมายด้านสถาปัตยกรรม。
ตัวอย่างที่เริ่มจากได้ง่าย:
เลือกไม่กี่ตัวที่สะท้อนสัญญาของทีม (ความเร็วการเปลี่ยนแปลง ความน่าเชื่อถือ ความปลอดภัย) แล้วรันต่อเนื่อง
เริ่มจากโมโนลิธแบบมีโมดูลเป็นค่าเริ่มต้น เว้นแต่มีแรงกดดันที่วัดได้และคงที่ที่ต้องการการ deploy แยกส่วน。
ไมโครเซอร์วิสจะให้ผลเมื่อมี:
ถ้าคุณยังไม่พร้อมจะรันบริการเดียวใน production ได้สบายๆ การแยกเป็นสิบจะเพิ่มความเจ็บปวดหลายเท่า
เริ่มโดยทำให้การพึ่งพาเป็นเรื่องที่มองเห็นและมีเจตนา。
การเคลื่อนไหวที่ให้ผลสูง:
ฐานข้อมูลที่แชร์สร้างการพึ่งพาลับๆ ที่บังคับให้ต้องปล่อยแบบประสานงาน
เขียน ADR เพื่อจับ สิ่งที่ตัดสินใจ และ ทำไม ในขณะที่บริบทยังสดอยู่。
ADR แบบเบาๆ ควรมี:
เก็บ ADR ใกล้กับโค้ด (เช่น /docs/adr/) และอ้างอิงแนวทางที่เกี่ยวข้อง เช่น ข้อความที่อยู่บนหน้า /blog/architecture-decision-records