Come evitare una grande funzione / esposizione dell'implementazione sottostante

5

Attualmente leggendo Clean Code , e gli autori sembrano implicare che qualsiasi funzione con un'arità maggiore di 3 dovrebbe essere evitata a tutti i costi.

Sfortunatamente sto incontrando un problema in cui mi trovo di fronte a un metodo di classe con un'arità di 4 (5 se conti self )

 def start_job(self, operation, name, external_id, format):
    ...

Tutti i parametri possono variare e sono necessari per iniziare il lavoro. Tuttavia, se penso all'incapsulamento di tutti quei parametri in una sorta di class

class Job(object):
    def __init__(self, operation, name, external_id, format):

ma poi tutti quei parametri sarebbero necessari per __init__ , e avrebbe ancora bisogno di esporre la struttura sottostante dell'oggetto alla funzione start_job . A questo punto, sembrerebbe anche un'invidia alle funzionalità e avrebbe senso cambiare la funzione start_job alla classe Job e chiamarla start .

Qualche idea su come evitare questo odore?

    
posta C.B. 08.10.2014 - 05:08
fonte

3 risposte

15

Questo non è realmente rispondibile senza conoscere il caso esatto che stai cercando di risolvere. Il motivo per cui li chiamano " odori di codice " non è dovuto al fatto che "l'odore" in sé è cattivo, ma piuttosto perché indica che lì c'è qualcos'altro che non va, una pila metaforica di cagate sotto la generazione di quell'odore.

Come tale, la risposta generalmente non è quella di attaccare direttamente l'odore stesso. Non è meglio che spruzzare la merda con lisol. La risposta è cercare di capire cosa nel design sottostante ti ha spinto ad usare un metodo con quattro parametri. Forse esaminare l'odore lo farà uscire, o forse deciderà che è stato solo un soffio di compost e forse non così male.

In questo caso, quattro parametri non sono molto puzzolenti. È quando raggiungi dieci o quindici anni che le cose puzzano in alto cielo.

Un modo per vedere se questo è un problema reale è guardare il codice all'interno della funzione. È un insieme di blocchi elif , in pratica una dichiarazione di un caso controllata da uno dei tuoi parametri? Se è così, forse il metodo dovrebbe essere suddiviso lungo quelle linee.

Stai passando lo stesso set di parametri a un insieme di metodi? Allora forse dovresti avere una classe che controlla quei valori con i membri per ciascuno dei metodi originali.

Alcuni parametri sono combinati in particolari modi all'interno del metodo per creare un singolo valore? Forse potrebbe essere tirato fuori dalla funzione. (Ad esempio, stai creando un nome file che assomiglia a name + '.' + extension dove extension dipende da format ?

Un parametro assume quasi sempre un valore particolare? Quindi impostalo come predefinito. Pur non riducendo "l'arità", riduce il carico cognitivo necessario per utilizzare la funzione.

    
risposta data 08.10.2014 - 06:03
fonte
7

Se tutti questi parametri sono sempre richiesti (mai opzionali), variano in modo indipendente, non hanno sottogruppi sensibili e hanno valori molto diversi, quindi sarà difficile fare meglio di quanto hai già fatto. Argomenti nominati possono rendere la lunga lista meno confusa da leggere.

Se non è esattamente il caso, ci possono essere margini di miglioramento. Chiediti:

Sono richiesti tutti i parametri o sono opzionali? Se facoltativo dovrebbero avere un valore predefinito. Crea attributi e utilizza una proprietà o setter per modificare il valore predefinito. Conserva solo quelli necessari in __init___ .

Qualcuno dei parametri è correlato? Se conosco due di loro posso fare qualcosa di utile? Se è così, crea un oggetto per loro che faccia questa cosa utile e vedi se può aiutarti a fare la tua cosa.

Se conosco uno di questi, posso sapere qual è l'altro? Se è così, probabilmente stai fornendo informazioni ridondanti. Scopri cosa puoi vivere senza.

Qualcuno dei parametri ha un numero limitato di stati? Per esempio ci sono solo 5 cose che funzionano? Forse 5 metodi sarebbero un'idea migliore, o anche 5 classi.

Ci sono molti schemi che possono aiutare con questo problema. I modelli di costruzione GoF, in particolare il costruttore e l'oggetto parametro. Potrebbe essere d'aiuto anche la versione pitone del costruttore di Josh Bloch. Che si tratti di 4 o 14 parametri, devi sempre cercare un modo per semplificare l'utilizzo del codice.

    
risposta data 08.10.2014 - 07:46
fonte
1

I membri di Job logicamente si uniscono in un oggetto? Sì. Cosa puoi fare con un lavoro? Avvia, fermalo, interroga il suo stato.

Sembra che tu abbia un oggetto in buona fede con i metodi di istanza start (), stop (), query ().

    
risposta data 08.10.2014 - 05:53
fonte

Leggi altre domande sui tag