Applicazione dei principi del codice pulito ai linguaggi funzionali


16

Attualmente sto leggendo il codice pulito di Robert Martin . Penso che sia fantastico, e quando scrivo il codice OO sto prendendo a cuore le sue lezioni. In particolare, penso che il suo consiglio di usare piccole funzioni con nomi significativi renda il mio codice molto più fluido. È meglio riassunto da questa citazione:

[Vogliamo essere in grado di leggere il programma come se fosse un insieme di paragrafi TO, ognuno dei quali descrive l'attuale livello di astrazione e fa riferimento ai successivi paragrafi TO al livello successivo in basso.

( Codice pulito , pagina 37: un "paragrafo TO" è un paragrafo che inizia con una frase espressa nell'infinito. "Per fare X, eseguiamo i passaggi Y e Z." "Per fare Y, noi ..." ecc. ) Per esempio:

PER RenderPageWithSetupsAndTeardowns, controlliamo se la pagina è una pagina di test e, in tal caso, includiamo le impostazioni e gli smontaggi. In entrambi i casi eseguiamo il rendering della pagina in HTML

Scrivo anche codice funzionale per il mio lavoro. Gli esempi di Martin nel libro sicuramente leggono come se fossero una serie di paragrafi, e sono molto chiari - ma non sono così sicuro che "legge come una serie di paragrafi" sia una qualità desiderabile per il codice funzionale .

Prendendo un esempio dalla libreria standard Haskell :

maximumBy               :: (a -> a -> Ordering) -> [a] -> a
maximumBy _ []          =  error "List.maximumBy: empty list"
maximumBy cmp xs        =  foldl1 maxBy xs
                        where
                           maxBy x y = case cmp x y of
                                       GT -> x
                                       _  -> y

Questo è il più lontano possibile dal consiglio di Martin, ma è conciso, idiomatico Haskell. A differenza degli esempi di Java nel suo libro, non riesco a immaginare alcun modo per ricondurlo a qualcosa che ha il tipo di cadenza che chiede. Ho il sospetto che Haskell scritto secondo lo standard di Clean Code sarebbe risultato prolisso e innaturale.

Sbaglio considerare (almeno parte di) Clean Code in contrasto con le migliori pratiche di programmazione funzionale? C'è un modo ragionevole per reinterpretare ciò che dice in un diverso paradigma?


1
I programmatori funzionali tendono a scrivere codici troppo concisi, è vero. Non considererei a distanza questa best practice, anche in quell'ambiente.
Telastyn,

Perdona l'ignoranza, ma cos'è un paragrafo TO?
Shashank Gupta,

4
Come è stato recentemente menzionato in un'altra domanda, Dijkstra ha scritto della follia della "programmazione in linguaggio naturale" e tendo a concordare con lui che il codice che legge come la prosa è un sogno irrealizzabile. Penso che ciò sia particolarmente vero in Haskell che, essendo puro, esprime simbolicamente le uguaglianze tra valori piuttosto che sequenze di passaggi per produrre effetti. Penso che la cosa importante sia che il codice citato sia idiomatico. Ad esempio, xsè un brutto nome, ma è comune nei linguaggi funzionali come iper le variabili di ciclo.
Doval,

@ShashankGupta Ho modificato la domanda con un link alla pagina specifica del libro, nonché la mia comprensione di ciò che ha scritto lo zio Bob.

@ShashankGupta Fa alcuni esempi, ma l'idea è che dovrebbe leggere come in prosa. "Per trovare il massimo dell'elenco, controlla ogni elemento ..."
Patrick Collins,

Risposte:


11

Clean Code è prima di tutto un manuale di stile. Strunk and White non si applica quando scrivi in ​​Klingon. L'idea è che vuoi essere chiaro ai programmatori che probabilmente leggeranno il tuo codice. Vuoi avere un codice che è modulare e facile da ristrutturare. Ci sono modi per farlo in Haskell così come ci sono modi per farlo in qualsiasi altra lingua, ma i dettagli precisi varieranno.

Detto questo, ci sono un certo numero di linee guida di stile là fuori per Haskell. Stack Overflow ha anche una guida abbastanza completa . Mantenere una logica di codifica semplice e concisa sembra essere abbastanza costante. Anche la generalizzazione delle funzioni è sottolineata in quanto porta alla modularità. Anche il codice DRY è stressato, come nel caso del codice Clean.

Alla fine, le linee guida per la codifica di Clean Code e Haskell si sforzano per la stessa cosa, ma finiscono per prendere le proprie strade per arrivarci.


1
Sento che questa risposta sconta i principi insegnati da Clean Code che sono molto applicabili in tutte le lingue e che sono alla base della domanda posta. Posso capire perché la gente pensa a Clean Code come a un manuale di stile, e penso che sia parzialmente vero, ma non abbastanza vero da liquidare l'intero libro come uno.
Allan,

Non penso al libro Clean Code di Martin come a un manuale di stile. Sento che gli insegnamenti del libro si adattano in qualche modo tra una guida di stile e modelli di design.
Michael R

15

Non sono sicuro di seguire cosa intendi con il tuo esempio. I paragrafi, come li descrive, non necessitano di lungimiranza. Non vuole dire che il codice dovrebbe leggere come l'inglese. La parte importante è il raggruppamento di funzionalità allo stesso livello di astrazione, in una progressione logica. È un concetto strutturale teorico che trascende i paradigmi di programmazione.

Espresso nel formato "TO paragrafo" di Bob Martin, ho letto il tuo esempio come:

  • Per calcolare maximumBy, è necessaria una funzione di ordinamento e un elenco e il risultato è un elemento di tale elenco.
  • Per calcolare il maximumBydi un elenco vuoto e qualsiasi funzione di ordinamento è un errore.
  • Per calcolare il maximumBydi un elenco xs, piega quell'elenco usando la maxByfunzione.
  • Per calcolare i maxBydue elementi dell'elenco, confrontarli utilizzando la funzione di ordinamento specificata. Se il primo elemento è maggiore, sceglierlo. Altrimenti scegli il secondo.

Stai iniziando con i concetti più generali e procedendo verso maggiori dettagli, proprio come negli esempi imperativi. L'idea dei "paragrafi TO" è che puoi smettere di leggere ad un certo punto quando hai ottenuto abbastanza dettagli, senza dover saltare su e giù nella pagina. Questo è certamente il caso qui.

Un paio di nomi potrebbero forse essere migliori, ma sono convenzioni comuni della lingua, specialmente quando si scrivono funzioni generiche di ordine superiore. Anche i nomi delle funzioni di ordine superiore non si traducono bene in frasi verbo imperative come gli esempi nel libro, perché descrivono maggiormente le relazioni tra i verbi.

Esistono modi per implementare ciò che non seguono le linee guida "paragrafo TO". Lasciando la firma esplicita del tipo si ometterebbe la frase "panoramica" di livello superiore. È possibile utilizzare un'espressione if per la gestione degli errori anziché la corrispondenza dei modelli, che confonderebbe in modo inappropriato con un altro livello di astrazione. È possibile inline maxBycome una funzione anonima invece di dargli un nome che può essere descritto in seguito in maggiore dettaglio.

In effetti, penso che i costrutti come in whererealtà si adattino meglio al formato del paragrafo, perché puoi usarli per dare un nome a un dettaglio più profondo in un modo vicino a come lo esprimiamo in inglese, e allo stesso modo limitarne l'ambito in un modo chiaro per il contesto del "paragrafo".

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.