Come si definisce un codice elegante? [duplicare]

70

In una discussione sulla qualità della codifica e su come la si identifica, mi sono imbattuto in una discussione sulla verifica della capacità di codifica delle persone, facendo in modo che mostrassero come scambiare due valori usando un pezzo di codice per raggiungere l'obiettivo. Sono state prodotte due soluzioni chiave:

  1. Introdurre una variabile di riserva per fare in modo che passi il pacco dei valori o:
  2. Utilizza alcuni operatori bit a bit.

Quindi è seguito un argomento su cui si trovava di fatto la soluzione migliore (sarei propenso alla prima opzione pur essendo consapevole che la seconda esiste, ma potrebbe non sempre valutare come previsto a seconda dei valori in questione).

Tenendo presente la storia di Mel the Real Programmer , sono interessato a conoscere come valuti il codice come elegante o meno, ed è succintamente una caratteristica chiave del codice elegante.

    
posta temptar 12.04.2017 - 09:31
fonte

22 risposte

76

Il buon codice dovrebbe essere pulito, semplice e facile da capire prima di tutto. Più semplice e pulito è, minore è la possibilità di insinuarsi degli errori. Come ha coniato Saint-Exupery, "La perfezione si ottiene, non quando non c'è altro da aggiungere, ma quando non c'è più nulla da togliere".

Inoltre, il codice elegante di solito è il risultato di un'attenta analisi del problema e della ricerca di un algoritmo e di un design che semplifica notevolmente il codice (e spesso lo accelera troppo). Per esempio. Perle di programmazione mostra diversi esempi in cui le informazioni acquisite durante l'analisi hanno fornito un angolo di attacco, risultante in una soluzione molto semplice, elegante e breve.

Mostrare quanto intelligente sia l'autore, viene solo dopo questi ;-) Il micro-ottimizzazione delle prestazioni (come l'uso delle operazioni bit a bit che si menzionano) dovrebbe essere usato solo quando si può dimostrare (con misurazioni concrete) che il pezzo di codice in questione è il collo di bottiglia, e che la modifica migliora effettivamente le prestazioni (ho visto esempi al contrario).

    
risposta data 03.08.2011 - 16:03
fonte
47

Il codice elegante è una combinazione di:

  • correttezza. IMHO nessun codice sbagliato può essere davvero elegante.
  • concisione. Meno codice significa meno per andare male, meno per capire *.
  • leggibilità. Più facile è capire il codice, più facile da mantenere.
  • Prestazioni. Ad un certo punto. Il codice prematuramente pessimizzato non può essere davvero elegante.
  • Seguendo gli standard stabiliti della piattaforma o del progetto. Quando vengono date due opzioni altrettanto eleganti, quella che è più vicina allo standard stabilito è la migliore.
  • Esattamente come lo farei io. Ok, sto scherzando, ma è facile etichettare il codice che NON è come lo si farebbe come "poco elegante". Per favore, non farlo: tieni la mente aperta a un codice diverso.

Naturalmente, c'è anche l'adagio troppo spesso vero: "Ad ogni problema c'è una soluzione semplice, elegante e sbagliata".

* Come mostrano i commenti qui sotto, c'è qualche contesa sul codice più breve. "Succinto" non significa "nel minor numero possibile di caratteri", significa "Brevemente e chiaramente espresso".

    
risposta data 03.08.2011 - 16:31
fonte
28

Il codice semplice è un codice così leggibile che persino i programmatori inesperti possono risolvere (almeno in generale) il codice che sta facendo. (Vedi: sintassi delle espressioni ruby )

Il codice estremamente complesso è il codice che fa il maggior numero possibile di righe il più possibile, senza un reale riguardo alla leggibilità (vedi: Perl )

