Come vengono mantenute enormi librerie open source pur avendo il codice lontano da pratiche di "codice pulito"?

78

Sono ancora inesperto per scrivere codice di alta qualità, quindi ho letto libri che affrontano il problema come Clean Code di Robert C. Martin, e continuo a controllare il codice di librerie ben note per migliorare il mio competenze.

Sebbene molte librerie open source siano state mantenute per anni, il che significa che è molto improbabile che non siano sulla strada giusta, ho trovato che il codice in molti di essi è lontano dai principi per scrivere codice pulito - es. metodi contenenti centinaia di righe di codice.

Quindi la mia domanda è: i principi del codice pulito sono troppo limitati e possiamo fare a meno di questi in molte librerie come queste? Altrimenti, in che modo vengono mantenute enormi librerie senza considerare molti di questi principi?

Apprezzerò qualsiasi breve chiarimento. Mi scuso se la domanda sembra essere stupida da un ragazzo novizio.

Modifica

Controlla questo esempio nella libreria Butterknife - una delle librerie più conosciute della comunità Android.

    
posta Islam Salah 11.07.2018 - 12:25
fonte

9 risposte

83

Buona risposta già qui, ma lasciami dire una parola sul tuo butterknife esempio: anche se non ho idea di cosa faccia il codice, a prima vista, non sembra davvero impossibile da mantenere. Le variabili e i nomi dei metodi sembrano essere scelti deliberatamente, il codice è correttamente rientrato e formattato, ha alcuni commenti e i metodi lunghi mostrano almeno una struttura a blocchi.

