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


80

Sono ancora inesperto a scrivere codice di alta qualità, quindi ho letto libri che trattano il problema come Clean Code di Robert C. Martin e continuo a controllare il codice di librerie famose per migliorare le mie capacità.

Sebbene molte librerie open source siano state mantenute per anni, il che significa che è molto improbabile che non siano sulla strada giusta, ho trovato il codice in molte di esse lontano dai principi indirizzati alla scrittura di codice pulito, ad esempio metodi contenenti centinaia di righe di codice.

Quindi la mia domanda è: i principi del codice pulito sono troppo limitati e possiamo farne a meno in molte librerie come queste? In caso contrario, come vengono gestite le enormi librerie senza considerare molti di questi principi?

Apprezzerò qualsiasi breve chiarimento. Mi scuso se la domanda sembra sciocca da un novizio.

MODIFICARE

Dai un'occhiata a questo esempio nella libreria Butterknife , una delle librerie più conosciute della community Android.


71
Soffri di un campione distorto. Dici di controllare il codice di librerie "ben note". Bene, le biblioteche che sono crollate sotto il loro stesso peso perché non stavano seguendo le migliori pratiche non sono "ben note", sono svanite nell'oscurità.
Jörg W Mittag,

3
Hai controllato ad es. Le fonti Linux?
Ripristina Monica - M. Schröder l'

55
La misura principale per un valore del software non è quanto "pulito" sia il codice, ma quanto soddisfa un determinato compito. Mentre ad alcune persone piace scrivere software per il solo scopo di scrivere qualcosa, per la maggior parte delle persone, il codice è solo un mezzo per raggiungere un fine.
whatsisname

3
Nessuno non è d'accordo con te. La domanda è: come mantenere un codice scadente per anni? Perché non è stato ripulito da quelle tante iterazioni dell'evoluzione?
Islam Salah,

13
La premessa della domanda (che i progetti open source a lungo mantenuti devono aderire intrinsecamente alla nozione di best practice di un particolare autore del libro) è completamente falsa e non so da dove l'hai presa. Potresti espandere la premessa della tua domanda, per favore?
Razze di leggerezza in orbita,

Risposte:


84

Buona risposta già qui, ma lasciami dire una parola sul tuo esempio di coltello a lama : anche se non ho idea di cosa faccia il codice, a prima vista, non mi sembra davvero irraggiungibile. Le variabili e i nomi dei metodi sembrano essere stati scelti deliberatamente, il codice è correttamente indentato 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 zio 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 facilmente "ripuliti" estraendo quei blocchi in metodi da soli (con un basso rischio di introdurre bug quando si usano strumenti di refactoring).

Il vero problema con tale codice è l'aggiunta di un blocco e un altro blocco e un altro blocco funziona in una certa misura, a volte nel corso degli anni. Ma ogni giorno il codice diventa più difficile da evolvere un po ', e ci vuole un po' più di 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 vorresti che qualcuno avesse iniziato a ripulire il codice più presto.


I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
yannis,

158

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

In particolare, la preferenza per i metodi brevi non è concordata da tutti. Se il codice in un metodo più lungo non viene ripetuto altrove, estrarne una parte 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 interessarsene. Quindi è un compromesso, non un miglioramento oggettivo.

I consigli nel libro sono anche (come tutti i consigli) orientati verso un particolare tipo di software: le applicazioni aziendali. Altri tipi di software come giochi o sistemi operativi hanno vincoli diversi rispetto al software aziendale, quindi sono in gioco modelli e principi di progettazione diversi.

Anche il linguaggio è un fattore: Clean Code presuppone Java o un linguaggio simile - se usi C o Lisp molti consigli non si applicano.

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

Per quanto riguarda i progetti open source, la qualità del codice varia da abissale a geniale. Dopotutto, chiunque può pubblicare il proprio codice come open source. Ma se guardi a un progetto open source maturo e di successo con più collaboratori, puoi essere abbastanza sicuro che si siano stabiliti consapevolmente su uno stile che funziona 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, poiché il codice di lavoro supera le opinioni.


18
+1 per "orientato verso un particolare tipo di software". Questo può essere esteso alla maggior parte dei libri su questo e argomenti simili. Prendi tutto ciò che leggi con un pizzico di sale, potrebbe essere distorto dal momento in cui è scritto, dall'ambiente di destinazione, dalla metodologia di sviluppo e da tutti i tipi di altri fattori.
Reginald Blue,

