È ** kwargs un antipattern?

14

Abbiamo un sacco di codice nella nostra base di codice interna che chiama internamente le nostre librerie - queste librerie hanno spesso molti argomenti (pensate a matplotlib) e il nostro codice spesso fa solo un compito specifico e passa semplicemente il **kwargs a la prossima funzione chiamata.

per esempio:.

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

Mentre **kwargs ci impedisce di ripetere tutti i parametri nella nostra dichiarazione di metodo, rende anche opaco quali argomenti sono validi quando si chiama our_method - Devo sapere quale metodo viene chiamato, che spesso non voglio sapere.

Che ne pensi di questo?

    
posta Christian Sauer 22.08.2015 - 09:53
fonte

2 risposte

15

Come viene utilizzato il codice dagli sviluppatori? In altre parole, cosa fanno esattamente per determinare quali argomenti dovrebbero essere utilizzati e in che modo?

  • Se si basano sulla documentazione generata automaticamente dal tuo codice e il generatore non ha idea di cosa fare con **kwargs , questo è davvero problematico. Invece di trovare la lista di argomenti e il loro significato nella documentazione, non hanno assolutamente nessuna informazione tranne il vago "ci vogliono alcuni argomenti".

    Questo problema potrebbe probabilmente essere risolto documentando il metodo manualmente, sostituendo automaticamente la documentazione generata. Ciò richiede un lavoro extra dall'implementatore del metodo, ma ricorda che il codice (e la sua documentazione) viene letto molto più frequentemente di quanto non sia scritto.

  • Se il codice è la loro documentazione, gli sviluppatori che usano il metodo con **kwargs necessitano di due passaggi aggiuntivi: hanno bisogno non solo di guardare la firma del metodo, ma anche della sua effettiva implementazione, al fine di trovare l'altro metodo in effetti chiama. Poi, hanno bisogno di andare a questo altro metodo per trovare finalmente quello che stavano cercando.

    Questo non richiede molto sforzo, ma comunque, lo sforzo dovrebbe essere ripetuto, ancora e ancora. La parte peggiore è che non è possibile aiutarli aggiungendo la documentazione: se si commenta il metodo, elencando gli argomenti effettivi, c'è un grosso rischio che la prossima versione della libreria chiamata dal metodo abbia argomenti diversi e la documentazione essere obsoleto, poiché nessuno ricorderà che deve essere tenuto aggiornato.

La mia raccomandazione è di fare affidamento su **kwargs solo per metodi che hanno un ambito ridotto. Metodi privati (e da privato in un contesto di Python, intendo i metodi che iniziano con _ ) che sono usati in pochi posti nella classe sono buoni candidati, per esempio. D'altra parte, i metodi usati da dozzine di classi su tutto il codice sono candidati molto cattivi.

Dopotutto, non dovrebbe essere necessario troppo tempo per riscrivere gli argomenti di un metodo che chiamate all'interno del metodo che scrivete. Si spera che la maggior parte dei metodi non richieda più di 6-8 argomenti, e se lo fanno, chiediti se non dovresti refactoring del codice. In tutti i casi:

  • Rendere gli argomenti espliciti all'interno del tuo metodo non richiede molto sforzo,

  • Puoi, in seguito, convalidare comunque gli argomenti (anche se se fai affidamento solo su questo punto per rendere espliciti gli argomenti, violerai YAGNI).

risposta data 24.08.2015 - 21:55
fonte
3

Se la funzione di livello successivo ha un __doc__, puoi semplicemente copiare __doc__ nella tua nuova funzione.

Ad esempio:

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

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

b.__doc__=a.__doc__

Questo potrebbe applicarsi in modo ricorsivo e potrebbe essere applicato da un decoratore (che potrebbe essere utile se lo stai facendo contemporaneamente). Anche la stringa __doc__ può essere manipolata per aggiungere altro alla fine. Ciò significa che i parametri mostrati sarebbero ancora kwargs, ma almeno c'è documentazione nella guida che descrive i parametri attuali.

    
risposta data 22.04.2016 - 00:55
fonte

Leggi altre domande sui tag