Analyzing Trade-Offs (การวิเคราะห์ Trade-Off)

การคิดแบบสถาปนิกคือการมองเห็น trade-off ใน solution ทุกอย่าง ไม่ว่าจะเป็นทางเทคนิคหรือไม่ก็ตาม และวิเคราะห์ trade-off เหล่านั้นเพื่อพิจารณา solution ที่ดีที่สุด เหตุผลที่นี่เป็นหนึ่งในกิจกรรมสำคัญของสถาปนิก (และจึงเป็นส่วนหนึ่งของ architectural thinking) แสดงให้เห็นได้ผ่านคำพูดต่อไปนี้ของ Mark (หนึ่งในผู้เขียนของเรา)

Architecture คือสิ่งที่คุณ Google หรือถาม LLM ไม่ได้

Mark Richards

ทุกสิ่ง ใน architecture คือ trade-off ซึ่งเป็นเหตุผลว่าทำไมคำตอบชื่อดังสำหรับทุกคำถามด้าน architecture ในจักรวาลนี้ คือ “มันขึ้นอยู่กับสถานการณ์” แม้คำตอบนี้อาจฟังดูน่ารำคาญ แต่น่าเสียดายที่มันเป็นความจริง คุณไม่สามารถ Google หาคำตอบ หรือถาม AI engine หรือ large language model (LLM) ได้ว่า REST หรือ messaging ดีกว่ากันสำหรับระบบของคุณ หรือว่า microservices เป็น architecture style ที่ถูกต้องสำหรับผลิตภัณฑ์ใหม่ของคุณหรือไม่ เพราะคำตอบนั้น ขึ้นอยู่กับ จริงๆ มันขึ้นอยู่กับ deployment environment, business driver, วัฒนธรรมองค์กร, งบประมาณ, กรอบเวลา, ทักษะของนักพัฒนา และปัจจัยอื่นๆ อีกหลายสิบอย่าง สภาพแวดล้อม สถานการณ์ และปัญหาของแต่ละคนจะแตกต่างกัน นั่นเป็นเหตุผลว่าทำไม architecture ถึงยากขนาดนี้ อ้างคำพูดของ Neal ผู้เขียนอีกคนของเรา

ไม่มีคำตอบที่ถูกหรือผิดใน architecture มีแต่ trade-off

Neal Ford

ตัวอย่างเช่น ลองพิจารณาระบบประมูลสินค้า ( รูปที่ 2-8 ) ที่ผู้ประมูลออนไลน์เสนอราคาสินค้าที่นำมาประมูล service Bid Producer สร้าง bid จากผู้ประมูล แล้วส่งจำนวนเงินที่เสนอนั้นไปยัง service Bid Capture , Bid Tracking และ Bid Analytics

Bidding Example

Figure 2-8. Auction system example of a trade-off—queues or topics?

สำหรับพฤติกรรม asynchronous ในระบบนี้ สถาปนิกสามารถใช้ queue แบบ point-to-point messaging หรือใช้ topic แบบ publish-and-subscribe messaging ก็ได้ พวกเขาควรเลือกอันไหน พวกเขา Google หาคำตอบไม่ได้ Architectural thinking ต้องการให้พวกเขาวิเคราะห์ trade-off ที่เกี่ยวข้องกับแต่ละตัวเลือก และเลือกตัวเลือกที่ดีที่สุด (หรือแย่น้อยที่สุด) ตามสถานการณ์เฉพาะนั้นๆ

ตัวเลือก messaging สองแบบสำหรับระบบประมูลสินค้าแสดงไว้ใน รูปที่ 2-9 ซึ่งแสดงการใช้ topic ใน publish-and-subscribe messaging model และ รูปที่ 2-10 ซึ่งแสดงการใช้ queue ใน point-to-point messaging model

Bidding Example Using Topic

Figure 2-9. Using a topic for communication between services

Bidding Example Using Queues

Figure 2-10. Using queues for communication between services

ข้อได้เปรียบที่ชัดเจน (และดูเหมือนจะเป็น solution ที่ชัดแจ้ง) สำหรับปัญหานี้ใน รูปที่ 2-9 คือ architectural extensibility service Bid Producer ต้องการเพียงการเชื่อมต่อเดียวไปยัง topic เปรียบเทียบกับ solution แบบ queue ใน รูปที่ 2-10 ที่ Bid Producer ต้องเชื่อมต่อกับ queue สามตัวที่ต่างกัน ถ้ามี service ใหม่ชื่อ Bid History ถูกเพิ่มเข้ามาในระบบนี้ (เพื่อให้ผู้ประมูลแต่ละคนดูประวัติการเสนอราคาทั้งหมดของตัวเองได้) ก็จะไม่ต้องเปลี่ยนแปลง service หรือ infrastructure ที่มีอยู่เดิมเลย service Bid History ใหม่สามารถ subscribe ไปยัง topic ที่มีข้อมูล bid อยู่แล้วได้เลย

อย่างไรก็ตาม ด้วยตัวเลือก queue ที่แสดงใน รูปที่ 2-10 service Bid History จะต้องมี queue ใหม่ และ Bid Producer ก็ต้องถูกแก้ไขเพื่อเพิ่มการเชื่อมต่อใหม่ไปยัง queue นั้น ประเด็นตรงนี้คือการใช้ queue หมายความว่า การเพิ่มฟังก์ชันการประมูลใหม่ต้องเปลี่ยนแปลง service และ infrastructure อย่างมาก ในขณะที่ด้วยแนวทาง topic ไม่ต้องเปลี่ยนแปลง infrastructure ที่มีอยู่เลย นอกจากนี้ Bid Producer ยังมี coupling น้อยกว่าในตัวเลือก topic ที่ Bid Producer ไม่รู้ว่าข้อมูล bid จะถูกใช้อย่างไรหรือโดย service ไหน ในตัวเลือก queue Bid Producer รู้แน่ชัดว่าข้อมูล bid จะถูกใช้อย่างไร (และโดยใคร) จึงมี coupling กับระบบมากกว่า

