L'interruzione di una funzione in più piccoli è grande ... tranne per quanto riguarda il code-folding? [duplicare]

1

Attualmente sto leggendo il libro del codice pulito di Robert Martin. Finora mi sto divertendo.

Martin parla molto della separazione delle funzioni lunghe in funzioni brevi, ognuna delle quali fa esattamente una cosa ad un livello di astrazione.

In generale mi piace l'idea e capisco il concetto e i vantaggi. Ma ho una semplice domanda da porre:

Come si sta prendendo un pezzo logico di codice estraendolo a un nuovo metodo, diverso dal semplice "piegarlo"? Gli IDE più moderni sono dotati della funzione di piegatura del codice.

Il vantaggio del code-folding è che quando devi guardare quel pezzo logico di codice, non devi scorrere su e giù per trovarlo. Basta premere un pulsante ed è proprio lì davanti a te, nel suo posto lineare.

Estrarre piccoli pezzi logici di codice in nuovi metodi, significa che quando un programmatore vuole esaminare il metodo che hai estratto, di solito deve andare a scorrere su e giù per la pagina. È molto fastidioso e rende più difficile concentrarsi.

Sono d'accordo con la maggior parte di ciò che Zio Bob scrive nel suo libro, e voglio davvero essere d'accordo con questo punto. Ma con il code-folding di una parte dei più moderni IDE, non riesco a trovare una vera ragione per questa idea.

Spiega i vantaggi dell'estrazione di piccoli pezzi logici di codice in nuovi metodi, invece di limitarli semplicemente al codice.

(Ricordo che c'era un'altra domanda su questo sito, ma era meno focalizzata e le risposte non mi soddisfacevano)

    
posta Aviv Cohn 18.09.2014 - 15:43
fonte

5 risposte

10

La piegatura del codice non dice nulla sull'oscilloscopio. Se hai una funzione di 2000 righe 1 che si piega bene in 200 blocchi di 10 righe, non sai ancora quale tipo di dipendenze potrebbero avere quei blocchi tra loro.

Se si calcola tale funzione in tante piccole funzioni secondarie (anche se ciascuna funzione secondaria viene utilizzata una sola volta), è possibile vedere a colpo d'occhio quali variabili vengono utilizzate dove, quali dipendenze sono, quali possono essere facilmente modificate, ecc. .

In breve, è molto più semplice pensare a piccole funzioni in cui è possibile vedere le dipendenze piuttosto che pensare a un blocco di codice apparentemente piccolo che può dipendere da MOLTE variabili definite centinaia di linee di distanza.

1: sì, sto esagerando per fare un punto

    
risposta data 18.09.2014 - 16:08
fonte
5

