A che punto è tabù avere loop all'interno di loop?

23

Solo curiosi. Il più che ho mai avuto è stato un ciclo for all'interno di un ciclo for, perché dopo aver letto questo da Linus Torvalds:

Tabs are 8 characters, and thus indentations are also 8 characters. There are heretic movements that try to make indentations 4 (or even 2!) characters deep, and that is akin to trying to define the value of PI to be 3.

Rationale: The whole idea behind indentation is to clearly define where a block of control starts and ends. Especially when you've been looking at your screen for 20 straight hours, you'll find it a lot easier to see how the indentation works if you have large indentations.

Now, some people will claim that having 8-character indentations makes the code move too far to the right, and makes it hard to read on a 80-character terminal screen. The answer to that is that if you need more than 3 levels of indentation, you're screwed anyway, and should fix your program.

link

Ho pensato che fosse una pratica inaccettabile per me andare a un terzo livello di loop e ristrutturare il mio codice (principalmente Qt).

Linus stava scherzando?

Dipende dalla lingua o dall'applicazione?

Ci sono alcune cose che richiedono assolutamente tre o più livelli di loop?

    
posta Akiva 23.12.2015 - 13:03
fonte

8 risposte

19

Il kernel preferisce strongmente algoritmi semplici

Mentre una varietà di algoritmi può richiedere cicli profondamente annidati all'interno di loop, nel contesto del kernel Linux (in cui è stata detta la citazione) in genere è necessario disporre di risposte rapide in tempo reale. In questo contesto, l'annidamento profondo è un odore che può indicare che il flusso di codice è troppo complesso per questo dominio e potrebbe dover essere modificato a causa delle sue caratteristiche di esecuzione, non di leggibilità o di rientro.

Inoltre, il kernel di Linux è diverso dalla maggior parte del codice applicativo per quanto riguarda i requisiti di controllo e verifica - e quindi preferirebbe non avere un algoritmo annidato a 4+ livelli in una singola funzione. Dovrebbe essere ovvio vedere quale frammento di codice esattamente e in dettaglio, inclusi tutti i possibili casi di flusso di controllo e di margini. Il codice profondamente annidato lo ostacola.

    
risposta data 23.12.2015 - 15:58
fonte
49

In un certo senso, ho smesso di prendere seriamente questa citazione su "Le schede sono 8 caratteri" . L'intero punto dei tabulatori è che non sono un numero fisso di caratteri (se mai, una scheda è un un carattere ). Che carico di tosh. Allo stesso modo, non sono completamente convinto che l'impostazione di una regola dura e veloce di "tre livelli di indentazione" sia sensata (tanto quanto impostare una regola dura e veloce per qualsiasi cosa è sensata) .

Tuttavia, limitare i livelli di indentazione è in generale un suggerimento ragionevole, e non uno che dovrebbe essere una sorpresa per te.

In definitiva, se il tuo programma ha bisogno di tre livelli di iterazione, è ciò di cui il tuo programma ha bisogno . Lo spirito della citazione non è quello di alleviare magicamente questo requisito dal tuo progetto, ma di rimuovere la logica in funzioni e tipi in modo che il tuo codice sia più teso e più espressivo.

Questo riporta semplicemente alla stessa linea guida sopra riportata per quanto riguarda i livelli di indentazione. Si tratta di come strutturare il codice e renderlo leggibile, gestibile e divertente da modificare negli anni a venire.

    
risposta data 23.12.2015 - 14:09
fonte
16

Il punto è lo stesso di qualsiasi costrutto di controllo del flusso: se il codice è difficile da comprendere, è necessario rifattorizzarlo. Se stai facendo una semplice manipolazione di un array multidimensionale, allora avere loop nidificati cinque o sei in profondità può essere appropriato, a patto che la logica nel ciclo più interno sia semplice. Tuttavia, se stai elaborando alcune complicate logiche di business e il corpo del tuo loop è una dozzina di righe o più, probabilmente non vorrai annidare più di un loop in profondità. Puoi provare a calcolare la complessità ciclomatica del codice, ma in realtà si tratta della leggibilità e della manutenibilità del codice in questione.

    
risposta data 23.12.2015 - 14:10
fonte
13

