Apakah ** kwargs adalah antipattern?

15

Kami memiliki banyak kode dalam basis kode internal kami yang memanggil perpustakaan kami secara internal - perpustakaan ini sering memiliki banyak argumen (pikirkan matplotlib) dan kode kami sering melakukan hanya tugas tertentu dan hanya meneruskan **kwargske fungsi berikutnya yang disebut.

Misalnya:

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

Sementara **kwargsmencegah kita mengulangi semua parameter dalam deklarasi metode kami, itu juga membuatnya sangat buram argumen mana yang valid saat memanggil our_method- saya harus tahu metode mana yang dipanggil, yang sering saya tidak ingin tahu.

Apa pendapat Anda tentang hal ini?

Sauer Kristen
sumber

Jawaban:

15

Bagaimana kode Anda digunakan oleh pengembang? Dengan kata lain, apa yang sebenarnya mereka lakukan untuk menentukan argumen mana yang harus digunakan dan bagaimana?

  • Jika mereka bergantung pada dokumentasi yang dihasilkan secara otomatis dari kode Anda, dan generator tidak tahu apa yang harus dilakukan **kwargs, ini memang bermasalah. Alih-alih menemukan daftar argumen dan maknanya dalam dokumentasi, mereka sama sekali tidak memiliki informasi kecuali samar-samar "dibutuhkan beberapa argumen".

    Masalah ini mungkin dapat diselesaikan dengan mendokumentasikan metode secara manual, menggantikan dokumentasi yang dihasilkan secara otomatis. Ini membutuhkan kerja ekstra dari pelaksana metode ini, tetapi ingat, kode (dan dokumentasinya) dibaca lebih sering daripada yang tertulis.

  • Jika kode adalah dokumentasinya, pengembang yang menggunakan metode ini **kwargsperlu dua langkah tambahan: mereka tidak hanya perlu melihat tanda tangan metode tersebut, tetapi juga pada implementasinya yang sebenarnya, untuk menemukan metode lain yang sebenarnya ia panggil. Kemudian, mereka perlu pergi ke metode lain ini untuk akhirnya menemukan apa yang mereka cari.

    Ini tidak melibatkan banyak upaya, tetapi tetap saja, upaya itu harus diulang, lagi dan lagi. Bagian terburuknya adalah Anda tidak dapat membantu mereka dengan menambahkan dokumentasi: jika Anda mengomentari metode Anda, mendaftar argumen yang sebenarnya, ada risiko besar bahwa versi pustaka panggilan metode berikutnya akan memiliki argumen yang berbeda, dan dokumentasi Anda akan sudah ketinggalan zaman, karena tidak ada yang akan ingat bahwa itu harus tetap up to date.

Rekomendasi saya adalah **kwargshanya mengandalkan metode yang cakupannya berkurang. Metode pribadi (dan secara pribadi dalam konteks Python, maksud saya metode yang dimulai dengan _) yang digunakan di beberapa tempat di kelas adalah kandidat yang baik, misalnya. Di sisi lain, metode yang digunakan oleh banyak kelas di seluruh basis kode adalah kandidat yang sangat buruk.

Lagi pula, tidak perlu terlalu banyak upaya untuk menulis ulang argumen metode yang Anda panggil dalam metode yang Anda tulis. Mudah-mudahan, sebagian besar metode tidak memerlukan lebih dari enam hingga delapan argumen, dan jika itu benar, tanyakan pada diri Anda apakah Anda tidak boleh membuat ulang kode. Dalam semua kasus:

  • Membuat argumen secara eksplisit dalam metode Anda tidak membutuhkan banyak usaha,

  • Anda mungkin ingin, kemudian, untuk memvalidasi argumen (walaupun jika Anda hanya mengandalkan pada titik ini untuk membuat argumen eksplisit, Anda melanggar YAGNI).

Arseni Mourzenko
sumber
Saya sangat suka jawaban ini dan berpikir ini adalah jawaban yang bagus. Sayangnya, banyak kode kami memiliki banyak metode publik menggunakan pola ini. Tapi sekarang saya punya argumen bahwa kita harus mengubahnya (dan drop matplotlib, tidak pernah melihat "antarmuka" crappier ..)
Christian Sauer
3

Jika fungsi level selanjutnya memiliki __doc__, maka Anda bisa menyalin __doc__ ke fungsi baru Anda.

Sebagai contoh:

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

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

b.__doc__=a.__doc__

Ini dapat diterapkan secara rekursif, dan dapat diterapkan oleh dekorator (yang mungkin berguna jika Anda melakukan ini dalam jumlah besar). String __doc__ juga dapat dimanipulasi, untuk menambahkan lebih banyak ke bagian akhir. Ini berarti parameter yang ditampilkan masih berupa kwarg, tetapi setidaknya ada dokumentasi dalam bantuan yang menjelaskan parameter aktual.

AMADANON Inc.
sumber