451 lines
25 KiB
ReStructuredText
451 lines
25 KiB
ReStructuredText
.. include:: ../disclaimer-ita.rst
|
||
|
||
:Original: :ref:`Documentation/process/4.Coding.rst <development_coding>`
|
||
:Translator: Alessia Mantegazza <amantegazza@vaga.pv.it>
|
||
|
||
.. _it_development_coding:
|
||
|
||
Scrivere codice corretto
|
||
========================
|
||
|
||
Nonostante ci sia molto da dire sul processo di creazione, sulla sua solidità
|
||
e sul suo orientamento alla comunità, la prova di ogni progetto di sviluppo
|
||
del kernel si trova nel codice stesso. È il codice che sarà esaminato dagli
|
||
altri sviluppatori ed inserito (o no) nel ramo principale. Quindi è la
|
||
qualità di questo codice che determinerà il successo finale del progetto.
|
||
|
||
Questa sezione esaminerà il processo di codifica. Inizieremo con uno sguardo
|
||
sulle diverse casistiche nelle quali gli sviluppatori kernel possono
|
||
sbagliare. Poi, l'attenzione si sposterà verso "il fare le cose
|
||
correttamente" e sugli strumenti che possono essere utili in questa missione.
|
||
|
||
Trappole
|
||
--------
|
||
|
||
Lo stile del codice
|
||
*******************
|
||
|
||
Il kernel ha da tempo delle norme sullo stile di codifica che sono descritte in
|
||
:ref:`Documentation/translations/it_IT/process/coding-style.rst <codingstyle>`.
|
||
Per la maggior parte del tempo, la politica descritta in quel file è stata
|
||
praticamente informativa. Ne risulta che ci sia una quantità sostanziale di
|
||
codice nel kernel che non rispetta le linee guida relative allo stile.
|
||
La presenza di quel codice conduce a due distinti pericoli per gli
|
||
sviluppatori kernel.
|
||
|
||
Il primo di questi è credere che gli standard di codifica del kernel
|
||
non sono importanti e possono non essere applicati. La verità è che
|
||
aggiungere nuovo codice al kernel è davvero difficile se questo non
|
||
rispetta le norme; molti sviluppatori richiederanno che il codice sia
|
||
riformulato prima che anche solo lo revisionino. Una base di codice larga
|
||
quanto il kernel richiede una certa uniformità, in modo da rendere possibile
|
||
per gli sviluppatori una comprensione veloce di ogni sua parte. Non ci sono,
|
||
quindi, più spazi per un codice formattato alla carlona.
|
||
|
||
Occasionalmente, lo stile di codifica del kernel andrà in conflitto con lo
|
||
stile richiesto da un datore di lavoro. In alcuni casi, lo stile del kernel
|
||
dovrà prevalere prima che il codice venga inserito. Mettere il codice
|
||
all'interno del kernel significa rinunciare a un certo grado di controllo
|
||
in differenti modi - incluso il controllo sul come formattare il codice.
|
||
|
||
L’altra trappola è quella di pensare che il codice già presente nel kernel
|
||
abbia urgentemente bisogno di essere sistemato. Gli sviluppatori potrebbero
|
||
iniziare a generare patch che correggono lo stile come modo per prendere
|
||
famigliarità con il processo, o come modo per inserire i propri nomi nei
|
||
changelog del kernel – o entrambe. La comunità di sviluppo vede un attività
|
||
di codifica puramente correttiva come "rumore"; queste attività riceveranno
|
||
una fredda accoglienza. Di conseguenza è meglio evitare questo tipo di patch.
|
||
Mentre si lavora su un pezzo di codice è normale correggerne anche lo stile,
|
||
ma le modifiche di stile non dovrebbero essere fatte fini a se stesse.
|
||
|
||
Il documento sullo stile del codice non dovrebbe essere letto come una legge
|
||
assoluta che non può mai essere trasgredita. Se c’è un a buona ragione
|
||
(per esempio, una linea che diviene poco leggibile se divisa per rientrare
|
||
nel limite di 80 colonne), fatelo e basta.
|
||
|
||
Notate che potete utilizzare lo strumento “clang-format” per aiutarvi con
|
||
le regole, per una riformattazione automatica e veloce del vostro codice
|
||
e per revisionare interi file per individuare errori nello stile di codifica,
|
||
refusi e possibili miglioramenti. Inoltre è utile anche per classificare gli
|
||
``#includes``, per allineare variabili/macro, per testi derivati ed altri
|
||
compiti del genere. Consultate il file
|
||
:ref:`Documentation/translations/it_IT/process/clang-format.rst <clangformat>`
|
||
per maggiori dettagli
|
||
|
||
Se utilizzate un programma compatibile con EditorConfig, allora alcune
|
||
configurazioni basilari come l'indentazione e la fine delle righe verranno
|
||
applicate automaticamente. Per maggiori informazioni consultate la pagina:
|
||
https://editorconfig.org/
|
||
|
||
Livelli di astrazione
|
||
*********************
|
||
|
||
|
||
I professori di Informatica insegnano ai propri studenti a fare ampio uso dei
|
||
livelli di astrazione nel nome della flessibilità e del nascondere informazioni.
|
||
Certo il kernel fa un grande uso dell'astrazione; nessun progetto con milioni
|
||
di righe di codice potrebbe fare altrimenti e sopravvivere. Ma l'esperienza
|
||
ha dimostrato che un'eccessiva o prematura astrazione può rivelarsi dannosa
|
||
al pari di una prematura ottimizzazione. L'astrazione dovrebbe essere usata
|
||
fino al livello necessario e non oltre.
|
||
|
||
Ad un livello base, considerate una funzione che ha un argomento che viene
|
||
sempre impostato a zero da tutti i chiamanti. Uno potrebbe mantenere
|
||
quell'argomento nell'eventualità qualcuno volesse sfruttare la flessibilità
|
||
offerta. In ogni caso, tuttavia, ci sono buone possibilità che il codice
|
||
che va ad implementare questo argomento aggiuntivo, sia stato rotto in maniera
|
||
sottile, in un modo che non è mai stato notato - perché non è mai stato usato.
|
||
Oppure, quando sorge la necessità di avere più flessibilità, questo argomento
|
||
non la fornisce in maniera soddisfacente. Gli sviluppatori di Kernel,
|
||
sottopongono costantemente patch che vanno a rimuovere gli argomenti
|
||
inutilizzate; anche se, in generale, non avrebbero dovuto essere aggiunti.
|
||
|
||
I livelli di astrazione che nascondono l'accesso all'hardware -
|
||
spesso per poter usare dei driver su diversi sistemi operativi - vengono
|
||
particolarmente disapprovati. Tali livelli oscurano il codice e possono
|
||
peggiorare le prestazioni; essi non appartengono al kernel Linux.
|
||
|
||
D'altro canto, se vi ritrovate a dover copiare una quantità significativa di
|
||
codice proveniente da un altro sottosistema del kernel, è tempo di chiedersi
|
||
se, in effetti, non avrebbe più senso togliere parte di quel codice e metterlo
|
||
in una libreria separata o di implementare quella funzionalità ad un livello
|
||
più elevato. Non c'è utilità nel replicare lo stesso codice per tutto
|
||
il kernel.
|
||
|
||
|
||
#ifdef e l'uso del preprocessore in generale
|
||
********************************************
|
||
|
||
Il preprocessore C sembra essere una fonte di attrazione per qualche
|
||
programmatore C, che ci vede una via per ottenere una grande flessibilità
|
||
all'interno di un file sorgente. Ma il preprocessore non è scritto in C,
|
||
e un suo massiccio impiego conduce a un codice che è molto più difficile
|
||
da leggere per gli altri e che rende più difficile il lavoro di verifica del
|
||
compilatore. L'uso eccessivo del preprocessore è praticamente sempre il segno
|
||
di un codice che necessita di un certo lavoro di pulizia.
|
||
|
||
La compilazione condizionata con #ifdef è, in effetti, un potente strumento,
|
||
ed esso viene usato all'interno del kernel. Ma esiste un piccolo desiderio:
|
||
quello di vedere il codice coperto solo da una leggera spolverata di
|
||
blocchi #ifdef. Come regola generale, quando possibile, l'uso di #ifdef
|
||
dovrebbe essere confinato nei file d'intestazione. Il codice compilato
|
||
condizionatamente può essere confinato a funzioni tali che, nel caso in cui
|
||
il codice non deve essere presente, diventano vuote. Il compilatore poi
|
||
ottimizzerà la chiamata alla funzione vuota rimuovendola. Il risultato è
|
||
un codice molto più pulito, più facile da seguire.
|
||
|
||
Le macro del preprocessore C presentano una serie di pericoli, inclusi
|
||
valutazioni multiple di espressioni che hanno effetti collaterali e non
|
||
garantiscono una sicurezza rispetto ai tipi. Se siete tentati dal definire
|
||
una macro, considerate l'idea di creare invece una funzione inline. Il codice
|
||
che ne risulterà sarà lo stesso, ma le funzioni inline sono più leggibili,
|
||
non considerano i propri argomenti più volte, e permettono al compilatore di
|
||
effettuare controlli sul tipo degli argomenti e del valore di ritorno.
|
||
|
||
|
||
Funzioni inline
|
||
***************
|
||
|
||
Comunque, anche le funzioni inline hanno i loro pericoli. I programmatori
|
||
potrebbero innamorarsi dell'efficienza percepita derivata dalla rimozione
|
||
di una chiamata a funzione. Queste funzioni, tuttavia, possono ridurre le
|
||
prestazioni. Dato che il loro codice viene replicato ovunque vi sia una
|
||
chiamata ad esse, si finisce per gonfiare le dimensioni del kernel compilato.
|
||
Questi, a turno, creano pressione sulla memoria cache del processore, e questo
|
||
può causare rallentamenti importanti. Le funzioni inline, di norma, dovrebbero
|
||
essere piccole e usate raramente. Il costo di una chiamata a funzione, dopo
|
||
tutto, non è così alto; la creazione di molte funzioni inline è il classico
|
||
esempio di un'ottimizzazione prematura.
|
||
|
||
In generale, i programmatori del kernel ignorano gli effetti della cache a
|
||
loro rischio e pericolo. Il classico compromesso tempo/spazio teorizzato
|
||
all'inizio delle lezioni sulle strutture dati spesso non si applica
|
||
all'hardware moderno. Lo spazio *è* tempo, in questo senso un programma
|
||
più grande sarà più lento rispetto ad uno più compatto.
|
||
|
||
I compilatori più recenti hanno preso un ruolo attivo nel decidere se
|
||
una data funzione deve essere resa inline oppure no. Quindi l'uso
|
||
indiscriminato della parola chiave "inline" potrebbe non essere non solo
|
||
eccessivo, ma anche irrilevante.
|
||
|
||
Sincronizzazione
|
||
****************
|
||
|
||
Nel maggio 2006, il sistema di rete "Devicescape" fu rilasciato in pompa magna
|
||
sotto la licenza GPL e reso disponibile per la sua inclusione nella ramo
|
||
principale del kernel. Questa donazione fu una notizia bene accolta;
|
||
il supporto per le reti senza fili era considerata, nel migliore dei casi,
|
||
al di sotto degli standard; il sistema Deviscape offrì la promessa di una
|
||
risoluzione a tale situazione. Tuttavia, questo codice non fu inserito nel
|
||
ramo principale fino al giugno del 2007 (2.6.22). Cosa accadde?
|
||
|
||
Quel codice mostrava numerosi segnali di uno sviluppo in azienda avvenuto
|
||
a porte chiuse. Ma in particolare, un grosso problema fu che non fu
|
||
progettato per girare in un sistema multiprocessore. Prima che questo
|
||
sistema di rete (ora chiamato mac80211) potesse essere inserito, fu necessario
|
||
un lavoro sugli schemi di sincronizzazione.
|
||
|
||
Una volta, il codice del kernel Linux poteva essere sviluppato senza pensare
|
||
ai problemi di concorrenza presenti nei sistemi multiprocessore. Ora,
|
||
comunque, questo documento è stato scritto su di un portatile dual-core.
|
||
Persino su sistemi a singolo processore, il lavoro svolto per incrementare
|
||
la capacità di risposta aumenterà il livello di concorrenza interno al kernel.
|
||
I giorni nei quali il codice poteva essere scritto senza pensare alla
|
||
sincronizzazione sono da passati tempo.
|
||
|
||
Ogni risorsa (strutture dati, registri hardware, etc.) ai quali si potrebbe
|
||
avere accesso simultaneo da più di un thread deve essere sincronizzato. Il
|
||
nuovo codice dovrebbe essere scritto avendo tale accortezza in testa;
|
||
riadattare la sincronizzazione a posteriori è un compito molto più difficile.
|
||
Gli sviluppatori del kernel dovrebbero prendersi il tempo di comprendere bene
|
||
le primitive di sincronizzazione, in modo da sceglier lo strumento corretto
|
||
per eseguire un compito. Il codice che presenta una mancanza di attenzione
|
||
alla concorrenza avrà un percorso difficile all'interno del ramo principale.
|
||
|
||
Regressioni
|
||
***********
|
||
|
||
Vale la pena menzionare un ultimo pericolo: potrebbe rivelarsi accattivante
|
||
l'idea di eseguire un cambiamento (che potrebbe portare a grandi
|
||
miglioramenti) che porterà ad alcune rotture per gli utenti esistenti.
|
||
Questa tipologia di cambiamento è chiamata "regressione", e le regressioni son
|
||
diventate mal viste nel ramo principale del kernel. Con alcune eccezioni,
|
||
i cambiamenti che causano regressioni saranno fermati se quest'ultime non
|
||
potranno essere corrette in tempo utile. È molto meglio quindi evitare
|
||
la regressione fin dall'inizio.
|
||
|
||
Spesso si è argomentato che una regressione può essere giustificata se essa
|
||
porta risolve più problemi di quanti non ne crei. Perché, dunque, non fare
|
||
un cambiamento se questo porta a nuove funzionalità a dieci sistemi per
|
||
ognuno dei quali esso determina una rottura? La migliore risposta a questa
|
||
domanda ci è stata fornita da Linus nel luglio 2007:
|
||
|
||
::
|
||
Dunque, noi non sistemiamo bachi introducendo nuovi problemi. Quella
|
||
via nasconde insidie, e nessuno può sapere del tutto se state facendo
|
||
dei progressi reali. Sono due passi avanti e uno indietro, oppure
|
||
un passo avanti e due indietro?
|
||
|
||
(http://lwn.net/Articles/243460/).
|
||
|
||
Una particolare tipologia di regressione mal vista consiste in una qualsiasi
|
||
sorta di modifica all'ABI dello spazio utente. Una volta che un'interfaccia
|
||
viene esportata verso lo spazio utente, dev'essere supportata all'infinito.
|
||
Questo fatto rende la creazione di interfacce per lo spazio utente
|
||
particolarmente complicato: dato che non possono venir cambiate introducendo
|
||
incompatibilità, esse devono essere fatte bene al primo colpo. Per questa
|
||
ragione sono sempre richieste: ampie riflessioni, documentazione chiara e
|
||
ampie revisioni dell'interfaccia verso lo spazio utente.
|
||
|
||
|
||
Strumenti di verifica del codice
|
||
--------------------------------
|
||
Almeno per ora la scrittura di codice priva di errori resta un ideale
|
||
irraggiungibile ai più. Quello che speriamo di poter fare, tuttavia, è
|
||
trovare e correggere molti di questi errori prima che il codice entri nel
|
||
ramo principale del kernel. A tal scopo gli sviluppatori del kernel devono
|
||
mettere insieme una schiera impressionante di strumenti che possano
|
||
localizzare automaticamente un'ampia varietà di problemi. Qualsiasi problema
|
||
trovato dal computer è un problema che non affliggerà l'utente in seguito,
|
||
ne consegue che gli strumenti automatici dovrebbero essere impiegati ovunque
|
||
possibile.
|
||
|
||
Il primo passo consiste semplicemente nel fare attenzione agli avvertimenti
|
||
proveniente dal compilatore. Versioni moderne di gcc possono individuare
|
||
(e segnalare) un gran numero di potenziali errori. Molto spesso, questi
|
||
avvertimenti indicano problemi reali. Di regola, il codice inviato per la
|
||
revisione non dovrebbe produrre nessun avvertimento da parte del compilatore.
|
||
Per mettere a tacere gli avvertimenti, cercate di comprenderne le cause reali
|
||
e cercate di evitare le "riparazioni" che fan sparire l'avvertimento senza
|
||
però averne trovato la causa.
|
||
|
||
Tenete a mente che non tutti gli avvertimenti sono disabilitati di default.
|
||
Costruite il kernel con "make KCFLAGS=-W" per ottenerli tutti.
|
||
|
||
Il kernel fornisce differenti opzioni che abilitano funzionalità di debugging;
|
||
molti di queste sono trovano all'interno del sotto menu "kernel hacking".
|
||
La maggior parte di queste opzioni possono essere attivate per qualsiasi
|
||
kernel utilizzato per lo sviluppo o a scopo di test. In particolare dovreste
|
||
attivare:
|
||
|
||
- FRAME_WARN per ottenere degli avvertimenti su stack frame più
|
||
grandi di un dato valore. Il risultato generato da questi
|
||
avvertimenti può risultare verboso, ma non bisogna preoccuparsi per
|
||
gli avvertimenti provenienti da altre parti del kernel.
|
||
|
||
- DEBUG_OBJECTS aggiungerà un codice per tracciare il ciclo di vita di
|
||
diversi oggetti creati dal kernel e avvisa quando qualcosa viene eseguito
|
||
fuori controllo. Se state aggiungendo un sottosistema che crea (ed
|
||
esporta) oggetti complessi propri, considerate l'aggiunta di un supporto
|
||
al debugging dell'oggetto.
|
||
|
||
- DEBUG_SLAB può trovare svariati errori di uso e di allocazione di memoria;
|
||
esso dovrebbe esser usato dalla maggior parte dei kernel di sviluppo.
|
||
|
||
- DEBUG_SPINLOCK, DEBUG_ATOMIC_SLEEP, e DEBUG_MUTEXES troveranno un certo
|
||
numero di errori comuni di sincronizzazione.
|
||
|
||
Esistono ancora delle altre opzioni di debugging, di alcune di esse
|
||
discuteremo qui sotto. Alcune di esse hanno un forte impatto e non dovrebbero
|
||
essere usate tutte le volte. Ma qualche volta il tempo speso nell'capire
|
||
le opzioni disponibili porterà ad un risparmio di tempo nel breve termine.
|
||
|
||
Uno degli strumenti di debugging più tosti è il *locking checker*, o
|
||
"lockdep". Questo strumento traccerà qualsiasi acquisizione e rilascio di
|
||
ogni *lock* (spinlock o mutex) nel sistema, l'ordine con il quale i *lock*
|
||
sono acquisiti in relazione l'uno con l'altro, l'ambiente corrente di
|
||
interruzione, eccetera. Inoltre esso può assicurare che i *lock* vengano
|
||
acquisiti sempre nello stesso ordine, che le stesse assunzioni sulle
|
||
interruzioni si applichino in tutte le occasioni, e così via. In altre parole,
|
||
lockdep può scovare diversi scenari nei quali il sistema potrebbe, in rari
|
||
casi, trovarsi in stallo. Questa tipologia di problema può essere grave
|
||
(sia per gli sviluppatori che per gli utenti) in un sistema in uso; lockdep
|
||
permette di trovare tali problemi automaticamente e in anticipo.
|
||
|
||
In qualità di programmatore kernel diligente, senza dubbio, dovrete controllare
|
||
il valore di ritorno di ogni operazione (come l'allocazione della memoria)
|
||
poiché esso potrebbe fallire. Il nocciolo della questione è che i percorsi
|
||
di gestione degli errori, con grande probabilità, non sono mai stati
|
||
collaudati del tutto. Il codice collaudato tende ad essere codice bacato;
|
||
potrete quindi essere più a vostro agio con il vostro codice se tutti questi
|
||
percorsi fossero stati verificati un po' di volte.
|
||
|
||
Il kernel fornisce un framework per l'inserimento di fallimenti che fa
|
||
esattamente al caso, specialmente dove sono coinvolte allocazioni di memoria.
|
||
Con l'opzione per l'inserimento dei fallimenti abilitata, una certa percentuale
|
||
di allocazione di memoria sarà destinata al fallimento; questi fallimenti
|
||
possono essere ridotti ad uno specifico pezzo di codice. Procedere con
|
||
l'inserimento dei fallimenti attivo permette al programmatore di verificare
|
||
come il codice risponde quando le cose vanno male. Consultate:
|
||
Documentation/fault-injection/fault-injection.rst per avere maggiori
|
||
informazioni su come utilizzare questo strumento.
|
||
|
||
Altre tipologie di errori possono essere riscontrati con lo strumento di
|
||
analisi statica "sparse". Con Sparse, il programmatore può essere avvisato
|
||
circa la confusione tra gli indirizzi dello spazio utente e dello spazio
|
||
kernel, un miscuglio fra quantità big-endian e little-endian, il passaggio
|
||
di un valore intero dove ci sia aspetta un gruppo di flag, e così via.
|
||
Sparse deve essere installato separatamente (se il vostra distribuzione non
|
||
lo prevede, potete trovarlo su https://sparse.wiki.kernel.org/index.php/Main_Page);
|
||
può essere attivato sul codice aggiungendo "C=1" al comando make.
|
||
|
||
Lo strumento "Coccinelle" (http://coccinelle.lip6.fr/) è in grado di trovare
|
||
una vasta varietà di potenziali problemi di codifica; e può inoltre proporre
|
||
soluzioni per risolverli. Un buon numero di "patch semantiche" per il kernel
|
||
sono state preparate nella cartella scripts/coccinelle; utilizzando
|
||
"make coccicheck" esso percorrerà tali patch semantiche e farà rapporto su
|
||
qualsiasi problema trovato. Per maggiori informazioni, consultate
|
||
:ref:`Documentation/dev-tools/coccinelle.rst <devtools_coccinelle>`.
|
||
|
||
Altri errori di portabilità sono meglio scovati compilando il vostro codice
|
||
per altre architetture. Se non vi accade di avere un sistema S/390 o una
|
||
scheda di sviluppo Blackfin sotto mano, potete comunque continuare la fase
|
||
di compilazione. Un vasto numero di cross-compilatori per x86 possono
|
||
essere trovati al sito:
|
||
|
||
http://www.kernel.org/pub/tools/crosstool/
|
||
|
||
Il tempo impiegato nell'installare e usare questi compilatori sarà d'aiuto
|
||
nell'evitare situazioni imbarazzanti nel futuro.
|
||
|
||
|
||
Documentazione
|
||
--------------
|
||
|
||
La documentazione è spesso stata più un'eccezione che una regola nello
|
||
sviluppo del kernel. Nonostante questo, un'adeguata documentazione aiuterà
|
||
a facilitare l'inserimento di nuovo codice nel kernel, rende la vita più
|
||
facile per gli altri sviluppatori e sarà utile per i vostri utenti. In molti
|
||
casi, la documentazione è divenuta sostanzialmente obbligatoria.
|
||
|
||
La prima parte di documentazione per qualsiasi patch è il suo changelog.
|
||
Questi dovrebbero descrivere le problematiche risolte, la tipologia di
|
||
soluzione, le persone che lavorano alla patch, ogni effetto rilevante
|
||
sulle prestazioni e tutto ciò che può servire per la comprensione della
|
||
patch. Assicuratevi che il changelog dica *perché*, vale la pena aggiungere
|
||
la patch; un numero sorprendente di sviluppatori sbaglia nel fornire tale
|
||
informazione.
|
||
|
||
Qualsiasi codice che aggiunge una nuova interfaccia in spazio utente - inclusi
|
||
nuovi file in sysfs o /proc - dovrebbe includere la documentazione di tale
|
||
interfaccia così da permette agli sviluppatori dello spazio utente di sapere
|
||
con cosa stanno lavorando. Consultate: Documentation/ABI/README per avere una
|
||
descrizione di come questi documenti devono essere impostati e quali
|
||
informazioni devono essere fornite.
|
||
|
||
Il file :ref:`Documentation/translations/it_IT/admin-guide/kernel-parameters.rst <kernelparameters>`
|
||
descrive tutti i parametri di avvio del kernel. Ogni patch che aggiunga
|
||
nuovi parametri dovrebbe aggiungere nuove voci a questo file.
|
||
|
||
Ogni nuova configurazione deve essere accompagnata da un testo di supporto
|
||
che spieghi chiaramente le opzioni e spieghi quando l'utente potrebbe volerle
|
||
selezionare.
|
||
|
||
Per molti sottosistemi le informazioni sull'API interna sono documentate sotto
|
||
forma di commenti formattati in maniera particolare; questi commenti possono
|
||
essere estratti e formattati in differenti modi attraverso lo script
|
||
"kernel-doc". Se state lavorando all'interno di un sottosistema che ha
|
||
commenti kerneldoc dovreste mantenerli e aggiungerli, in maniera appropriata,
|
||
per le funzioni disponibili esternamente. Anche in aree che non sono molto
|
||
documentate, non c'è motivo per non aggiungere commenti kerneldoc per il
|
||
futuro; infatti, questa può essere un'attività utile per sviluppatori novizi
|
||
del kernel. Il formato di questi commenti, assieme alle informazione su come
|
||
creare modelli per kerneldoc, possono essere trovati in
|
||
:ref:`Documentation/translations/it_IT/doc-guide/ <doc_guide>`.
|
||
|
||
Chiunque legga un ammontare significativo di codice kernel noterà che, spesso,
|
||
i commenti si fanno maggiormente notare per la loro assenza. Ancora una volta,
|
||
le aspettative verso il nuovo codice sono più alte rispetto al passato;
|
||
inserire codice privo di commenti sarà più difficile. Detto ciò, va aggiunto
|
||
che non si desiderano commenti prolissi per il codice. Il codice dovrebbe
|
||
essere, di per sé, leggibile, con dei commenti che spieghino gli aspetti più
|
||
sottili.
|
||
|
||
Determinate cose dovrebbero essere sempre commentate. L'uso di barriere
|
||
di memoria dovrebbero essere accompagnate da una riga che spieghi perché sia
|
||
necessaria. Le regole di sincronizzazione per le strutture dati, generalmente,
|
||
necessitano di una spiegazioni da qualche parte. Le strutture dati più
|
||
importanti, in generale, hanno bisogno di una documentazione onnicomprensiva.
|
||
Le dipendenze che non sono ovvie tra bit separati di codice dovrebbero essere
|
||
indicate. Tutto ciò che potrebbe indurre un inserviente del codice a fare
|
||
una "pulizia" incorretta, ha bisogno di un commento che dica perché è stato
|
||
fatto in quel modo. E così via.
|
||
|
||
Cambiamenti interni dell'API
|
||
----------------------------
|
||
|
||
L'interfaccia binaria fornita dal kernel allo spazio utente non può essere
|
||
rotta tranne che in circostanze eccezionali. L'interfaccia di programmazione
|
||
interna al kernel, invece, è estremamente fluida e può essere modificata al
|
||
bisogno. Se vi trovate a dover lavorare attorno ad un'API del kernel o
|
||
semplicemente non state utilizzando una funzionalità offerta perché questa
|
||
non rispecchia i vostri bisogni, allora questo potrebbe essere un segno che
|
||
l'API ha bisogno di essere cambiata. In qualità di sviluppatore del kernel,
|
||
hai il potere di fare questo tipo di modifica.
|
||
|
||
Ci sono ovviamente alcuni punti da cogliere. I cambiamenti API possono essere
|
||
fatti, ma devono essere giustificati. Quindi ogni patch che porta ad una
|
||
modifica dell'API interna dovrebbe essere accompagnata da una descrizione
|
||
della modifica in sé e del perché essa è necessaria. Questo tipo di
|
||
cambiamenti dovrebbero, inoltre, essere fatti in una patch separata, invece di
|
||
essere sepolti all'interno di una patch più grande.
|
||
|
||
L'altro punto da cogliere consiste nel fatto che uno sviluppatore che
|
||
modifica l'API deve, in generale, essere responsabile della correzione
|
||
di tutto il codice del kernel che viene rotto per via della sua modifica.
|
||
Per una funzione ampiamente usata, questo compito può condurre letteralmente
|
||
a centinaia o migliaia di modifiche, molte delle quali sono in conflitto con
|
||
il lavoro svolto da altri sviluppatori. Non c'è bisogno di dire che questo
|
||
può essere un lavoro molto grosso, quindi è meglio essere sicuri che la
|
||
motivazione sia ben solida. Notate che lo strumento Coccinelle può fornire
|
||
un aiuto con modifiche estese dell'API.
|
||
|
||
Quando viene fatta una modifica API incompatibile, una persona dovrebbe,
|
||
quando possibile, assicurarsi che quel codice non aggiornato sia trovato
|
||
dal compilatore. Questo vi aiuterà ad essere sicuri d'avere trovato,
|
||
tutti gli usi di quell'interfaccia. Inoltre questo avviserà gli sviluppatori
|
||
di codice fuori dal kernel che c'è un cambiamento per il quale è necessario del
|
||
lavoro. Il supporto al codice fuori dal kernel non è qualcosa di cui gli
|
||
sviluppatori del kernel devono preoccuparsi, ma non dobbiamo nemmeno rendere
|
||
più difficile del necessario la vita agli sviluppatori di questo codice.
|