Il codice elegante è il codice che rende gli altri sviluppatori dire "Oh uomo, perché non ci ho pensato ?!" È una specie di intermedio tra i primi due, con un codice che potrebbe non essere così facilmente evidente che i tuoi genitori possono leggerlo, ma non qualche scarabocchio arcano che richiede un codice da interpretare. Fa il lavoro, lo fa bene , e non lascia le persone che mantengono il codice grattandosi la testa.

    
risposta data 02.08.2011 - 16:46
fonte
13

Fred Brooks suddivide la complessità di una soluzione nelle categorie "complessità essenziale" e "complessità accidentale" . Il codice perfettamente elegante, per me, è quello che è tutto "complessità essenziale" e no "complessità accidentale". Il trucco è che diversi programmatori avranno idee diverse su cosa sia "complesso", quindi è probabile che non saremo d'accordo sul fatto che un po 'di codice sia elegante.

Ad esempio, trovo che la struttura del codice Lisp sia significativamente più elegante della struttura del codice nei linguaggi C-like. D'altra parte, la notazione del prefisso di Lisp e la costruzione di un albero di parsing esplicito violano la nostra intuizione su come dovrebbero apparire le espressioni matematiche, che possono rendere la lettura del codice di Lisp più difficile per le persone. Di conseguenza molti programmatori considerano tutte quelle parentesi in Lisp non per essere "eleganti" affatto, ma in effetti piuttosto brutte. Per qualcuno che è davvero preoccupato di come il compilatore interpreterà il codice, Lisp può sembrare elegante. Per qualcuno che è più preoccupato di come la gente interpreterà il codice, Lisp può sembrare brutto.

    
risposta data 02.08.2011 - 18:04
fonte
11

La succinta è una componente importante, ma per me, per essere chiamata elegante, il codice deve anche essere facilmente comprensibile al punto che dici "Certo che è il modo più ovvio per farlo!" Anche se paradossalmente non è il primo modo in cui hai pensato. Se non supera questo test, può essere definito "intelligente" o "efficiente", ma non elegante.

    
risposta data 02.08.2011 - 15:42
fonte
10

È simile alla poesia, che è un linguaggio elegante.

I poeti possono dire in pochissime parole cosa richiederebbero altre pagine e pagine, per dire e non altrettanto bene. I codificatori eleganti possono fare lo stesso con il codice.

Un tipico esempio è il confronto di un'implementazione tipica di quicksort in C con quicksort in Haskell:

quicksort :: Ord a => [a] -> [a]
quicksort []     = []
quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
    where
        lesser  = filter (< p) xs
        greater = filter (>= p) 

(minore e maggiore può essere sottolineato per una soluzione a tre linee).

    
risposta data 03.08.2011 - 15:54
fonte
7

Lo scambio XOR è abbastanza noto. E tutti, chi ha almeno un po 'dell'umiltà richiesta da Dijkstra, vi diranno che è il modo sbagliato di fare le cose. Non solo è più difficile da leggere per gli umani, ma anche per i compilatori. I compilatori sono relativamente bravi nell'analisi del flusso e nell'assegnazione dei registri e in ogni genere di cose. Avendo un buon compilatore, non puoi aspettarti che ogni variabile che crei sia effettivamente presente nello stack / in un registro in qualsiasi momento. Quello che devi fare è esprimere chiaramente le cose. In una lingua che supporta la chiamata per riferimento, questa è la la strada da percorrere: swap(x, y); .
Questa è la soluzione migliore (oserei dire così, almeno date le alternative che hai fornito). È una ed è auto-esplicativo. Non usa il voodoo come fa lo scambio XOR. Non introduce il rumore di una variabile temporanea e 3 istruzioni di assegnazione. Questo è qualcosa che accade all'interno dello swap. Supponendo che sia una funzione, un compilatore decente eseguirà questa chiamata in linea. Potresti anche renderlo una macro. Qualunque sia.

Ciò che rende il codice veramente elegante è la mancanza di ridondanze, è l'ortogonalità, è la semplicità. Assicura sistemi robusti che crescono l'uno sull'altro. Avere gruppi di istruzioni ricorrenti ovunque nel luogo in cui si desidera uno swap introduce ridondanza, manca di ortogonalità e fallisce nella semplicità.

    
risposta data 03.08.2011 - 16:00
fonte
4

