เมื่อเราพยายามจะแยกอะไรบางอย่างออกมาเดี่ยวๆ เราจะพบว่ามันถูกผูกติดอยู่กับทุกสิ่งทุกอย่างในจักรวาล
John Muir, My First Summer in the Sierra
ใน Topic 8, _The Essence of Good Design_ เราบอกว่าการใช้หลักการออกแบบที่ดีจะช่วยให้โค้ดที่คุณเขียนนั้นแก้ง่าย Coupling คือศัตรูตัวฉกาจของการเปลี่ยนแปลง เพราะมันผูกมัดสิ่งที่ต้องเปลี่ยนไปพร้อมๆ กันเข้าด้วยกัน ซึ่งทำให้การแก้ไขทำได้ยากขึ้น ไม่ว่าจะเป็นการที่คุณต้องเสียเวลาไล่ตามแก้ทุกส่วนที่เกี่ยวข้องกัน หรือต้องมานั่งสงสัยว่าทำไมพอแก้ "แค่ที่เดียว" แล้วที่อื่นถึงพังตามไปด้วย
เวลาที่คุณออกแบบสิ่งที่ต้องการความแข็งแรง เช่น สะพานหรือหอคอย คุณต้องเชื่อมส่วนประกอบต่างๆ เข้าด้วยกัน:
ตัวเชื่อมเหล่านี้ทำงานร่วมกันเพื่อให้โครงสร้างมันแข็งแรง
ลองมาเปรียบเทียบกับอะไรแบบนี้ดู:
ที่นี่ไม่มีความแข็งเกร็งเชิงโครงสร้าง: ตัวเชื่อมแต่ละตัวสามารถเปลี่ยนได้ โดยที่ตัวอื่นๆ ก็แค่ปรับตัวตาม
เวลาคุณออกแบบสะพาน คุณต้องการให้มันคงรูปเดิมไว้ คุณต้องการให้มันแข็งแรง (Rigid) แต่เวลาคุณออกแบบซอฟต์แวร์ที่คุณรู้ว่าจะต้องเปลี่ยนในอนาคต คุณต้องการสิ่งที่ตรงกันข้ามเลย นั่นคือคุณต้องการความยืดหยุ่น (Flexible) และเพื่อที่จะให้มันยืดหยุ่นได้ แต่ละคอมโพเนนต์ควรจะเชื่อมต่อ (Couple) กับคอมโพเนนต์อื่นๆ ให้น้อยที่สุดเท่าที่จะเป็นไปได้
และที่แย่ไปกว่านั้น Coupling มันมีสมบัติการถ่ายทอด (Transitive): ถ้า A เชื่อมกับ B และ C, แล้ว B เชื่อมกับ M และ N, และ C เชื่อมกับ X และ Y, นั่นหมายความว่าจริงๆ แล้ว A เชื่อมอยู่กับทั้ง B, C, M, N, X และ Y เลย
ซึ่งนั่นหมายความว่านี่คือหลักการง่ายๆ ที่คุณควรทำตาม:
| Tip 44 | Decoupled Code Is Easier to Change |
|---|
ในเมื่อปกติเราไม่ได้เขียนโค้ดด้วยคานเหล็กและหมุดย้ำ แล้วคำว่า Decouple โค้ดมันแปลว่าอะไรล่ะ? ในหัวข้อนี้เราจะมาคุยกันเรื่อง:
- Train wrecks—การเรียกเมธอดต่อกันเป็นทอดๆ (Chains of method calls)
- Globalization—อันตรายจากสิ่งที่พึ่งพาค่าคงที่ (Static things)
- Inheritance—ทำไมการสร้างซับคลาส (Subclassing) ถึงอันตราย
ลิสต์นี้อาจจะดูถูกสร้างขึ้นมาหน่อยๆ เพราะ Coupling สามารถเกิดขึ้นได้เกือบตลอดเวลาที่โค้ดสองส่วนแชร์อะไรบางอย่างร่วมกัน ดังนั้นในขณะที่คุณอ่านข้อความต่อไปนี้ ให้ลองสังเกตรูปแบบที่ซ่อนอยู่เพื่อนำไปประยุกต์ใช้กับโค้ดของคุณ และคอยสังเกตอาการของ Coupling เหล่านี้ดู:
- การพึ่งพาอาศัยกัน (Dependencies) ที่แปลกประหลาดระหว่างโมดูลหรือไลบรารีที่ไม่ได้เกี่ยวข้องกันเลย
- การแก้ไข "ง่ายๆ" ในโมดูลเดียวแต่ส่งผลกระทบไปทั่วระบบในโมดูลอื่นๆ ที่ไม่เกี่ยวข้องกัน หรือทำให้ที่อื่นพังเฉย
- นักพัฒนาที่กลัวการแก้โค้ด เพราะไม่แน่ใจว่าจะส่งผลกระทบอะไรบ้าง
- การประชุมที่ทุกคนต้องเข้า เพราะไม่มีใครแน่ใจว่าการเปลี่ยนแปลงนี้จะส่งผลกระทบถึงใครบ้าง