Component Coupling (การเชื่อมโยงระหว่าง Component)

เมื่อ component สื่อสารกัน หรือเมื่อการเปลี่ยนแปลง component หนึ่งอาจส่งผลกระทบต่อ component อื่น ๆ เราเรียก component เหล่านั้นว่า coupled กัน ยิ่งระบบมี component ที่ coupled กันมากเท่าไร ก็ยิ่งดูแลรักษาและทดสอบระบบได้ยากขึ้นเท่านั้น (ดู Figure 8-11 ) ดังนั้นการให้ความสำคัญกับ coupling จึงเป็นเรื่องสำคัญ

Component coupling

Figure 8-11. Components can be coupled even if they don't communicate directly

Static Coupling (Static Coupling)

Static coupling เกิดขึ้นเมื่อ component สื่อสารกันแบบ synchronous สถาปนิกต้องให้ความสำคัญกับ coupling สองประเภท คือ afferent และ efferent

Afferent coupling (หรือเรียกว่า incoming หรือ fan-in coupling) คือระดับที่ component อื่นพึ่งพา component เป้าหมาย ตัวอย่างเช่น ลองพิจารณา component Customer Notification จากตัวอย่างระบบ order-entry ของเราใน Figure 8-12 เพื่อส่งอีเมลถึงลูกค้า ทั้ง component Order Placement และ Order Shipment ต้องสื่อสารกับ component Customer Notification นั่นหมายความว่า component Customer Notification เรียกว่า afferently coupled กับ component Order Placement และ Order Shipment และจะมีระดับ afferent coupling เท่ากับ 2 (จำนวน dependency ขาเข้า) afferent coupling มักถูกแทนด้วย CA

Afferent coupling

Figure 8-12. The Customer Notification component is afferently coupled to the other components

Efferent coupling (หรือเรียกว่า outgoing หรือ fan-out coupling) คือระดับที่ component เป้าหมายพึ่งพา component อื่น ๆ ตัวอย่างเช่น ดังแสดงใน Figure 8-13 component Order Placement พึ่งพา component Order Fulfillment จึงถือว่า efferently coupled กับมัน และจะมีระดับ efferent coupling เท่ากับ 1 (จำนวน dependency ขาออก) efferent coupling มักถูกแทนด้วย CE

Efferent coupling

Figure 8-13. The Order Placement component is efferently coupled to the Order Fulfillment component

Temporal Coupling (Temporal Coupling)

Temporal coupling อธิบายความสัมพันธ์แบบไม่ static ซึ่งมักอิงกับเรื่องเวลาหรือ transaction (หน่วยงานเดี่ยว) ตัวอย่างเช่น เมื่อระบบกำลังประมวลผลคำสั่งซื้อ ฟังก์ชันการทำงานใน component Order Placement ต้องถูกเรียกก่อนฟังก์ชันการทำงานใน component Order Shipment component เหล่านั้นจึงเรียกได้ว่ามี temporal coupling กัน

ปัญหาของ temporal coupling คือมันตรวจจับได้ยากด้วยเครื่องมือที่มีอยู่ในตลาดปัจจุบัน ในกรณีส่วนใหญ่ coupling ประเภทนี้มักถูกระบุผ่านเอกสารออกแบบหรือตรวจพบผ่านเงื่อนไข error แทน

The Law of Demeter (กฎของ Demeter)

สถาปนิกส่วนใหญ่ถูกสอนให้มุ่งสร้าง loose coupling ในการออกแบบระบบ การมี coupling ที่น้อยลงระหว่าง component หรือ service ทำให้ระบบดูแลรักษาได้ง่ายขึ้น ทดสอบง่ายขึ้น และมีความเสี่ยงในการ deploy น้อยลง มันยังเพิ่มความน่าเชื่อถือโดยรวมของระบบด้วย เพราะการเปลี่ยนแปลงจะส่งผลต่อ component น้อยลง ทำให้มีโอกาสเกิดข้อผิดพลาดน้อยลง

เทคนิคหนึ่งในการสร้างระบบที่ loosely coupled เรียกว่า Law of Demeter หรือเรียกอีกอย่างว่า Principle of Least Knowledge ในตำนานเทพเจ้ากรีก เทพี Demeter เป็นผู้ผลิตธัญพืชทั้งหมดให้กับทั้งโลก แต่เธอไม่มีความคิดเลยว่าผู้คนนำมันไปทำอะไร (เลี้ยงปศุสัตว์ ทำขนมปัง และอื่น ๆ) Demeter จึงถูก decoupled จากส่วนที่เหลือของโลกได้อย่างมีประสิทธิภาพ

