Se lo scopo di una singola LOC complicata è chiaro, ti preoccuperesti di dividerlo su più righe per rendere chiaro anche il suo metodo?

4

Data una linea di codice (relativamente) complicata, sarei spesso incline a dividerlo su più righe per rendere la sua funzione / scopo chiara agli altri.

Tuttavia, se è abbastanza chiaro dal contesto cosa fa una linea , faresti comunque la stessa cosa solo per rendere più chiaro come lo fa ? O prenderesti l'atteggiamento che i futuri sviluppatori probabilmente non sanno / cura come funziona, solo che funziona?

Per alcuni contesti, la particolare linea a cui viene posta questa domanda è il codice Python che accetta una stringa come "1.title" e la usa per modificare self.data[1].title :

#IRL, these 2 values are already set somehow
id = "1.title"
val = "foo"

setattr(self.data[int(id[:id.index(".")])], id[id.index(".")+1:], val)

L'ultima riga non è la cosa più bella del mondo da leggere, quindi stavo pensando di dividerlo in:

index = int(id[:id.index(".")])
attrib = id[id.index(".")+1:]
setattr(self.data[index], attrib, val)

Se volevi impazzire, potresti persino fare dotLocation = id.index(".") prima, e usarlo nelle impostazioni di index e attrib .

Questo è probabilmente un po 'più chiaro a qualcun altro che lo legge per la prima volta, ma preferisco che sia bello e conciso su una riga, ed è altamente improbabile che qualcuno abbia bisogno di modificare questa funzione di utilità a una riga. C'è davvero molto motivo per dividerlo così?

(Nota: sono pienamente consapevole che questa non è esattamente la vita o la morte. Non ho intenzione di perdere il sonno su di esso, mi sto solo chiedendo cosa avrebbero fatto gli altri in questo tipo di situazione. )

(L'ultima cosa: qualcuno potrebbe voler aggiungere tag migliori a questo, è la mia prima domanda Programmers :))

    
posta Cam Jackson 14.09.2011 - 03:50
fonte

4 risposte

14

In questo caso, big fat YES .

I motivi:

  • La linea originale viola effettivamente DRY - su una scala micro, ma immobile. Stai eseguendo lo stesso calcolo due volte; il factoring elimina una potenziale fonte di bug
  • Hai un livello di nidificazione di parentesi pari a 5, che è decisamente troppo. 3 è profondo quanto sarei disposto a leggere senza interruzioni di riga e rientranza per aiutarmi

Mi piacerebbe fare un ulteriore passo avanti e separare le preoccupazioni un po 'di più, definendo la "divisione al primo evento del carattere specificato" in una funzione a sé stante, quindi si ridurrebbe a qualcosa del tipo:

def split_at_char(s, c):
    charIndex = s.index(c)
    left = s[:charIndex]
    right = s[charIndex + 1:]
    return left, right

... e poi, usandolo:

indexStr, attrName = split_at_char(id, '.')
index = int(indexStr)
setattr(self.data[attrName], index, val)

In effetti, esiste una funzione Python esistente che fa esattamente ciò che split_at_char fa: link Non c'è bisogno di reinventare nessuna ruota qui. Quindi:

indexStr, attrName = id.split('.', 2)
index = int(indexStr)
setattr(self.data[index], attrName, val)

Il test finale è: può qualcuno che non ha familiarità con il codebase leggere fluentemente il codice senza dover rileggere nulla? Altrimenti, le parti che ti fanno inciampare hanno bisogno di più lavoro.

    
risposta data 14.09.2011 - 07:38
fonte
5

Le istruzioni a riga singola vanno bene, quando possono essere lette linearmente, ad esempio:

[r.name for r in rows].sort.splitIntoColumns(2)

La trovo la tua:

setattr(self.data[int(id[:id.index(".")])], id[id.index(".")+1:], val)

non è chiaro. La ripetizione di id.index(".") interrompe il flusso di lettura, ed è un po 'troppo basso per me. Perché non hai usato split?

 index, name = id.split(".")
 setattr(self.data[int(index)], name, val)

Questo è solo leggermente più lungo, ma mi sembra abbastanza chiaro.

    
risposta data 15.09.2011 - 15:24
fonte
1

Sembra bello avere cose concise. Tuttavia, guarda le seguenti caratteristiche della suddivisione, specialmente quando la tua linea è composta da funzioni logiche separate.

  1. Semplice da leggere e gestire dagli altri

  2. Più facile catturare errori sulle singole parti logiche piuttosto che sull'intera espressione (nel tuo esempio, index e attrib sono parti logicamente separate) - Puoi testare separatamente il risultato di ogni parte

  3. In un sistema con decine di migliaia di righe di codice, che differenza farebbe se ne aggiungessimo altre?

Una domanda alquanto simile è stata posta su: Formattazione del Math "complesso"

Modifica: Non posso dire che la decomposizione sia sempre la strada giusta. Se l'espressione è ovvia e non stai identificando in quale parte fallisce, crea tutto in una riga.

    
risposta data 14.09.2011 - 04:09
fonte
1

A volte baso decisioni come questa sulla facilità di eseguire il debug delle istruzioni come linee separate. Ogni tanto, durante il debug, una singola riga di codice sovraccaricata diventa un impedimento perché oscura i risultati intermedi.

    
risposta data 15.09.2011 - 16:31
fonte

Leggi altre domande sui tag