16
Seguire quel libro produce rigorosamente ciò che molti chiamano "codice spazzatura".
Frank Hileman,

16
@FrankHileman: non segue ancora nessuna delle raccomandazioni di quel libro.
Doc Brown,

5
@ jpmc26 - La tua risposta collegata riguarda un campo che conosco intimamente, la programmazione scientifica. Recentemente ho ottenuto un articolo della lista dei desideri che doveva rendere il modello gravitazionale usato in diverse simulazioni del Johnson Space Center relativamente relativisticamente corrette. Contando i commenti e le righe vuote, il codice che ho scritto che calcola la perturbazione relativistica alla gravità newtoniana è lungo 145 righe ed è tutto in una funzione. Normalmente mi farebbe rabbrividire nel vedere che io stesso ho scritto una funzione lunga 45 righe, figuriamoci 145. Ma non in questo caso. ...
David Hammen,

12
... La funzione in questione implementa una singola equazione, equazione X nel giornale Y, quindi segue sicuramente la regola del singolo scopo. (Che l'equazione copra un quarto di pagina è nei dettagli.) Non c'è posto significativo per dividere questa funzione in parti, e nessuna ragione significativa per farlo. I commenti, che lo zio Bob disprezza? Sono assolutamente necessari in questo caso, e questo è tipico nella programmazione scientifica. Sebbene sia utile vedere i riferimenti dei journal pertinenti nella documentazione TeX del modello, è anche utile visualizzarli nell'implementazione.
David Hammen,

34

Sommario

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 ti aspettavi probabilmente avranno semplicemente altri principi.

La mia prospettiva

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

  • la portata e l'architettura dei nostri prodotti,
  • il mercato di riferimento / aspettative dei clienti,
  • per quanto tempo vengono mantenuti i prodotti,
  • la metodologia di sviluppo che utilizziamo,
  • la struttura organizzativa della nostra azienda e
  • abitudini, opinioni ed esperienze passate dei nostri sviluppatori.

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

Detto questo, credo che per essere in grado di mantenere con successo basi di codice di grandi dimensioni nel corso degli anni, ogni squadra dovrebbe concordare una serie di convenzioni di codice che ritengono adatte agli aspetti sopra indicati. Ciò può significare adottare pratiche di Robert C. Martin, di un altro autore o inventarne le proprie; può significare scriverli formalmente o documentarli "per esempio". Ma dovrebbero esistere.

Esempio

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

Robert C. Martin dice che questo stile permette di limitare il contenuto di ogni metodo per un livello di astrazione - come un esempio semplificato, un metodo pubblico sarebbe probabilmente consistere solo di chiamate ai metodi privati come verifyInput(...), loadDataFromHardDisk(...), transformDataToJson(...)e, infine sendJsonToClient(...), e questi metodi avrebbe i dettagli di implementazione.

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

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


13

Molte librerie open source soffrono infatti di pratiche di codifica obiettivamente scarse e sono gestite con difficoltà da un piccolo gruppo di collaboratori a lungo termine che possono gestire la scarsa leggibilità perché conoscono molto bene le parti del codice che mantengono più frequentemente . Il refactoring del codice per migliorare la leggibilità dopo il fatto è spesso uno sforzo erculeo perché tutti devono essere sulla stessa pagina, non è divertente e non paga perché non sono implementate nuove funzionalità.

Come altri hanno già detto, qualsiasi libro sul codice pulito che afferma qualcosa contiene necessariamente consigli che non sono universalmente concordati. In particolare, quasi ogni regola può essere seguita 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 funzioni e nessun dato scrivibile a livello globale. Cercare di abbattere una funzione molto complessa in funzioni più piccole spesso porta a elenchi di argomenti molto lunghi quando la funzione era davvero complessa. La creazione e il mantenimento di un codice leggibile è un esercizio di equilibrio tra regole di buonsenso reciprocamente contrastanti. Leggere libri è buono, ma solo l'esperienza ti insegnerà come trovare la falsa complessità , che è il luogo in cui si ottengono i veri guadagni di leggibilità.


2
Vorrei aggiungere: semplicemente perché qualcosa è "open source" non significa che chiunque sia un collaboratore. Spesso molti progetti open source sono gestiti da cricche, nel bene e nel male, che isolano il loro progetto da altri collaboratori e, a meno che non venga biforcuto, nessun altro contribuisce. Se non viene biforcato, sia perché nessuno ha bisogno di modificarlo o perché nessuno può capire come farlo, probabilmente lo stile convenzionale del codice rimarrà invariato.
can-ned_food,

7

La maggior parte dei progetti open source sono gestiti male. Ci sono ovviamente 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 utilizzato. Queste persone hanno cose migliori da fare con il loro tempo, come il loro effettivo lavoro retribuito.

All'inizio il codice è opera di una persona ed è probabilmente piccolo. E il codice piccolo non deve essere pulito. O meglio, lo sforzo necessario per rendere pulito il codice è maggiore del vantaggio.

Col passare del tempo, il codice è più un mucchio di patch di molte persone diverse. Gli autori di patch non sentono la proprietà del codice, vogliono solo aggiungere questa funzionalità o correggere questo bug nel modo più semplice possibile.

Il proprietario non ha il tempo di ripulire le cose e a nessuno importa.

E il codice sta diventando grande. E brutto.

Man mano 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 in altri punti del codice.

A questo punto non è solo che alle persone non importa, non osano più ripulire poiché hanno paura di rompere le cose.

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

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


23
Se elimini le parole "open" e "source" in questa risposta, continuerà ad essere altrettanto vero.
Stephen M. Webb,

Direi che questo è altrettanto vero per il software a sorgente chiuso.
Mark Rotteveel,

3

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

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

Questo ovviamente ci porta anche alla " normalizzazione della devianza " che porta a situazioni come Heartbleed , dove, proprio come per rispondere alla tua domanda, un imponente e invaso mucchio di spaghetti di codice open source chiamato OpenSSL è diventato " non pulito " per qualcosa come dieci anni , finendo con un enorme difetto di sicurezza che colpisce migliaia di milioni di persone .

La soluzione era inventare un sistema completamente nuovo chiamato LibreSSL , che avrebbe usato il codice clean-ish , e ovviamente quasi nessuno lo utilizza .

Quindi, come vengono mantenuti enormi progetti open source mal codificati? La risposta è nella domanda Molti di loro non sono mantenuti in uno stato pulito. Sono patchati in modo casuale da migliaia di persone diverse per coprire casi d'uso su varie macchine e situazioni sconosciute su cui gli sviluppatori non avranno mai accesso. Il codice funziona "abbastanza bene" fino a quando non lo fa , quando tutti vanno nel panico e decidono di buttare soldi per il problema .

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

La risposta è che non dovresti. O lo fai o non lo fai , e il mondo continua a girare a prescindere, perché la natura umana non cambia sulla scala di una vita umana . Personalmente, provo solo a scrivere codice pulito perché mi piace il modo in cui ci si sente a farlo.


1
Così tanti link ... a prima vista pensavo che questa risposta potesse essere stata intrecciata con la pubblicità al passaggio del mouse o che fosse una pagina di Wikipedia.
Jonny Henly,

2

Ciò che costituisce un buon codice dipende dal contesto, e i libri classici che ti guidano su questo sono, se non troppo vecchi per discutere di open-source, almeno parte di una tradizione che conduce la guerra infinita contro cattive basi di codici interni. 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 mi serve per qualsiasi cosa stia lavorando, a meno che non stia copiando ciò che un La risposta di Stack Exchange mi ha detto di fare. Quindi inizio a digitare from A import(se è in Python, diciamo) e vedo cosa succede. Ciò significa che ciò che vedo elencato deve riflettere le attività logiche che dovrò prendere in prestito, ed è quello che deve essere nella base di codice. Innumerevoli metodi di aiuto che lo rendono più breve mi confonderanno.
  • Le biblioteche sono lì per il programmatore più inesperto che cerca di usare un algoritmo di cui la maggior parte delle persone ha solo vagamente sentito parlare. Hanno bisogno di documentazione esterna, e questo deve rispecchiare con precisione il codice, cosa che non può fare se continuiamo a refactoring di tutto per rendere felici gli aderenti con metodi brevi e una cosa sola.
  • Ogni metodo di biblioteca che le persone prendono in prestito potrebbe rompere il codice in tutto il mondo con conseguenze disastrose se viene rimosso o addirittura rinominato. Certo, vorrei che Sklearn correggesse l'errore di battitura in Calinski-Harabasz , ma ciò potrebbe causare un altro incidente con il pad sinistro . In effetti, nella mia esperienza il problema più grande con l'evoluzione delle biblioteche è quando si sforzano troppo di adottare un nuovo "miglioramento" di buon codice su come strutturare tutto.
  • In-house, i commenti sono in gran parte un male necessario nella migliore delle ipotesi, per tutti i tipi di ragioni che non ho bisogno di rigurgitare (anche se quei punti esagerano in qualche modo). Un buon commento dice perché il codice funziona, non come. Ma le biblioteche sanno che i loro lettori sono programmatori competenti che non potrebbero, per esempio, scrivere algebra lineare in uscita da un sacchetto di carta. In altre parole, tutto ha bisogno di essere commentato: perché funziona! (OK, questa è un'altra esagerazione.) Ecco perché vedi una riga della firma, un blocco di commenti di 100 righe, 1 riga di codice che potrebbe letteralmente essere passata sulla riga della firma (lingua permettendo, ovviamente).
  • Diciamo che aggiorni qualcosa su Github e attendi per vedere se il tuo codice verrà accettato. Deve essere chiaro il motivo per cui la modifica del codice funziona. So per esperienza che il refactoring per rendere il campeggio più pulito come parte di un commit funzionale spesso implica un sacco di salvataggio, riordino e ridenominazione della linea, il che rende più difficile il lavoro del revisore senza stipendio e causa altri problemi di cui sopra.

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


Informazioni sul primo punto elenco. Ecco perché hai metodi pubblici / privati. Esponi API pubbliche che chiamano internamente metodi privati ​​o interni. Anche il secondo punto elenco non è preciso. Non vedo alcun motivo per cui non è possibile avere documentazione su un metodo pubblico breve e quindi chiamare molti piccoli.
FCin

@FCin Questo è l'approccio praticabile, a condizione che i manutentori ricordino di usare sempre la parola chiave corretta di fronte a ogni singolo metodo man mano che vanno e vengono. Oppure potrebbero semplicemente fare qualcosa che è più facile e meno soggetto a errori.
JG,

In linguaggi come C #, Java (di cui parla di solito lo zio Bob), i modificatori di accesso sono lo strumento più basilare usato per scrivere davvero qualsiasi codice. L'uso della parola chiave corretta fa parte della scrittura di qualsiasi codice.
FCin

@FCin Sono meno frequentemente resi espliciti in alcune altre lingue, ma ho lavorato anche su basi di codice C # interne in cui le persone non necessariamente utilizzavano i modificatori che avrebbero dovuto avere.
JG

Ecco perché dovrebbero leggere il libro di Zio Bob :)
FCin

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 un codice non eccezionale. 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 temo di toccare, ma c'è molto lavoro da fare indipendentemente e le persone usano la piattaforma con successo e si divertono. La cosa più importante è che funzioni.

Su codice leggibile

Quando dici:

Ho trovato il codice in molti di essi lontano dai principi indirizzati alla scrittura di codice pulito, ad esempio metodi contenenti centinaia di righe di codice.

Le righe di codice non sono una grande misura di quanto sia leggibile. Nello studio che ho collegato al kernel Linux è stato analizzato e un sondaggio di programmatori ha scoperto che il codice "normale" (codice che la gente si aspetta sostanzialmente) e il codice coerente sono migliori del codice "pulito" nella 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 brave da lavorare su Linux e non vuole attrarne di più.

Personalmente non sono assolutamente d'accordo con la sua posizione lì, ma è anche qualcosa che la gente fa.


1

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

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

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, dividerebbe metodi complessi in più metodi semplici.

Non hai mostrato alcun esempio, ma dalla mia comprensione questo è spesso collegato al linguaggio di sviluppo. Alcuni linguaggi impongono fin dall'inizio rigide regole di sfilacciatura e test di unità pesanti (o persino TDD). Sia il linting che i test unitari di solito impediscono tale problema (è difficile testare metodi complessi / lunghi).

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

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.