Law of Demeter ระบุว่า component หรือ service ควรมีความรู้เกี่ยวกับ component หรือ service อื่นในระดับจำกัด แม้ฟังดูเรียบง่ายและชัดเจนในตัวเอง แต่จริง ๆ แล้วไม่ใช่ ให้เราแสดงให้คุณเห็นว่าเราหมายถึงอะไร

ลองพิจารณา component และการสื่อสารที่สอดคล้องกันที่แสดงใน Figure 8-14 เมื่อรับคำสั่งซื้อของลูกค้า component Order Placement ต้องบอก component Inventory Management ให้ลดจำนวนสินค้าคงคลังลง ถ้าสต็อกลดลงต่ำเกินไป component Order Placement ต้องทำสองอย่าง คือบอก component Supplier Ordering ให้สั่งสต็อกเพิ่มจากซัพพลายเออร์ และบอก component Item Pricing ให้ปรับราคาตามสต็อกที่มีจำกัด สุดท้าย เมื่อทุกอย่างเสร็จสิ้น component Order Placement จะบอก component Email Notification ให้ส่งอีเมลรายละเอียดคำสั่งซื้อให้ลูกค้า

Law of Demeter before

Figure 8-14. The Order Placement component is highly coupled to the rest of the system because it has too much knowledge

สังเกตว่าใน architecture นี้ component Order Placement coupled กับ component อื่น ๆ อย่างมาก แม้มันจะไม่มี ความรับผิดชอบ ในการทำการกระทำเหล่านั้น แต่มันมี ความรู้ ว่าการกระทำเหล่านี้ต้องเกิดขึ้น — และยิ่งมีความรู้มากเท่าไร ก็ยิ่ง coupling แน่นขึ้นเท่านั้น

แนวคิดเบื้องหลัง Law of Demeter คือการจำกัด ความรู้ ของแต่ละ component เกี่ยวกับส่วนที่เหลือของระบบ ใน Figure 8-14 component Order Placement รู้ว่าต้องลดสินค้าคงคลัง อาจต้องสั่งสต็อกเพิ่ม อาจต้องปรับราคาสินค้า และต้องส่งอีเมลถึงลูกค้า (นั่นคือความรู้ที่เยอะมาก!) แต่ถ้าความรู้นั้นถูกกระจายไปยัง component อื่นได้ล่ะ ถ้าทำได้ สถาปนิกก็จะสามารถ decouple component นั้นออกจากส่วนที่เหลือของระบบได้อย่างมีประสิทธิภาพ

เพื่อดูว่า Law of Demeter สามารถนำมาใช้ลด component coupling ได้อย่างไร ลองย้อนกลับไปดูระบบใน Figure 8-14 ถ้าสถาปนิกเพิ่ม component อีกตัวระหว่าง Order Placement และ Inventory Management เพื่อผลัก ความรู้ เรื่องการลดสินค้าคงคลังออกไป component Order Placement ก็จะยังคงมีระดับ efferent (ขาออก) coupling เท่าเดิม ดังนั้น จุด coupling นั้นจึงจำเป็นต้องคง เหมือนเดิม

แต่ความรู้ที่ว่า ถ้าสต็อกลดลงต่ำเกินไป ระบบต้องสั่งสต็อกเพิ่มและปรับราคาสินค้าล่ะ ความรู้ทั้งสองอย่างนี้ สามารถ ถูกผลักไปยัง component Inventory Management ได้ ซึ่งจะลดระดับ coupling ของ component Order Placement ลง Figure 8-15 แสดง architecture ที่ได้หลังจากนำ Law of Demeter มาใช้ การเอา ความรู้ ที่ว่าฟังก์ชันบางอย่างต้องเกิดขึ้นออกไปทำให้ component Order Placement coupled กับส่วนที่เหลือของระบบน้อยลง

Law of Demeter after

Figure 8-15. The Order Placement component is less coupled to the system when it has less knowledge

ผู้อ่านที่ช่างสังเกตจะเห็นว่า แม้การนำ Law of Demeter มาใช้จะลดระดับ coupling ของ component Order Placement แต่มันก็ เพิ่ม ระดับ coupling ของ component Inventory Management ด้วยเช่นกัน การนำ Law of Demeter มาใช้ไม่ได้แปลว่าจะลดระดับ coupling โดยรวมของทั้งระบบลงเสมอไป แต่โดยทั่วไปแล้วมันจะแค่กระจาย coupling นั้นไปยังส่วนอื่น ๆ ของระบบแทน