Governance and the Paved Road (Governance และ Paved Road)

ส่วนหนึ่ง ของสิ่งที่สถาปนิกต้องจัดการคือ governance แล้ว governance หมายความว่าอะไรกันแน่ ปรากฏว่ากรอบการทำงาน COBIT (Control Objectives for Information Technologies) มีคำนิยามที่ค่อนข้างดี: 8

Governance ensures that enterprise objectives are achieved by evaluating stakeholder needs, conditions and options; setting direction through prioritization and decision making; and monitoring performance, compliance and progress against agreed-on direction and objectives.

กล่าวโดยสรุป เราสามารถมอง governance ว่าเป็นการตกลงกันว่าควรทำสิ่งต่างๆ อย่างไร มั่นใจว่าคนรู้ว่าควรทำสิ่งต่างๆ อย่างไร และมั่นใจว่าสิ่งต่างๆ ถูกทำตามนั้นจริง ในบางสภาพแวดล้อม governance เกิดขึ้นอย่างไม่เป็นทางการ เป็นส่วนหนึ่งของกิจกรรมการพัฒนาซอฟต์แวร์ปกติ ในสภาพแวดล้อมอื่น โดยเฉพาะในองค์กรขนาดใหญ่ มันอาจต้องเป็นฟังก์ชันที่เป็นรูปธรรมมากขึ้น

Governance สามารถนำไปใช้กับหลายเรื่องในแวดวงไอที เราต้องการโฟกัสไปที่แง่มุมของ technical governance ซึ่งผมรู้สึกว่าเป็นหน้าที่ของสถาปนิก ถ้าหนึ่งในหน้าที่ของสถาปนิกคือการมั่นใจว่ามีวิสัยทัศน์ทางเทคนิค governance ก็คือการมั่นใจว่าสิ่งที่เรากำลังสร้างตรงกับวิสัยทัศน์นี้ และวิวัฒนาการวิสัยทัศน์เมื่อจำเป็น

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

การมารวมตัวกันและตกลงกันว่าจะทำสิ่งต่างๆ อย่างไรเป็นความคิดที่ดี แต่การใช้เวลาให้แน่ใจว่าคนกำลังทำตามแนวทางเหล่านี้นั้นสนุกน้อยกว่า เช่นเดียวกับการวางภาระให้นักพัฒนาต้องนำสิ่งมาตรฐานทั้งหมดที่คุณคาดหวังให้ไมโครเซอร์วิสแต่ละตัวทำไปปฏิบัติจริง ผมเชื่ออย่างแรงกล้าในการทำให้สิ่งที่ถูกต้องทำได้ง่าย และอย่างที่เราพูดถึงใน Chapter 15 paved road เป็นแนวคิดที่มีประโยชน์มากตรงนี้ สถาปนิกมีบทบาทในการอธิบายวิสัยทัศน์อย่างชัดเจน ว่าคุณกำลังมุ่งหน้าไปทางไหน และทำให้การไปถึงจุดนั้นง่าย ดังนั้นพวกเขาควรเข้ามามีส่วนร่วมในการช่วยกำหนดรูปร่างความต้องการของ paved road ที่คุณจะสร้าง สำหรับหลายองค์กร แพลตฟอร์มจะเป็นตัวอย่างที่ใหญ่ที่สุดของเรื่องนี้ สถาปนิกจะกลายเป็นผู้มีส่วนได้ส่วนเสียที่สำคัญของทีมแพลตฟอร์ม

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

Exemplars (ตัวอย่างต้นแบบ)

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

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

Tailored Microservice Template (เทมเพลตไมโครเซอร์วิสที่ปรับแต่งเฉพาะ)

จะดี แค่ไหนถ้าคุณสามารถทำให้นักพัฒนาทุกคนทำตามแนวทางส่วนใหญ่ที่คุณมีได้ง่ายมากด้วยงานเพียงเล็กน้อย จะเป็นอย่างไรถ้านักพัฒนามีโค้ดส่วนใหญ่พร้อมใช้งานตั้งแต่แกะกล่อง เพื่อนำคุณลักษณะหลักที่ไมโครเซอร์วิสแต่ละตัวต้องมีไปใช้

