โค้ด Python ที่จับคู่อย่างหลวมๆ กับ Dependency Injection

Jan 13 2023
ซอฟต์แวร์ต้องมีความยืดหยุ่นเพื่อตอบสนองต่อการเปลี่ยนแปลง การพึ่งพาอาศัยเป็นเทคนิคในการจัดการการพึ่งพาระหว่างส่วนประกอบซอฟต์แวร์

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

การพึ่งพาการฉีดใน Python

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

การสร้างนามธรรมด้วยส่วนต่อประสาน

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

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

อินเทอร์เฟซสำหรับตัวเข้ารหัสและตัวถอดรหัส

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

คลาสคอนกรีต PaddedPacketEncoder

การใช้การฉีดพึ่งพา

ฟังก์ชัน นี้encode_nameเป็นการใช้งานอย่างง่ายสำหรับการสร้างเพย์โหลดที่เข้ารหัสด้วยชื่อที่ระบุ ใช้IPacketEncoderวัตถุและสตริงเป็นพารามิเตอร์

อินสแตนซ์ PaddedPacketEncoder ส่งผ่านไปยังฟังก์ชัน encode_name

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

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

คลาสคอนกรีต NullTerminatedPacketEncoder

NullTerminatedPacketEncoderโดยพื้นฐานแล้วจะเพิ่มNULL_BYTEหลังจากแต่ละสตริงที่เข้ารหัส กลับไปที่encode_nameฟังก์ชัน อินสแตนซ์ของNullTerminatedPacketEncoderเป็นอาร์กิวเมนต์ตัวเข้ารหัสที่ถูกต้องเนื่องจากNullTerminatedPacketEncoderใช้IPacketEncoderอินเทอร์เฟซคล้ายPaddedPacketEncoderกับ

NullTerminatedPacketEncoder ส่งผ่านไปยังฟังก์ชัน encode_name

หากไม่ได้ใช้การพึ่งพาอาศัยกันที่นี่ อาจส่งผลให้โค้ดเชื่อมโยงแน่นและเปลี่ยนแปลงได้ยาก เช่น

การเข้ารหัสรหัส Python ควบคู่กัน

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

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

SocketService ใช้การฉีดขึ้นต่อกัน

เมื่อโครงการเติบโตอย่างต่อเนื่อง ขอแนะนำให้ใช้เฟรมเวิร์ กการพึ่งพาการพึ่งพาเพื่อ "ฉีด" การพึ่งพาเหล่านี้โดยอัตโนมัติ เช่นการพึ่งพาการแทรก

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

ขอบคุณที่อ่านค่ะ หากคุณต้องการเชื่อมต่อกับฉัน คุณสามารถค้นหาฉันได้ที่LinkedinหรือGithub