Sì, non segue in alcun modo le regole del "codice pulito" di Uncle Bob, e alcuni dei metodi sono sicuramente troppo lunghi (probabilmente l'intera classe). Ma guardando il codice vedo ancora abbastanza struttura in modo che possano essere "ripuliti" facilmente estraendo questi blocchi in metodi da soli (con un basso rischio di introdurre bug quando si usano strumenti di refactoring).

Il vero problema con tale codice è, aggiungendo un blocco e un altro blocco e un altro blocco funziona in una certa misura, a volte negli anni. Ma ogni giorno il codice diventa più difficile evolversi un po ', e ci vuole un po' più tempo per modificarlo e testarlo. E quando devi davvero cambiare qualcosa che non può essere risolto "aggiungendo un altro blocco", ma richiede una ristrutturazione, allora vorrai che qualcuno abbia iniziato a ripulire il codice più presto.

    
risposta data 11.07.2018 - 16:26
fonte
157

I principi indicati in "Codice pulito" non sono sempre generalmente concordati. La maggior parte è di buon senso, ma alcune delle opinioni dell'autore sono piuttosto controverse e non condivise da tutti.

In particolare, la preferenza per i metodi brevi non è condivisa da tutti. Se il codice in un metodo più lungo non viene ripetuto altrove, l'estrazione di alcuni di essi in un metodo separato (in modo da ottenere più metodi più brevi) aumenta la complessità complessiva, poiché questi metodi sono ora visibili per altri metodi che non dovrebbero interessarli. Quindi è un trade-off, non un miglioramento oggettivo.

Il consiglio nel libro è anche (come tutti i consigli) orientato verso un particolare tipo di software: applicazioni Enterprise. Altri tipi di software come i giochi o i sistemi operativi hanno vincoli diversi rispetto al software aziendale, quindi sono in gioco schemi e principi di progettazione diversi.

Anche la lingua è un fattore: Clean Code assume Java o un linguaggio simile - se usi C o Lisp molti dei consigli non si applicano.

In breve, il libro è opinioni di singole persone su una particolare classe di software. Non si applica ovunque.

Per quanto riguarda i progetti open source, la qualità del codice varia da abissale a brillante. Dopo tutto, chiunque può pubblicare il proprio codice come open source. Ma se si guarda ad un progetto open source maturo e di successo con più contributori, si può essere certi che si siano consapevolmente accontentati di uno stile che funzioni per loro. Se questo stile è in contraddizione con alcune opinioni o linee guida, allora (per dirla senza mezzi termini) è la linea guida che è sbagliata o irrilevante, dal momento che il codice operativo supera le opinioni.

    
risposta data 11.07.2018 - 13:35
fonte
33

Riepilogo

Come scrive JacquesB, non tutti sono d'accordo con il "Codice pulito" di Robert C. Martin.

I progetti open source che hai scoperto "violano" i principi che ci si aspettava avrebbero semplicemente altri principi.

La mia prospettiva

Mi capita di supervisionare diverse basi di codice che aderiscono molto ai principi di Robert C. Martin. Tuttavia, in realtà non sostengo che siano giusti , posso solo dire che funzionano bene per noi - e che "noi" è in realtà una combinazione di almeno

  • l'ambito e l'architettura dei nostri prodotti,
  • le aspettative del mercato target / cliente,
  • per quanto tempo i prodotti vengono mantenuti,
  • la metodologia di sviluppo che utilizziamo,
  • la struttura organizzativa della nostra azienda e
  • abitudini, opinioni e esperienze passate dei nostri sviluppatori.

Fondamentalmente, questo si riduce a: ogni squadra (che si tratti di un'azienda, di un dipartimento o di un progetto open source) è unica. Avranno priorità diverse e diversi punti di vista, e naturalmente faranno diversi compromessi. Questi compromessi e lo stile del codice in cui si traducono sono in gran parte una questione di gusti e non possono essere dimostrati "sbagliati" o "giusti". Le squadre possono solo dire "lo facciamo perché funziona per noi" o "dovremmo cambiarlo perché non funziona per noi".

Detto questo, credo che per poter mantenere con successo basi di codice di grandi dimensioni nel corso degli anni, ogni squadra dovrebbe concordare un insieme di convenzioni di codice che ritengono siano adatte per gli aspetti sopra indicati. Ciò può significare l'adozione di pratiche di Robert C. Martin, di un altro autore o l'invenzione di una propria; potrebbe significare scriverli formalmente o documentarli "con l'esempio". Ma dovrebbero esistere.

Esempio

Considera la pratica di "suddividere il codice da un metodo lungo in diversi metodi privati".

Robert C. Martin afferma che questo stile consente di limitare il contenuto di ciascun metodo a un livello di astrazione - come esempio semplificato, un metodo pubblico probabilmente consisterebbe solo in chiamate a metodi privati come verifyInput(...) , loadDataFromHardDisk(...) , transformDataToJson(...) e infine sendJsonToClient(...) , e questi metodi avrebbero i dettagli di implementazione.

  • Alcune persone amano questo perché i lettori possono avere una rapida panoramica dei passaggi di alto livello e possono scegliere i dettagli di cui vogliono leggere.
  • A qualcuno non piace perché quando vuoi conoscere tutti i dettagli, devi saltare nella classe per seguire il flusso di esecuzione (questo è ciò a cui JacquesB si riferisce probabilmente quando scrive di aggiungere complessità).

La lezione è: tutti hanno ragione, perché hanno il diritto di avere un'opinione.

    
risposta data 11.07.2018 - 20:57
fonte
13

Molte librerie open source infatti soffrono di pratiche di codifica povere oggettivamente e sono mantenute con difficoltà da un piccolo gruppo di contributori a lungo termine che possono gestire la scarsa leggibilità perché hanno molta familiarità con le parti del codice che mantengono più frequentemente. Codice di refactoring per migliorare la leggibilità dopo che il fatto è spesso uno sforzo erculeo perché tutti devono essere sulla stessa pagina, non è divertente e non paga perché non vengono implementate nuove funzionalità.

Come altri hanno già detto, qualsiasi libro sul codice pulito che affermi qualcosa contiene necessariamente consigli che non sono universalmente condivisi. In particolare, quasi tutte le regole possono essere seguite con eccessivo zelo, sostituendo un problema di leggibilità con un altro.

Personalmente, evito di creare funzioni con nome se non ho un buon nome per loro. E un buon nome deve essere breve e descrivere fedelmente ciò che la funzione fa al mondo esterno. Questo è anche legato al tentativo di avere il minor numero possibile di argomenti di funzione e nessun dato scrivibile a livello globale. Cercando di ridurre una funzione molto complessa in funzioni più piccole spesso risultano elenchi di argomenti molto lunghi quando la funzione era veramente complessa. Creare e mantenere un codice leggibile è un esercizio in equilibrio tra regole di buon senso reciprocamente contrastanti. La lettura dei libri è buona, ma solo l'esperienza ti insegnerà come trovare falsa complessità , che è dove vengono fatti i reali guadagni di leggibilità.

    
risposta data 12.07.2018 - 18:21
fonte
7

La maggior parte dei progetti open source è mal gestita. Ovviamente ci sono delle eccezioni, ma troverai un sacco di spazzatura nel mondo open-source.

Questa non è una critica di tutti i proprietari / gestori dei progetti di cui sto parlando, è semplicemente una questione di tempo usata. Queste persone hanno cose migliori da fare con il loro tempo, come il loro vero lavoro retribuito.

All'inizio il codice è il lavoro di una persona ed è probabilmente piccolo. E il codice piccolo non ha bisogno di essere pulito. O meglio, lo sforzo necessario per rendere il codice pulito è più grande del vantaggio.

Col passare del tempo, il codice è più una pila di patch di molte persone diverse. Gli autori di patch non sentono la proprietà del codice, vogliono solo che questa funzione venga aggiunta o che questo bug sia risolto nel modo più semplice possibile.

Il proprietario non ha il tempo di pulire le cose e a nessun altro importa.

E il codice sta diventando grande. E brutto.

Dal momento che diventa sempre più difficile orientarsi nel codice, le persone iniziano ad aggiungere funzionalità nel posto sbagliato. E invece di correggere i bug, aggiungono soluzioni alternative ad altri punti nel codice.

A questo punto non è solo che le persone non si preoccupano, non più osano ripulire dal momento che hanno paura di rompere le cose.

Ho avuto persone che descrivevano basi di codice come "punizione crudele e insolita".

Le mie esperienze personali non sono poi così male, ma ho visto alcune cose molto strane.

    
risposta data 12.07.2018 - 12:10
fonte
3

Mi sembra che tu stia chiedendo come funziona questa roba anche se nessuno sta facendo quello che sono presumibilmente. E se funziona, allora perché dovremmo fare queste cose ?

La risposta, IMHO, è che funziona "abbastanza buono" , noto anche come " peggio è meglio " filosofia . Fondamentalmente, nonostante la storia rocciosa tra open source e Bill Gates, entrambi hanno adottato de facto la stessa idea, che la maggior parte delle persone si preoccupa caratteristiche, non bug .

Questo naturalmente ci porta anche a " normalizzazione della devianza " che porta a situazioni come Heartbleed , dove, proprio come se rispondessi alla tua domanda, un enorme, overgrown pila di spaghetti di aperto codice sorgente chiamato OpenSSL inserito " non ripulito " per qualcosa come dieci anni , liquidando con un massiccio errore di sicurezza che interessa migliaia di milioni di persone .

La soluzione doveva inventare un sistema completamente nuovo chiamato LibreSSL , che era utilizzerà il codice clean-ish e, naturalmente, quasi nessuno lo utilizza .

Quindi come sono mantenuti enormi progetti open source mal codificati? La risposta è nella domanda. Molti di loro non sono mantenuti in uno stato pulito. Sono rattoppati casualmente da migliaia di persone diverse per coprire use cases su varie macchine sconosciute e situazioni in cui lo sviluppatore non ha accesso al test. Il codice funziona "abbastanza bene" fino a non , quando tutti vanno in panico e decidono di buttare soldi al problema .

Quindi perché dovresti preoccuparti di fare qualcosa " nel modo giusto " se non lo è nessun altro?

La risposta è che non dovresti. O sei fai o non lo fai e continua a girare a prescindere, perché natura umana non cambia sulla scala di un umano lifetime . Personalmente, cerco solo di scrivere codice pulito perché mi piace come ci si sente a farlo.

    
risposta data 13.07.2018 - 08:25
fonte
2

Ciò che costituisce un buon codice dipende dal contesto, e i classici libri che ti guidano sono, se non troppo vecchi per discutere dell'open-source, almeno parte di una tradizione che combatte la guerra infinita contro le codebase interne. Quindi è facile trascurare il fatto che le biblioteche hanno obiettivi completamente diversi e sono scritte di conseguenza. Considera i seguenti problemi, in nessun ordine particolare:

  • Quando importare una libreria, o da una libreria, probabilmente non sono abbastanza esperto nella sua struttura interna per sapere esattamente quale piccola parte del suo toolkit ho bisogno per qualsiasi cosa stia lavorando, a meno che non sia copiare ciò che una risposta allo Stack Exchange mi ha detto di fare. Così comincio a digitare from A import (se è in Python, diciamo) e vediamo cosa succede. Ma ciò significa che quello che vedo elencato deve riflettere le attività logiche che ho bisogno di prendere in prestito, e questo è ciò che deve essere nella base di codice. Innumerevoli metodi di aiuto che rendono più breve mi confondono.
  • Le librerie sono lì per il programmatore più inesperto che cerca di utilizzare un algoritmo di cui la maggior parte delle persone ha solo vagamente sentito parlare. Hanno bisogno di documentazione esterna, e questo ha bisogno di rispecchiare esattamente il codice, cosa che non può fare se continuiamo a refactoring di tutto per rendere felici i seguaci di short-method e do-one-thing.
  • Ogni metodo di prestito che le persone prendono in prestito potrebbe rompere il codice in tutto il mondo con conseguenze disastrose se viene rimosso o rinominato. Certo, vorrei che sklearn correggesse l'errore di battitura in Calinski-Harabasz , ma che potrebbe causare un altro incidente a sinistra . In effetti, nella mia esperienza il problema più grande dell'evoluzione delle librerie è quando si sforzano troppo per adottare dei "miglioramenti" di buon codice su come strutturano tutto.
  • In casa, i commenti sono in gran parte un male necessario nella migliore delle ipotesi, per tutti i motivi che non ho bisogno di rigurgitare (anche se questi punti esagerano un po '). Un buon commento dice perché il codice funziona, non come. Ma le biblioteche sanno che i loro lettori sono programmatori competenti che non possono, ad esempio, scrivere algebra lineare come uscire da un sacchetto di carta. In altre parole, tutto ha bisogno di commenti re: perché funziona! (OK, questa è un'altra esagerazione). Ecco perché vedete la linea della firma, il blocco di commenti di 100 righe, 1 riga di codice che potrebbe letteralmente essere andata sulla linea della firma (lingua permettendo, ovviamente).
  • Supponiamo che tu aggiorni qualcosa su Github e aspetti di vedere se il tuo codice sarà accettato. Deve essere chiaro il motivo per cui il tuo cambio di codice funziona. So per esperienza che il refactoring per rendere il campeggio più pulito come parte di un commit funzionale spesso significa un sacco di risparmio, riarrangiamento e ridenominazione della linea, il che rende più difficile il lavoro del tuo revisore sfrenato e causa altri problemi di cui sopra.

Sono sicuro che le persone con più esperienza di me possano menzionare altri punti.

    
risposta data 11.07.2018 - 20:51
fonte
2

Ci sono già molte buone risposte - voglio dare la prospettiva di un manutentore open source.

La mia prospettiva

Sono un manutentore di molti di questi progetti con meno di un grande codice. A volte mi viene persino impedito di migliorare tale codice a causa di problemi di compatibilità poiché le librerie vengono scaricate milioni di volte ogni settimana.

Rende più difficile il mantenimento - come membro principale di Node.js ci sono parti del codice che ho paura di toccare, ma c'è molto lavoro da fare a prescindere e le persone usano la piattaforma con successo e si divertono. La cosa più importante è che funzioni.

Codice leggibile

Quando dici:

I found the code in many of them to be far from the principles addressed to write clean code – e.g methods containing hundreds of lines of code.

Le righe di codice non sono una misura grande di come leggibile è. Nello studio che ho collegato al kernel di Linux è stato analizzato e un sondaggio di programmatori ha trovato codice "normale" (codice che la gente si aspetta fondamentalmente) e codice coerente per essere migliore di codice "pulito" in comprensibilità. Questo si allinea anche con la mia esperienza personale.

Alcuni progetti open source non sono troppo accoglienti

Linus "notoriamente" ha detto che linux non dovrebbe avere un debugger integrato perché le persone che usano i debugger non sono abbastanza bravi per lavorare su Linux e lui non vuole attrarne altri.

Personalmente non sono assolutamente d'accordo con la sua posizione - ma è anche qualcosa che le persone fanno.

    
risposta data 13.07.2018 - 14:35
fonte
1

Il software open source non significa necessariamente che siano coinvolti più autori. Quando un software (o un'unità di software) è scritto da un singolo autore, le funzioni lunghe appaiono frequentemente.

Questo deriva dalla natura del processo di sviluppo. Un semplice metodo viene esteso nel tempo, vengono aggiunte nuove funzionalità e corretto il bug.

I metodi lunghi riducono drasticamente la comprensione della funzionalità per i nuovi autori. Tuttavia, con un singolo autore questo è raramente un problema e il problema tende a essere trascurato. Un'altra natura dell'open source è il fatto che molti software non sono sviluppati attivamente, quindi non esiste alcun lavoro di refactoring che, ad esempio, suddivida metodi complessi in più metodi semplici.

Non hai mostrato alcun esempio, ma dalla mia comprensione questo è anche spesso collegato al linguaggio di sviluppo. Alcuni linguaggi applicano rigorose regole di linting sin dall'inizio e test di unità pesanti (o anche TDD). Sia i test di sfilacciamento che i test di unità di solito prevengono questo problema (è difficile testare complessi metodi complessi / lunghi).

In generale, è più difficile rendere il codice pulito se il software è sviluppato da un singolo autore e gli altri contributori stanno solo correggendo piccoli problemi.

    
risposta data 13.07.2018 - 15:07
fonte