มีเฟรมเวิร์กมากมายสำหรับภาษาโปรแกรมต่างๆ ที่พยายามให้บล็อกพื้นฐานสำหรับเทมเพลตไมโครเซอร์วิสของคุณเอง Spring Boot น่าจะเป็นตัวอย่างที่ประสบความสำเร็จที่สุดของเฟรมเวิร์กแบบนี้สำหรับ JVM ตัวแกนของ Spring Boot ค่อนข้างเบา แต่คุณสามารถเลือกรวมชุดไลบรารีเข้าด้วยกันเพื่อให้ได้ฟีเจอร์ต่างๆ เช่น การตรวจสุขภาพ (health check) การให้บริการ HTTP หรือการเปิดเผยเมตริก ดังนั้นตั้งแต่แกะกล่อง คุณจะมีไมโครเซอร์วิส "Hello World" ง่ายๆ ที่สามารถรันได้จาก command line

หลายคนนำเฟรมเวิร์กเหล่านี้มาสร้างมาตรฐานการตั้งค่านี้ให้กับบริษัทของตัวเอง ตัวอย่างเช่น เมื่อสร้างไมโครเซอร์วิสตัวใหม่ พวกเขาอาจเขียนสคริปต์เพื่อให้ได้เทมเพลต Spring Boot พร้อมไลบรารีหลักที่องค์กรของตัวเองใช้ต่อสายไว้แล้ว มันอาจดึงไลบรารีสำหรับจัดการ circuit breaker มาด้วยแล้ว และถูกตั้งค่าให้จัดการ JWT authentication สำหรับ inbound call ได้แล้ว โดยปกติแล้ว การสร้างเทมเพลตแบบอัตโนมัตินี้ยังจะสร้าง build pipeline ที่เข้าคู่กันด้วย

Caution warranted (ข้อควรระวัง)

การเลือกและตั้งค่าเทมเพลตไมโครเซอร์วิสที่ปรับแต่งเฉพาะเหล่านี้มักเป็นงานของทีมแพลตฟอร์ม พวกเขาอาจจัดเตรียมเทมเพลตสำหรับแต่ละภาษาที่รองรับ เพื่อมั่นใจว่าเมื่อใช้เทมเพลตนั้น ไมโครเซอร์วิสที่ได้จะทำงานร่วมกับตัวแพลตฟอร์มได้ดี แต่นี่ก็อาจก่อให้เกิดความท้าทายได้เช่นกัน

ผมเคยเห็นขวัญกำลังใจและประสิทธิผลของหลายทีมถูกทำลายลง จากการถูกยัดเยียดเฟรมเวิร์กที่บังคับใช้ ในความพยายามที่จะปรับปรุงการนำโค้ดกลับมาใช้ซ้ำ งานมากขึ้นเรื่อยๆ ถูกใส่เข้าไปในเฟรมเวิร์กแบบรวมศูนย์ จนกระทั่งมันกลายเป็นสิ่งประหลาดที่ท่วมท้น ถ้าคุณตัดสินใจใช้เทมเพลตไมโครเซอร์วิสที่ปรับแต่งเฉพาะ ให้คิดให้รอบคอบมากๆ ว่าหน้าที่ของมันคืออะไร ในอุดมคติ การใช้มันควรเป็นทางเลือกอย่างแท้จริง แต่ถ้าคุณจะบังคับใช้มากขึ้น คุณต้องเข้าใจว่าความง่ายในการใช้งานสำหรับนักพัฒนาต้องเป็นแรงขับเคลื่อนหลัก การเปิดให้นักพัฒนาที่ใช้เทมเพลตสามารถแนะนำและแม้แต่ contribute การเปลี่ยนแปลงกลับไปยังเฟรมเวิร์กได้ บางทีอาจเป็นส่วนหนึ่งของโมเดล internal open source ก็สามารถช่วยได้มากตรงนี้