È facile individuare ciò che fa il codice elegante. Hai capito, "Perché non ci ho pensato?" vibrazione. Questo rispetto alla complessità del problema e della lingua utilizzata.

Questo non significa che la soluzione migliore o più semplice sia automaticamente elegante. Semplice è spesso una delle sue qualità. Le modifiche, sebbene di solito più semplici, non sempre mantengono l'eleganza.

    
risposta data 02.08.2011 - 16:57
fonte
2

Il bene è l'assenza di cattivo. Si applica a tutto nella vita e il codice non fa eccezione. Quindi,

Good code is one that doesn't have a smell! So, it is important for you to see and understand what a code smell is. No joke intended.

Pensaci. Dici di essere felice solo perché NON sei triste o sei stato cavalcato dalla tua tristezza. Allo stesso modo, si chiama qualcosa un buon codice, quando non si vede nulla di male nel codice. Ogni aspetto della qualità del codice (manutenibilità, leggibilità, ecc.) Può essere raggiunto eliminando l'odore del codice. E che ci crediate o no, non succede la prima volta - succede iterativamente:)

    
risposta data 02.08.2011 - 19:52
fonte
2

Mi piace confrontare il codice con il supporto di stampa qui.

Sai che lo odi quando leggi articoli eccessivamente semplificati. Storditi. Pochi fatti, frasi semplici. Questo si traduce in codice che collego ai principianti: banale, ingenuo persino, implementazione, niente è troppo complicato, ma è lungo e pieno di passaggi non necessari.

D'altra parte conosci questo stile torre d'avorio. Leggi un libro di noti filosofi. Leggi un articolo scientifico su una questione complicata: lo stile sembra spesso molto lungo. Le parole non vengono riutilizzate, devi mostrare che puoi conoscere una dozzina di sinonimi. Mentre il contenuto reale potrebbe essere puro, buono, interessante - lo stile della scrittura rende difficile seguirlo. Questo stile sfuma la linea originale dei pensieri. Questo è codice intelligente.

Il codice elegante è da qualche parte nel mezzo e altrettanto soggettivo come le preferenze possono essere. Puoi individuare e descrivere facilmente i casi difficili, ma la perfezione è diversa per la maggior parte di noi.

    
risposta data 03.08.2011 - 16:13
fonte
2

L'eleganza è la minimizzazione della complessità. Se riesci a consegnare rapidamente il codice a un altro programmatore con competenze ragionevoli e sono in grado di continuare il lavoro (e spero di essere all'altezza dello standard iniziale), il codice è probabilmente elegante.

Il software ben scritto dovrebbe rimanere in circolazione per almeno dieci anni. L'eleganza iniziale può essere spaventata dagli hack successivi, ma la lunghezza del codice temporale sopravvive è spesso una metrica ragionevole di quanto bene è stato scritto inizialmente. Il codice scritto in modo scadente o diventa stagnante (e la gente lo incide su di esso), o viene rielaborato (anche se in pratica ho visto persone sostituire codice elegante con soluzioni minori perché non l'hanno guardato attentamente).

    
risposta data 03.08.2011 - 18:34
fonte
1

La mia definizione è semplice, sfortunatamente non puoi determinarla tu stesso.

Il codice elegante ha le seguenti caratteristiche:

  • Risolve il problema.
  • Posso fidarmi dei test in modo tale che se modifico un comportamento, un test si interromperà.
  • Quando io o + qualsiasi altro sviluppatore + apro il codice, è immediatamente facile da seguire. Qualsiasi blocco logico non banale è descritto da un commento.
  • Le cose semplici sono semplici, le cose difficili sono possibili.
  • Qualcun altro è disposto + a prendere in carico lo sviluppo del codice anche se sono ancora lì. Senza essere forzato.
risposta data 03.08.2011 - 18:21
fonte
0

