** kwargs antipattern หรือไม่


16

เรามีรหัสจำนวนมากใน codebase ภายในของเราที่เรียกว่าห้องสมุดของเราภายใน - ห้องสมุดเหล่านี้มักจะมีข้อโต้แย้งมากมาย (คิดว่า matplotlib) และรหัสของเรามักจะทำเพียงงานที่เฉพาะเจาะจงและส่ง**kwargsต่อไปยังฟังก์ชันถัดไปที่เรียกว่า

เช่น:

def our_method(dataframe, **kwargs):
    result = do_something_with_data(dataframe)
    external_module.draw(result, **kwargs)

ในขณะที่**kwargsป้องกันไม่ให้เราทำซ้ำพารามิเตอร์ทั้งหมดในการประกาศวิธีการของเรามันยังทำให้มันทึบแสงมากซึ่งข้อโต้แย้งที่ถูกต้องเมื่อโทรour_method- ฉันต้องรู้ว่าวิธีการที่เรียกว่าซึ่งฉันมักจะไม่ต้องการที่จะรู้

คุณใช้อะไรกับเรื่องนี้?

คำตอบ:


16

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

  • หากพวกเขาพึ่งพาเอกสารที่สร้างขึ้นโดยอัตโนมัติจากรหัสของคุณและเครื่องกำเนิดไม่มีเงื่อนงำที่จะทำกับ**kwargsสิ่งนี้เป็นปัญหาแน่นอน แทนการหารายชื่อของการขัดแย้งและความหมายของพวกเขาอยู่ในเอกสารที่พวกเขาได้อย่างไม่มีข้อมูลยกเว้นคลุมเครือ“มันจะใช้เวลาบางข้อโต้แย้ง”

    ปัญหานี้อาจแก้ไขได้ด้วยการบันทึกวิธีด้วยตนเองแทนที่เอกสารที่สร้างขึ้นโดยอัตโนมัติ สิ่งนี้ต้องใช้งานพิเศษจากผู้ใช้วิธี แต่จำรหัส (และเอกสารประกอบ) ได้อ่านบ่อยกว่าที่เขียน

  • หากรหัสเป็นเอกสารของพวกเขานักพัฒนาที่ใช้วิธีการนั้น**kwargsต้องมีสองขั้นตอนเพิ่มเติม: พวกเขาไม่เพียง แต่ต้องดูที่ลายเซ็นของวิธีการ แต่ยังใช้งานจริงเพื่อหาวิธีอื่น ๆ ที่เรียกจริง จากนั้นพวกเขาต้องไปที่วิธีอื่นเพื่อหาสิ่งที่พวกเขากำลังมองหาในที่สุด

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

คำแนะนำของฉันคือการพึ่งพา**kwargsเฉพาะสำหรับวิธีการที่มีขอบเขตลดลง วิธีการส่วนตัว (และโดยส่วนตัวในบริบทของ Python ฉันหมายถึงวิธีการที่เริ่มต้นด้วย_) ซึ่งใช้ในบางสถานที่ในชั้นเรียนเป็นผู้สมัครที่ดีตัวอย่างเช่น ในทางกลับกันวิธีการที่ใช้โดยหลายสิบชั้นเรียนทั่วฐานรหัสเป็นผู้สมัครที่ไม่ดีมาก

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

  • การโต้แย้งอย่างชัดเจนภายในวิธีการของคุณไม่ต้องใช้ความพยายามมาก

  • คุณอาจต้องการตรวจสอบข้อโต้แย้งต่อไปในภายหลัง (แม้ว่าคุณจะใช้เฉพาะจุดนี้เพื่อสร้างข้อโต้แย้งที่ชัดเจนคุณละเมิด YAGNI)


ฉันชอบคำตอบนี้จริง ๆ และคิดว่านี่เป็นคำตอบที่ดี น่าเสียดายที่รหัสของเราจำนวนมากมีวิธีการสาธารณะมากมายที่ใช้รูปแบบนี้ แต่ตอนนี้ฉันมีข้อโต้แย้งว่าเราควรจะเปลี่ยนมัน (และวาง matplotlib ไม่เคยเห็น "อินเตอร์เฟซ" crappier .. .. )
คริสเตียนซาวเออร์

3

หากฟังก์ชันระดับถัดไปมี __doc__ คุณสามารถคัดลอก __doc__ ไปยังฟังก์ชันใหม่ของคุณได้

ตัวอย่างเช่น:

def a(x):
    """This function takes one parameter, x, and does nothing with it!"""
    pass

def b(**kwargs):
    a(**kwargs)

b.__doc__=a.__doc__

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.