ถึงตอนนี้ การวิเคราะห์ trade-off ดูเหมือนจะทำให้ชัดเจนว่าแนวทาง topic ที่ใช้ publish-and-subscribe messaging model เป็นตัวเลือกที่ชัดแจ้งและดีที่สุด แต่ให้อ้างคำพูดของ Rich Hickey ผู้สร้างภาษาโปรแกรม Clojure

โปรแกรมเมอร์รู้จักประโยชน์ของทุกอย่าง แต่ไม่รู้จัก trade-off ของอะไรเลย สถาปนิกต้องเข้าใจทั้งสองอย่าง

Rich Hickey

การคิดแบบสถาปนิกหมายถึงไม่ใช่แค่มองประโยชน์ของ solution หนึ่งๆ เท่านั้น แต่ต้องวิเคราะห์ด้านลบที่เกี่ยวข้อง หรือ trade-off ด้วย ต่อจากตัวอย่างระบบประมูลสินค้า software architect จะวิเคราะห์ด้านลบของ solution แบบ topic พร้อมกับด้านบวกด้วย ใน รูปที่ 2-9 คุณจะเห็นว่าด้วย topic ใครก็ตาม สามารถเข้าถึงข้อมูล bid ได้ ซึ่งก่อให้เกิดปัญหาที่เป็นไปได้เรื่องการเข้าถึงข้อมูลและความปลอดภัยของข้อมูล อย่างไรก็ตาม ใน queue model ที่แสดงใน รูปที่ 2-10 ข้อมูลที่ส่งไปยัง queue สามารถถูกเข้าถึงได้ เฉพาะ โดย consumer เฉพาะที่รับข้อความนั้นเท่านั้น ถ้า service ที่ไม่พึงประสงค์แอบฟัง queue อยู่ service ที่ควรได้รับข้อมูลจริงๆ ก็จะไม่ได้รับ bid เหล่านั้น และการแจ้งเตือนจะถูกส่งออกไปทันทีเกี่ยวกับการสูญเสียข้อมูล (และการละเมิดความปลอดภัยที่เป็นไปได้) กล่าวอีกนัยหนึ่งคือ มันง่ายมากที่จะดักฟัง topic แต่ไม่ใช่กับ queue

นอกจากปัญหาด้านความปลอดภัยแล้ว solution แบบ topic ใน รูปที่ 2-9 ยังรองรับเฉพาะ homogeneous contract เท่านั้น service ทั้งหมดที่รับข้อมูล bid ต้องยอมรับ data contract และชุดข้อมูล bid เดียวกัน ในตัวเลือก queue consumer แต่ละตัวสามารถมี contract ของตัวเอง เฉพาะกับข้อมูลที่มันต้องการได้ ตัวอย่างเช่น สมมติว่า service Bid History ใหม่ต้องการราคาเสนอปัจจุบันควบคู่กับ bid แต่ไม่มี service อื่นต้องการข้อมูลนั้น ในกรณีนี้ contract จะต้องถูกแก้ไข ซึ่งกระทบต่อ service อื่นๆ ทั้งหมดที่ใช้ข้อมูลนั้น ใน queue model นี่จะเป็น channel แยกต่างหาก และจึงเป็น contract แยกต่างหากที่ไม่กระทบ service อื่นเลย

ข้อเสียอีกอย่างของ topic model คือมันไม่รองรับการ monitor จำนวนข้อความใน topic ดังนั้นจึงไม่รองรับ ความสามารถ autoscaling อย่างไรก็ตาม ด้วยตัวเลือก queue แต่ละ queue สามารถ monitor ได้แยกกัน และสามารถใช้ programmatic load balancing กับ bidding consumer แต่ละตัว เพื่อให้แต่ละตัว scale ได้อัตโนมัติอย่างอิสระต่อกัน โปรดสังเกตว่า trade-off นี้เป็นเรื่องเฉพาะเทคโนโลยี Advanced Message Queuing Protocol (AMQP) สามารถรองรับ programmatic load balancing และ monitoring ได้ เพราะมันแยก exchange (ที่ producer ส่งไปหา) กับ queue (ที่ consumer ฟังอยู่) ออกจากกัน

เมื่อมี trade-off analysis ที่ครบถ้วนขึ้นแบบนี้ ตัวเลือกไหนดีกว่ากัน

มันขึ้นอยู่กับสถานการณ์! ตารางที่ 2-1 สรุป trade-off เหล่านี้

Table 2-1. Trade-offs for topics | ข้อดีของ Topic | ข้อเสียของ Topic | | --- | --- | | Architectural extensibility | ข้อกังวลเรื่องการเข้าถึงข้อมูลและความปลอดภัยของข้อมูล | | Service decoupling | ไม่มี heterogeneous contract | | | Monitoring และ programmatic scalability |

อีกครั้ง ทุกสิ่ง ใน software architecture มี trade-off ทั้งข้อดีและข้อเสีย การคิดแบบสถาปนิกหมายถึงการวิเคราะห์ trade-off เหล่านี้ แล้วตั้งคำถามอย่างเช่น “อะไรสำคัญกว่ากัน extensibility หรือ security” ทางเลือกของสถาปนิก จะขึ้นอยู่กับ business driver สภาพแวดล้อม และปัจจัยอื่นๆ อีกมากมายเสมอ