Con che facilità la maggior parte degli sviluppatori può leggerlo? Quanto è facile cambiare?

Di conseguenza, sarei decisamente d'accordo con te sul fatto che opton 1 è decisamente più elegante.

L'opzione 2 è intelligente e mostra una buona conoscenza degli operatori. Salva anche un piccolo frammento di memoria. Utile, forse, in casi eccezionali, e vale la pena che uno sviluppatore sia in grado di farlo. Ma non nel tuo caso medio del 99%.

    
risposta data 02.08.2011 - 15:43
fonte
0

Doveva essere coerente . Ci doveva essere un qualche tipo di schema in esso. E quando hai bisogno di rompere questo schema, spezzalo in modo coerente, in modo che nel complesso ci sia ancora un qualche tipo di schema.

Se qualcuno punta al tuo codice e ti chiede perché lo stai facendo in questo modo, e la tua risposta è "Non lo so, lo sto facendo in questo modo perché è così che mi è stato insegnato / perché è così che tutti gli altri stanno facendo " allora quel codice può essere elegante o non elegante . Tuttavia, se puoi spiegare perché il codice è così, perché hai scelto di codificarlo in quel modo, perché le altre alternative non sono così attraenti, allora puoi essere sicuro che il codice è elegante .

    
risposta data 02.08.2011 - 16:01
fonte
0

Ero blasé nel mio commento in cima, ma per me il codice elegante è quello che colpisce i miei sensi molto più di altri.

Produce una reazione positiva nel raggiungimento degli obiettivi pur essendo brevi e al punto, semplicità ma con uno scopo e una potenza, elegante, simmetrica e un po 'fuori dagli schemi nell'approccio. Sorge un elemento di sorpresa. Il metodo e l'algoritmo non sono così complessi (almeno superficialmente) da ostacolare la comprensione.

Il codice elegante è più della somma delle sue parti. A volte il codice elegante sembra quasi lavorare con i dati, piegarsi con esso, invece di usare la forza bruta o mappare i dati in un'altra forma. Per me, l'eleganza spesso si presenta in un pacchetto autonomo: una singola funzione, poche o nessuna chiamata esterna, né troppo lunga né troppo breve.

Ad esempio, ho visto metodi di ordinamento che definirei eleganti. Ed eleganti codici / algoritmi per disegnare frattali in modi insoliti ma estremamente efficienti - combinando l'eleganza della codifica estetica e !

    
risposta data 02.08.2011 - 16:45
fonte
0

Il codice elegante usa l'intelligenza per realizzare qualcosa in molto meno codice di quanto la maggior parte della gente potrebbe pensare possibile, ma in un modo leggibile e ovvio con il senno di poi e che non assomiglia al codice del golf.

    
risposta data 02.08.2011 - 17:01
fonte
0

Personalmente trovo il codice elegante da sopravvalutare. Ma lavoro nel mondo dei database in cui il codice performante è di importanza critica e il codice "elegante" nel contesto del codice SQL, molto spesso (almeno nella mia esperienza) si comporta male. Mi fa rabbrividire ogni volta che sento qualcuno che vuole scrivere codice SQL elegante.

In generale però, penso ancora che la ricerca dell'eleganza sia ridicola. In primo luogo, nessuno può definirlo correttamente. Quello che vuoi è un codice che funzioni correttamente, che funzioni bene, che sia manutenibile e che l'elegante sia un quarto lontano se addirittura fa la lista.

    
risposta data 02.08.2011 - 20:22
fonte
0

Il codice elegante non è lo stesso del design elegante anche se c'è un crossover tra il 2.

Come definisci un dipinto elegante? È bello da vedere, perfettamente leggibile, ha perfettamente senso è facilmente mantenibile e fa solo il lavoro.