Il punto di avere metodi più piccoli non è quello di risparmiare lo sforzo di scorrimento. Il punto è essere in grado di astrarre completamente da ciò che fa un blocco di codice, perché ciò rende più facile ragionare sulla routine sovraordinata. (E per favorire il riutilizzo di quel piccolo blocco, ma qui sto parlando dell'aiuto al ragionamento.)

Se senti la necessità di controllare cosa veramente è che il metodo di factoring-out, allora il refactoring ha fallito. Il nome del metodo refactored dovrebbe dirti tutto che devi conoscere; se c'è il dubbio, allora non siamo riusciti a ottenere l'effetto che volevamo.

    
risposta data 18.09.2014 - 15:54
fonte
1

Durante la lettura delle risposte e dei commenti a questa domanda, e anche mentre discuto con qualcuno su questo argomento, ora posso vedere due chiari vantaggi dell'estrazione del metodo rispetto alla piegatura del codice:

1- Come @DanPichelman e @Doval hanno detto, se hai una funzione lunga 200 righe con molti blocchi piegati, non hai modo di vedere quali sono le dipendenze tra di loro. Possono avere molte dipendenze ingarbugliate.

Le funzioni, tuttavia, definiscono in-parametri e valori di ritorno espliciti, rendendo così più esplicite le dipendenze tra le funzioni. Le funzioni possono anche leggere i membri della classe e lo stato globale, ma poiché le funzioni sono piccole sarà visibile al programmatore.

Questo è il punto più importante.

2- Inoltre, poiché in ecnourages, creando metodi in cui ognuno fa una cosa, consente il riutilizzo del codice in futuro. In questo momento potresti rendere privato quel nuovo metodo, ma in seguito potresti aver bisogno di questa funzionalità da qualche altra parte, quindi potresti estrarre questo metodo da una classe di utilità condivisa o qualcosa del genere. Questo sarebbe facile se si tratta di un metodo estratto e molto più pericoloso se si tratta di un blocco piegato: ancora una volta, a causa delle dipendenze implicite tra i blocchi.

Grazie per avermi aiutato a capire

    
risposta data 18.09.2014 - 16:13
fonte
0

Oltre alle altre risposte, una parola: ASCIUTTA. Con un metodo a lungo piegato, non c'è modo di vedere facilmente se una correzione che devi fare in un posto deve anche essere fatta altrove - forse molte volte - a parte il dispiegamento del lotto e il guadare attraverso di esso. I programmatori di manutenzione apprezzeranno se il codice è strutturato in modo tale da poter essere sicuri di dover apportare una modifica solo una volta.

    
risposta data 18.09.2014 - 16:22
fonte
0

Ci sono due ragioni principali per inserire il codice in più funzioni:

  • Astrazione / Encapsulation
  • Riusabilità

La riusabilità è ovviamente la più semplice da spiegare. Se ho una funzione:

int do_QWERTYalgo(int data1, int data2)
{ /*do stuff*/ }

Quindi ovviamente, se ho bisogno di fare quel workagain, posso semplicemente chiamare la funzione da altrove, e "tada!" è fatta, e non ho bisogno di scriverlo ancora una volta .

Naturalmente lo sai, ma hai pensato di implementare un programma in cui devi farlo più volte con diversi passaggi intermedi?

//...
a1 = 5;
a2 = 7;
a = do_QWERTYalgo (a1, a2);
b1 = a;
b2 = 8;
b = do_QWERTYalgo (b1, b2);
c = do_QWERTYalgo (a, b);

All'improvviso, abbiamo ridotto molto la quantità di codice che dobbiamo scrivere.
Inoltre, se do_QWERTYalgo è stato implementato in modo errato, ora dobbiamo solo cambiarlo in un'unica posizione, il che ci porta piacevolmente al nostro altro punto:

do_QWERTYalgo è astratto e incapsulato dal resto del codice.
L'algoritmo che si trova sopra non ha bisogno di per sapere come funziona l'algoritmo do_QWERTYalgo , semplicemente inserisce gli input e riceve l'output.
Inoltre, se è necessario modificare do_QWERTYalgo , purché gli input e gli output non cambino, non è necessario modificare nient'altro nel codice.

Per spiegare come questo è pensato per aiutarti: diciamo che stai usando una libreria per fornire comunicazioni crittografate tra te e un amico. Improvvisamente, ci sono notizie che il metodo di crittografia utilizzato è estremamente vulnerabile a un nuovo tipo di hack. All'improvviso, c'è un problema con il tuo programma di chat. cosa fai? Bene, prendi una versione aggiornata della libreria. Fatto. Potrebbero esserci decine di posizioni nel codice in cui si utilizzano le funzionalità fornite dalla libreria, ma poiché le funzioni di crittografia non sono incorporate nel codice dell'applicazione, non è necessario cercare ogni singolo utilizzo e modificarlo manualmente.

Un altro modo di pensare a questo: la funzione che stai scrivendo è una persona. Detto utente vuole guidare da A a B . Quindi la persona entra in car e inserisce l'input in car tramite i metodi push_pedals e turn_wheel . Con gli input corretti, la persona arriva dove vuole andare.
Scrivere tutto il codice in un unico grande metodo è come convincere la tua persona ad implementare la funzionalità fuel_injection , la funzionalità ignite_fuel , le funzionalità gearbox e clutch , la funzionalità turn_wheels_on_road_when_steering_wheel_turned , push_pedals , accellerate , brake funzionalità, mentre anche dovendo guidare l'auto ...
tutto continua ancora come prima, ma c'è ancora molto lavoro da fare.

Tutto il codice di piegatura fa nasconderne alcuni dalla tua vista, non è meglio che dare al tuo navigatore una benda sugli occhi.

    
risposta data 18.09.2014 - 16:35
fonte

Leggi altre domande sui tag