Formattazione del codice: vale la pena fare in modo che il codice non appaia male? [chiuso]

7

In Code Complete 2nd Edition, Steve McConnell ha scritto quanto segue (pagina 732):

Techniques that make good code look good and bad code look bad are more useful than techniques that make all code look good.

Ho una discussione su questo e regole del formato del codice Eclipse con un collega. Ha detto che il codice dall'aspetto malvagio rende più difficile il refactoring e la pulizia del codice errato, dal momento che ha bisogno di maggiori sforzi per comprendere il codice. D'altra parte ho trovato che il codice che sembra cattivo è simile a un avvertimento "fai attenzione". Mi ricorda che devo pensarci due volte prima di modificare qualsiasi cosa per assicurarmi di non rompere nulla. Inoltre, probabilmente costringe gli sviluppatori a ristrutturare il loro codice per essere un po 'più bello e meglio strutturato.

Un'altra cosa sono le annotazioni @SuppressFBWarnings per gli avvisi di FindBugs falsi positivi che rendono anche più difficile mantenere il codice poiché queste annotazioni sembrano scadenti, interrompono la struttura del codice e sono difficili da leggere. D'altra parte penso che anche questi risparmino tempo. Quando uno sviluppatore trova un codice che odora e FindBugs lo ha già trovato, lo sviluppatore probabilmente ha una ragione per cui è OK (o perché qualcuno ha pensato che sia OK) nell'elemento justification dell'annotazione.

Ci sono altri motivi per cui vale la pena o meno di rendere il codice errato un aspetto negativo o piuttosto una domanda di psicologia e entrambi i formati sono accettabili?

    
posta uqk 06.03.2015 - 11:24
fonte

4 risposte

17

La citazione dalla stessa pagina, stesso paragrafo, alcune frasi prima:

Making the code look pretty is worth something, but it's worth less than showing the code's structure. If one technique shows the structure better and another looks better, use the one that shows the structure better. [...] In practice, prioritizing logical representation usually doesn't create ugly code—unless the logic of the code is ugly.

Il punto non è che dovresti formattare il codice errato in modo intenzionale. Il punto è che in un buon codice, puoi facilmente vedere la struttura, mentre nel codice errato, trovare qualsiasi struttura (se ce ne sono) è doloroso.

In questo contesto, la formattazione è completamente superflua . Puoi passare ore a migliorare le convenzioni di denominazione o aggiungere interruzioni di riga, ma il codice errato rimarrà comunque negativo, perché - ancora una volta - della mancanza di struttura.

In sostanza, questa è la differenza tra bella e leggibile. Lo stile rende il codice carino, ma questo non significa che diventa immediatamente leggibile. Solo un refactoring (relativamente importante e doloroso) può farcela. D'altro canto, il codice leggibile può essere percepito come brutto a causa della mancanza di stile, ma uno strumento di base può attraversarlo e riformattarlo in pochi millisecondi.

    
risposta data 06.03.2015 - 11:58
fonte
5

Non solo una cattiva formattazione rende più difficile migliorare il codice, ma anche una formattazione errata (o, probabilmente, non familiare) potrebbe far apparire il codice come se fosse logicamente peggiore di quello che realmente è.

Una volta mi sono trovato a risolvere un problema che ero quasi sicuro fosse un bug, solo per scoprire che non c'era alcun bug, e mi sono reso conto che avevo l'impressione che ci fosse un bug perché la cattiva formattazione del il codice mi ha tentato di credere che stesse facendo qualcosa di sbagliato.

Quindi, per la maggior parte, no, non penso che sia una buona idea intenzionalmente fare in modo che il codice non sia buono o lasciare un cattivo aspetto del codice.