Il design elegante aiuta in un codice elegante. Non puoi avere un codice elegante senza un buon design ma puoi avere un codice brutto con un buon design. Molto meglio scrivere se can_can_add_apples_to_my_basket (20) allora   add_apples_to_basket (20) altro  render_not_enough_room_to_add_apples (20) fine poi scrivi il 2 se condizioni che potrebbero essere riutilizzabili dovunque ti servissero per qualunque cosa tu avessi bisogno di loro (questo è il design bit)

codice che sais se b.count + 20 < = b.max allora   b + = 20 altro   rilancio ("troppe mele") end

Hai ancora i 2 metodi (count e max) quindi hai ancora un buon design ma il codice è brutto e insignificante, difficile da mantenere senza conoscenza del sistema e totalmente ambiguo

    
risposta data 03.08.2011 - 06:00
fonte
0

Per essere onesti, raramente c'è una buona ragione per scambiare il valore di due variabili, e non è davvero una cosa "elegante" da fare, indipendentemente da come lo fai.

Il codice elegante non riguarda il codice in sé e per sé, si tratta in realtà di cosa fa il codice e come lo fa. Personalmente ritengo che questo sia un cattivo esempio per determinare quale "codice elegante" sia, poiché la cosa che viene fatta non è di per sé elegante. Trovo che il codice Haskell sia tipicamente elegante, perché (per la maggior parte) tratta valori immutabili . Tuttavia, gli algoritmi che utilizzano lo stato mutabile possono anche essere scritti elegantemente (e di solito non sembrano così caldi in Haskell).

    
risposta data 03.08.2011 - 09:56
fonte
0

Dipende davvero da chi chiedi. Qualcuno che proviene da un background matematico preferirà il codice che un programmatore esperto potrebbe trovare problematico. Questo lo rende molto soggettivo.

Inoltre, scoprirai che lingue diverse hanno diversi modi per risolvere lo stesso problema. In Python, ad esempio, lo scambio di due variabili è banale: x, y = y, x

In pratica, la maggior parte dei programmatori concordano sul fatto che ci sono alcuni criteri comuni:

  • il codice elegante deve essere il più breve possibile
  • ma verboso se necessario
  • dovrebbe essere facile da seguire
  • ogni dichiarazione dovrebbe essere facile da capire
  • nessuna istruzione dovrebbe sembrare ridondante o superflua
  • il codice dovrebbe seguire gli idiomi della lingua
  • non deve fare uso di astrazioni che perdono

Questa è una visione molto pragmatica dell'eleganza. Il codice non deve essere "intelligente" o non soddisfa questi criteri. Ma sarà mantenibile e più facile da regolare ed estendere.

Detto questo, c'è un codice che può essere un'opera d'arte, anche se assolutamente privo della maggior parte delle regole in questo elenco. Il codice "intelligente" spesso rientra in questa categoria. È molto denso, spesso si basa su una conoscenza approfondita delle implementazioni sottostanti (ad esempio, gestione della memoria o l'esatta implementazione del compilatore), ma evoca comunque un fascino sublime.

C'è una differenza tra l'eleganza che troverai in Yet Another Script di Perl contro il codice che vorresti utilizzare in produzione. Questo è il motivo per cui non vorresti mai che Mel fosse nella tua squadra anche se potessi chiamare il suo opus più elegante.

    
risposta data 03.08.2011 - 15:33
fonte
0

Comprendere il codice elegante dovrebbe essere come risolvere un enigma. All'inizio dovrebbe essere difficile da capire, quindi è molto facile capire una volta che hai "capito".

C'è un compromesso: le persone che non lo capiscono sono lasciate a grattarsi la testa, mentre le persone che lo capiscono lo trovano ovvio, a posteriori.

Per quanto riguarda lo scambio di variabili, nessuna sarà particolarmente elegante. Non c'è complessità da domare qui, quindi non c'è spazio per una soluzione "elegante".

    
risposta data 03.08.2011 - 17:39
fonte
-2
isElegant(code)
{
  return isSimple(code) && isReadable(code) && code.reducesComplexity();
}
    
risposta data 02.08.2011 - 20:37
fonte

Leggi altre domande sui tag