Was Linus joking?

Il pezzo è scritto in uno stile scherzoso che suggerisce che l'autore ha familiarità con il modo in cui lo stile di codifica è discusso tra i professionisti seri: tutti noi abbiamo le nostre preferenze e noi li difendiamo rabbiosamente, ma con la lingua almeno in parte in guancia. Capiamo perfettamente che gran parte di esso è solo una questione di gusto personale. Dice, in così tante parole, "Coding style is very personal, and I won't _force_ my views on anybody" - almeno al di fuori del codice che mantiene personalmente. Ma la coerenza dello stile in un determinato progetto è un'ottima idea. Preferirei molto codice per uno stile che non mi piace rispetto a gestire più stili in una determinata funzione.

Ecco un esempio di scrittura chiaramente giocosa:

However, there is one special case, namely functions: they have the
opening brace at the beginning of the next line, thus:

int function(int x)
{
    body of function
}

Heretic people all over the world have claimed that this inconsistency
is ...  well ...  inconsistent, but all right-thinking people know that
(a) K&R are _right_ and (b) K&R are right.  Besides, functions are
special anyway (you can't nest them in C).

Playful (1).

È discutibilmente un buon consiglio per cercare di evitare che il rientro sfugga al controllo, anche se un massimo di tre livelli potrebbe essere iperbolico. Non ho intenzione di usare la sorgente del kernel e contare le sequenze di quattro caratteri tab, ma scommetto che potresti trovare almeno uno che Torvalds ha scritto.

D'altra parte, se qualcuno può scrivere il kernel Linux senza spesso superare i tre livelli di rientro, un limite di tre livelli potrebbe essere un esercizio che vale la pena provare per un po 'nel proprio codice, solo per vedere dove ci vuole . Non è come un cambio di sesso, lo sai. Non è un impegno a vita.

Se incontri qualcuno su Internet che pensa di comprendere la programmazione molto meglio di Torvalds (2), beh, sai che tipo di persone piace parlare in grande su Internet.

D'altra parte, è criminalmente in errore riguardo alle schede a otto spazi. Questo è il delirio di un uomo che dovrebbe essere tenuto in freno e alimentato attraverso una fessura. Quattro spazi è ovviamente corretto.

(1) Ma nota come mette erroneamente uno spazio prima delle ellissi e due spazi dopo di loro, e due spazi dopo un punto. SBAGLIATO, SBAGLIATO, SBAGLIATO. E poi ha il coraggio sfacciato di castigare gli eretici. L'eretico sei tu, Torvalds! È TU!

(2) Se vuoi parlare di " capire come progettare un sistema di controllo del codice sorgente ", potrebbe esserci spazio per discussione.

Nota: caro utente che ha ripetutamente inviato la stessa modifica: la formattazione nel materiale quotato viene mantenuta esattamente come l'autore voleva che fosse. Questo perché proviene da un saggio sulla formattazione del testo a larghezza fissa, scritto in un testo a larghezza fissa, da qualcuno che ha dato la formattazione del testo a larghezza fissa una buona dose di pensiero. La formattazione è una parte cosciente e intenzionale dell'intento dell'autore ed è pertinente all'argomento.

Inoltre, ho fatto riferimento a quella formattazione nel mio stesso testo. Se si estrae la pre-formattazione, la mia nota in calce (1) diventa senza senso. Se la pre-formattazione viene rimossa, dovrebbe essere il testo nella mia nota a piè di pagina (1) che si riferisce alle coppie di spazi dopo i punti fermi alle estremità delle frasi. Riesco a vedere una motivazione per rimuovere comunque quella nota, perché è meno divertente di quello che sembrava quando l'ho scritto. Ma rimuovere la formattazione senza rimuovere la nota a piè di pagina non è utile.

    
risposta data 23.12.2015 - 18:45
fonte
9

Linus ha uno stile parlante molto schietto e un senso dell'umorismo asciutto, ma in questo caso non stava scherzando. Ci sono situazioni in cui un algoritmo ha bisogno di nidificare più a fondo di due livelli, ma puoi farlo usando altri mezzi rispetto all'indentazione del tuo codice. La guida allo stile del kernel Linux preferisce strongmente questi altri metodi, a causa della difficoltà di mantenere loop profondamente annidati, ed è quello che Linus sta dicendo qui.

Per alcuni esempi di metodi alternativi, puoi usare la ricorsione, scindere i loop interni nelle loro proprie funzioni o creare strutture di dati intermedi.

L'annidamento eccessivo è uno di quei casi che è più facile da scrivere, ma più difficile da leggere. Impostare una profondità di tabulazione di grandi dimensioni è il modo in cui Linus rende più noioso scrivere anche.

    
risposta data 23.12.2015 - 14:53
fonte
3

Ci sono molte domande in cui il consiglio è diverso per qualcuno che fa la domanda piuttosto che per qualcuno che non chiede. Se chiedi "Dovrei mai avere dei loop che sono annidati più di due livelli in profondità", allora per te, la persona che fa quella domanda, la risposta è NO. Se lo chiedi, allora non farlo. Se hai abbastanza esperienza che non hai bisogno di chiedere, allora sai qual è la risposta corretta in ogni caso. E non discutere se non sei d'accordo con la risposta, perché la risposta non è per te.

    
risposta data 23.12.2015 - 15:15
fonte
1

Questo sembrerebbe essere un caso da manuale della coda che scuote il cane.

Se hai un display di 80 caratteri allora ovviamente proverai a rendere il codice adatto al meglio anche se non produce la migliore struttura per il codice .

Affronta il resto dei tuoi punti in testa:

Ho pensato che fosse una pratica inaccettabile.

Penso che tu stia leggendo troppo in questo. Resisti all'impulso di prendere tutto ciò che leggi come vangelo senza comprendere adeguatamente il contesto.

Stava scherzando?

Difficile accertare il contesto, ma vedere il mio punto originale sopra.

Dipende dalla lingua o dall'applicazione?

Molto molto. Prendi qualsiasi linguaggio mainframe / midrange dove probabilmente stai codificando su un terminale (o emulatore di terminale).

Ci sono alcune cose che richiedono assolutamente tre o più livelli di loop?

Sì, è molto comune in alcuni algoritmi di forza bruta. Vedi Problema 31 su Project Euler. Questo è un classico esempio di un problema che potrebbe essere risolto con la forza bruta usando un numero di cicli (8 per la precisione).

    
risposta data 23.12.2015 - 14:34
fonte
0

Was Linus joking?

No, quelle sono le linee guida ufficiali.

Does it depend on the language or application?

Le linee guida di codifica dipendono generalmente dalla lingua e dall'applicazione, tuttavia il codice profondamente annidato sempre imposta il lettore.

Il problema con il codice annidato è che in generale aumenta la complessità ciclomatica: più il codice è nidificato, più potenziali percorsi di esecuzione esistono all'interno della funzione. Un'esplosione combinatoria di potenziali percorsi di esecuzione rende difficile ragionare sul codice e, pertanto, dovrebbe essere evitato in generale.

Quindi perché 3? Una linea guida soggettiva di codifica è sia difficile da far rispettare che impossibile da applicare automaticamente. L'impostazione di una linea guida di codifica obiettiva sul livello massimo di indentazione richiede di concordare un numero: nel kernel di Linux hanno scelto 3.

È arbitrario e apparentemente sufficiente per loro.

Are there some things which absolutely need three or more levels of looping?

Algoritmo-saggio, probabilmente, tuttavia in linguaggi sufficientemente espressivi puoi sempre rifattorizzare il codice in blocchi più piccoli (con funzioni o chiusure).

Ovviamente puoi scrivere un codice offuscato con una piccola nidificazione e molte piccole funzioni che si chiamano senza mai scrivere il loro contratto ...

... tuttavia, le piccole funzioni con contratti chiari sono molto più facili da controllare rispetto alle grandi funzioni con contratti chiari in generale.

    
risposta data 23.12.2015 - 17:26
fonte

Leggi altre domande sui tag