Sarei disposto a fare un'eccezione in alcuni casi in cui vengono scelti brutti identificatori per rappresentare correttamente la bruttezza di ciò che fa il codice. Per esempio, di volta in volta vedo i programmatori scrivere funzioni di annullamento del vuoto chiamate "checkSomething ()" come se fossero le piccole cose innocenti più naturali del mondo. Naturalmente, queste funzioni funzionano interamente per effetto collaterale, quindi sono piuttosto malvagie. Rinominerei questa funzione in "checkSomethingAndDoThisIfSuchOrThatOtherwise ()" per indicare chiaramente che questa è una funzione malvagia che probabilmente fa cose cattive.

    
risposta data 06.03.2015 - 12:50
fonte
5

Ti rimanderò a questa domanda , per la quale il rientro corretto del codice ha rivelato immediatamente la fonte del bug. Mi riferirò anche allo stile di codifica del kernel Linux , che utilizza esplicitamente le schede a 8 spazi per evidenziare nidificazione eccessiva.

Questi tipi di standard di codifica non sono pensati per posizionare un nastro di attenzione permanente attorno a aree del codice errate. Hanno lo scopo di darti un calcio visivo in testa in modo che il codice mal strutturato non venga mai inviato in primo luogo. Rendono intenzionalmente più difficile leggere determinati tipi di codice, non come una sorta di punizione o avvertimento permanente, ma così sistemarlo . Se devi disattivare temporaneamente la formattazione per correggerla, così sia, ma non è una scusa per lasciarla disattivata per sempre.

There are two ways to write code: write code so simple there are obviously no bugs in it, or write code so complex that there are no obvious bugs in it.
—Tony Hoare

La formattazione del codice è un modo semplice per rendere evidenti alcuni tipi di bug, in modo che possano essere rimossi. Non è d'aiuto con tutti i tipi di bug, ma qualsiasi passo facile da intraprendere in quella direzione è buono.

    
risposta data 06.03.2015 - 14:04
fonte
3

Se stai iniziando un progetto di refactoring e il codice è formattato male, devi prima riformattare meccanicamente l'intera base di codice in qualcosa di sensato. Dovresti fare nessun'altra modifica in quel commit VCS.

È possibile effettuare regolazioni manuali per la leggibilità locale (inserimento di righe vuote, allineamento di segni uguali consecutivi, rimozione di commenti privi di significato, ecc.) successivamente, come rifattori di ogni unità logica, ma la riformattazione iniziale dovrebbe essere meccanica al 100% e applicato al 100% del codice.

Ci sono tre ragioni per questo:

  • Non dovresti riformattare il codice errato pezzo per pezzo nello stesso momento in cui lo rifatti in modo semantico, perché ciò rende più difficile per i revisori del codice capire quali sono stati i cambiamenti semantici.

  • Sarà più facile per tu capire il codice abbastanza bene da refactarlo, se è ben formattato quando inizi.

  • Una patch di riformattazione meccanica è sicuramente grande e noiosa. Se è meccanico al 100%, i revisori del codice non devono leggerlo alla ricerca di cambiamenti semantici. È anche certo di toccare quasi tutti i file, quindi puoi anche renderli tutti i file, riducendo al minimo il numero di volte che qualcuno deve ricostruire il mondo.

Non importa quale stile di formattazione del codice sia applicabile meccanicamente (eccetto che non dovresti mai mettere degli spazi all'interno delle parentesi, perché questo fa piangere il bambino Gesù). La coerenza della formattazione in un intero progetto è molto più importante di qualsiasi stile particolare. (La leggibilità locale è ancora più importante, ma non ti preoccupare in questa fase.)

Infine, se il codice è così disordinato che riformattando meccanicamente il codice lo si interrompe, è necessario applicare le correzioni prima della patch di riformattazione. Cioè, la tua cronologia VCS dovrebbe apparire come

... --- [corrections so reformatting doesn't break the code] --- [reformatting] --- ...

tempo che avanza a destra. Questo è così che ogni revisione del codice nel VCS non è interrotta, ma la patch di riformattazione rimane al 100% meccanica.

Se non si dispone di un VCS, un processo di revisione del codice, una suite di test o un'infrastruttura di integrazione continua, procurarsi quelle prima che si tenta di rifattorizzare il programma. In questo ordine.

    
risposta data 06.03.2015 - 20:12
fonte

Leggi altre domande sui tag