Design appropriato per la funzione che fa un solo lavoro ma comporta molte piccole attività

0

Ho una classe in Python che la sua unica responsabilità è ricevere testo, un percorso del carattere, dimensione massima del carattere e dimensione minima del carattere e stampare il testo su un'immagine se si adatta.

Ho una funzione chiamata word_wrap() e fa la seguente:

  1. dichiara le variabili ( text , font )
  2. dividi il testo in linee se trova%% di caratteri% di caratteri
  3. dividi ogni riga in parole e ottieni la dimensione del font (larghezza, altezza) per ogni parola e calcola se \n ... Scommetto che capisci cosa fa se restituisce total_width_of_words + width_of_current_word > width_image o False . : -)
  4. Ora abbiamo un elenco di elenchi del modulo: True e ogni elenco interno è una frase che si adatta nella [['hello', 'world'], ['I', 'am', 'posting', 'on', 'programmers.se']] dell'immagine che stamperemo il testo in . : -)
  5. Moltiplicare width x number_of_sentences delle frasi per vedere se tutte le frasi si adattano all'altezza dell'immagine. Se non funziona la funzione restituisce False ... se si adatta, la funzione restituisce un oggetto font.

average_height è chiamato da una funzione chiamata word_wrap() e se il testo non si adatta all'immagine la prima volta bisect() chiama bisect() ancora una volta con una dimensione del carattere più piccola, ecc. ecc.

Dovrebbe essere ri-fattorizzato word_wrap() in funzioni più piccole? In questo caso, hai qualche suggerimento su come sarebbe la struttura?

Sono davvero aperto al feedback, ogni aiuto sarebbe molto apprezzato.

    
posta gglasses 11.04.2016 - 21:35
fonte

2 risposte

1

Prenderò per scontato che la tua funzione bisect() sia un metodo della classe che hai menzionato e che assomigli a questo:

def bisect()
    while self.word_wrap() == False:
        pass

Per quanto riguarda il metodo word_wrap() , proporrei di suddividerlo in metodi più piccoli perché i metodi più piccoli sono:

1. Più semplice da testare

Immagina di scrivere un test unitario per il tuo metodo word_wrap() . Dovrai testare se:

  • il testo è suddiviso correttamente in righe
  • le righe sono suddivise in parole correttamente
  • il controllo della lunghezza della linea funziona davvero per ogni tipo di input (ad esempio, una riga senza parole su di esso)
  • il calcolo dell'altezza funziona come previsto
  • l'oggetto font restituito ha le proprietà e i valori corretti

Scrivere un test unitario per quest'ultimo punto non è certamente un problema. Tuttavia, il resto del metodo è opaco a qualsiasi chiamante (inclusi i test di unità), ovvero non può essere (unità) testato a fondo . La rottura di tutti questi punti elenco nei loro metodi distinti ti consentirà di testarli.

2. Più facile da leggere

Alcune o anche tutte le attività eseguite richiedono le proprie variabili, la propria logica e i propri commenti, che devono essere scansionati e "organizzati" da un lettore.

2.a. Più facile da capire

Dalla mia esperienza, più di 3 o 4 variabili in una funzione porteranno il lettore a cercarle di nuovo durante la lettura del resto del metodo, indipendentemente da quanto semplici fossero le variabili in primo luogo. Non sto dicendo che non dovresti mai usare più di 3 o 4 variabili in un metodo, ma ti consiglio di provare ad evitarlo. Avere più metodi consente al lettore di ignorare tutte le variabili necessarie per svolgere un'attività più piccola e invece vedere le attività più piccole come un metodo che restituisce un risultato, non di più, non di meno. Questo 'libera' su capacità intellettuali che altrimenti verrebbero utilizzate per ricordare cosa una determinata variabile ha e se sarà ancora usata altrove in una funzione.

... the span of absolute judgment and the span of immediate memory impose severe limitations on the amount of information that we are able to receive, process, and remember. By organizing the stimulus input simultaneously into several dimensions and successively into a sequence of chunks, we manage to break (or at least stretch) this informational bottleneck. http://psychclassics.yorku.ca/Miller/

2.b. Più facile il debug

Un bug che può essere facilmente compreso è anche molto più facile da eseguire il debug, semplicemente perché è facile definire cosa esattamente non funzioni. È la stessa cosa che distingue una buona segnalazione di bug ("Firefox si blocca all'apertura del file SVG su Win10, registri allegati") da una cattiva ("Firefox si blocca all'apertura del file") o una buona domanda SO ("JS: Eccezione non rilevata: impossibile chiamare il metodo foo della barra ") da una cattiva (" il mio sito web non funziona, si prega di risolvere ").

2.c. Più facile da riutilizzare

A volte in futuro potresti dover risolvere un problema simile a quello che stai risolvendo ora, ad esempio se hai bisogno di adattare il testo a una forma geometrica arbitraria anziché solo un'immagine (o un rettangolo, in realtà). Molte delle attività più piccole, come la suddivisione del testo in linee e parole, la misurazione della dimensione della parola e le parole di adattamento in una forma dovranno essere nuovamente utilizzate per implementare la nuova funzione. Invece di dover rifattorizzare queste attività più piccole con un solo metodo, perché non dividerle nei loro stessi metodi adesso?

Infine, immagina quanto di questa risposta avresti già dimenticato se fosse stato scritto senza alcuna formattazione o punti elenco.

    
risposta data 11.04.2016 - 23:35
fonte
0

TL; DR: dipende. La funzione è mantenibile così com'è? Hai altri casi d'uso per le funzioni dei componenti?

Ci sono 2 cose che tipicamente guidano la scomposizione di una funzione in funzioni componente.

  1. Avere una necessità specifica per la sola funzione componente.
  2. Rendere il codice più mantenibile .

Il motivo 1. è piuttosto semplice. O hai questo bisogno e sai che non lo fai. Quindi ci concentreremo su 2.

Ci sono ragioni e il codice può essere più o meno mantenibile. Ciò dipende principalmente da quanto tempo occorrerà a uno sviluppatore per comprendere il codice abbastanza da estendere in sicurezza la funzione o risolvere un problema.

La parte difficile è che, mentre ci sono alcuni esempi che sono chiaramente costosi (una singola funzione che è lunga 5 pagine) sono quelli facili da riconoscere. I duri sono quelli che sembrano un po 'troppo grandi o un po' troppo complicati, ma non è chiaro. Le decisioni su come decomporsi sono spesso preferenze personali.

Tuttavia, in una squadra c'è un modo semplice per controllare. Chiedi a uno dei tuoi compagni di leggere il codice. Se capisce cosa sta succedendo rapidamente e facilmente, allora probabilmente stai bene. Se si sforza di capire cosa è inteso, o cosa sta succedendo, decomponi o aggiungi commenti.

    
risposta data 12.04.2016 - 18:05
fonte

Leggi altre domande sui tag