อย่างที่เราพูดถึงใน "DRY and the Perils of Code Reuse in a Microservice World" เราต้องตระหนักถึงอันตรายของ shared code ในความปรารถนาที่จะสร้างโค้ดที่นำกลับมาใช้ซ้ำได้ เราอาจสร้างแหล่งที่มาของ coupling ระหว่างไมโครเซอร์วิสได้ อย่างน้อยหนึ่งองค์กรที่ผมเคยคุยด้วยกังวลเรื่องนี้มากจนถึงขั้น copy โค้ดเทมเพลตไมโครเซอร์วิสด้วยมือลงในแต่ละไมโครเซอร์วิส นี่หมายความว่าการอัปเกรดเทมเพลตไมโครเซอร์วิสหลักต้องใช้เวลานานกว่าจะถูกนำไปใช้ทั่วทั้งระบบ แต่สิ่งนี้กังวลน้อยกว่าสำหรับองค์กรเมื่อเทียบกับอันตรายของ coupling ทีมอื่นที่ผมเคยคุยด้วยเลือกปฏิบัติต่อเทมเพลตไมโครเซอร์วิสเหมือนเป็น shared binary dependency แม้ว่าพวกเขาต้องระมัดระวังอย่างมากไม่ให้แนวโน้มของ DRY (don't repeat yourself) ทำให้เกิดระบบที่ coupled กันมากเกินไป!

The Paved Road at Scale (Paved Road ในระดับสเกลใหญ่)

การใช้ เทมเพลตและเฟรมเวิร์กไมโครเซอร์วิสภายในองค์กรมักพบในองค์กรที่มีไมโครเซอร์วิสจำนวนมาก Netflix และ Monzo เป็นสององค์กรแบบนั้น แต่ละแห่งตัดสินใจสร้างมาตรฐาน technology stack ของตัวเองในระดับหนึ่ง (JVM ในกรณีของ Netflix, Go ในกรณีของ Monzo) ทำให้สามารถเร่งการสร้างไมโครเซอร์วิสใหม่ด้วยพฤติกรรมมาตรฐานที่คาดหวังได้ โดยใช้ชุดเครื่องมือร่วมกัน กับ technology stack ที่หลากหลายกว่านี้ การมีเทมเพลตไมโครเซอร์วิสมาตรฐานสำหรับความต้องการของคุณเองก็จะยากขึ้น

ถ้าคุณเลือกใช้ technology stack ที่แตกต่างกันหลายแบบ คุณจะ ต้องมีเทมเพลตไมโครเซอร์วิสที่เข้าคู่กันสำหรับแต่ละแบบ นี่อาจเป็นวิธีหนึ่งที่คุณจำกัดทางเลือกภาษาในทีมของคุณอย่างแนบเนียน ถ้าเทมเพลตไมโครเซอร์วิสภายในรองรับแค่ JVM คนก็อาจถูกกันไม่ให้เลือก stack อื่น เพราะพวกเขาต้องทำงานเองมากขึ้นเยอะ Netflix ยกตัวอย่างเช่น ให้ความสำคัญเป็นพิเศษกับเรื่องอย่าง fault tolerance เพื่อมั่นใจว่าการล่มของส่วนหนึ่งของระบบจะไม่ทำให้ทุกอย่างล่มตาม เพื่อจัดการเรื่องนี้ มีการทำงานจำนวนมากเพื่อมั่นใจว่ามี client library บน JVM ที่ให้เครื่องมือที่ทีมต้องการเพื่อรักษาไมโครเซอร์วิสของตัวเองให้มีพฤติกรรมดี การนำเทคโนโลยี stack ใหม่มาใช้จะหมายความว่าต้องทำงานซ้ำทั้งหมดนี้ใหม่ ข้อกังวลหลักของ Netflix ไม่ได้อยู่ที่งานที่ต้องทำซ้ำมากเท่ากับความจริงที่ว่ามันง่ายมากที่จะทำผิดพลาดตรงนี้ ความเสี่ยงที่ไมโครเซอร์วิสตัวหนึ่งจะทำ fault tolerance ที่เพิ่งสร้างขึ้นใหม่ผิดพลาดนั้นสูง ถ้ามันอาจกระทบส่วนอื่นของระบบมากขึ้น Netflix บรรเทาปัญหานี้ด้วยการใช้ "sidecar service" ซึ่งสื่อสารในเครื่องกับ JVM ที่ใช้ไลบรารีที่เหมาะสมอยู่แล้ว

Service mesh ให้อีกวิธีหนึ่งที่เป็นไปได้ในการถ่ายโอนพฤติกรรมร่วมออกไป ฟังก์ชันบางอย่างที่เคยถูกมองว่าเป็นความรับผิดชอบภายในของไมโครเซอร์วิสแต่ละตัวตอนนี้สามารถถูกผลักไปยัง microservice mesh ได้ สิ่งนี้ช่วยให้พฤติกรรมสอดคล้องกันมากขึ้นข้ามไมโครเซอร์วิสที่เขียนด้วยภาษาโปรแกรมที่ต่างกัน และยังลดความรับผิดชอบของเทมเพลตไมโครเซอร์วิสเหล่านี้ด้วย