Gestire le API…
Seguendo di tanto in tanto la Linux Kernel Mailing List (LKML) ho notato che i kernel hacker sono sempre molto restii a introdurre nuove system-call e, piuttosto, sono favorevolissimi a sopprimere quelle non frequentemente usate (cfr. ad esempio mail come questa).
Estendendo il discorso fuori dall’ambito kernel, possiamo parlare più genericamente di gestione delle Application Program Interface (API) per un dato software.
Nota: in questo post userò impropriamente il termine API per descrivere in un colpo solo tutte quelle interfacce, chiamate, funzioni, procedure, metodi, … che normalmente vengono messe a disposizione di terzi per “costruirci sopra qualcosa”. Un esempio per tutti: funzioni di libreria.
Nel corso del tempo ho trovato (e spero assimilato) un po’ di best practices per quanto riguarda la gestione delle API (“API management” per gli anglofili), sintetizzabili nelle seguenti “regole”(e relativi corollari):
- diffusione: se diffondi qualcosa, qualcuno può usarla e certamente lo farà;
- più un’API è mal progettata, più è alta la probabilità che qualcuno l’abbia già usata abbondantemente;
- prima di aggiungere una nuova API chiediti se è davvero necessaria ossia se fornisce funzionalità-chiave altrimenti non disponibili;
- non reinventare la ruota;
- durata nel tempo: se un’API è esistita, continuerà ad esistere anche se l’hai dichiarata deprecata, se ne hai pubblicamente sconsigliato l’uso e/o se l’hai rimossa totalmente da una versione all’altra;
- le idiozie sono dure a morire, specie se appaiono facili da usare;
- visione di insieme: le API sono un insieme, non un singolo;
- riprogetta un insieme di API per aggiungerne una, non “buttarla” nel mucchio, senza averne valutato l’impatto con o sulle altre;
- se ti accorgi di aver introdotto un duplicato di un’altra API, inventa qualche magia ma sopprimilo appena possibile;
- numero: minimizza più che puoi il numero di API ufficiali/pubbliche mantenendo però la buona regola che impone “una funzione, un solo obiettivo”
- niente API tuttofare, niente funzioni/metodi mastodontici (cfr. questo bel post);
- progetta interfacce snelle, intuitive, con pochi parametri e resistenti quanto più possibile agli errori (come direbbe Steve Maguire, “Make it hard to ignore error conditions. Don’t bury error codes in return values.”)
- qualità: progetta accuratamente le API e ricontrollale/migliorale periodicamente;
- usa i design pattern, le best practices, ecc… fin dall’inizio non solo per refactoring;
- non continuare a supportare API “storiche” o inusate ma alla prima occasione, dopo averle pubblicamente marcate come obsolete/deprecate e se nessuno si oppone, rimuovile;
- coerenza e consistenza di forma, di struttura, dei nomi scelti, delle convenzioni adottate, dei modi d’uso, … sono concetti fondamentali in qualunque progetto e sono da applicare in blocco a tutto il codice, API nascoste incluse (cfr. ad esempio questo post);
- l’usabilità (e, se vogliamo, anche l’accessibilità) non è un concetto applicabile solo alle interfacce grafiche rivolte agli utenti finali: anche i programmatori gradiscono essere rispettati (non a caso la I di API sta proprio per interfaccia);
- la documentazione ed i commenti non sono un vezzo nè un optional: molti framework e librerie devono il loro successo anche all’abbondanza di documentazione precisa, abbondante ed aggiornata;
- nel limite del possibile, preferisci sempre la qualità e la manutenibilità alla retrocompatibilità;
- rimozione: aggiungere un’API è facile, rimuoverla terribilmente difficile;
- talvolta l’unica via d’uscita da pessime API ufficiali è farle morire in blocco introducendo una qualche major release e dichiarandola incompatibile all’indietro (o non garantendo che tutto il codice già scritto continui a funzionare out-of-the-box dopo un aggiornamento particolarmente significativo);
- protezione: non permettere la diffusione e/o l’utilizzo di API nascoste o non ufficialmente rilasciate;
- proteggi le API nascoste perchè nessuno le possa sfruttare: se è il caso e/o puoi, nascondi o vieta l’accesso ai relativi simboli esportati (cfr. ad esempio questa pagina sul sito di GNU)
- nega vigorosamente la documentazione ed il supporto a terzi per le API interne e non ufficiali;
- migliora le API ufficiali, non ufficializzare mai quelle nascoste e/o di debug (se sono nascoste ci sarà pure un qualche motivo valido, no?)
- nessuna concessione: le API non devono adattarsi ai bug dei client ma piuttosto è essenziale spingere questi ultimi a correggerli (*).
- se serve e se è il caso, concorda preventivamente con il cliente una strategia comune per sistemare/eliminare i bug e le API “speciali” in modo pulito e senza sbavature;
- comunicazione (da Stefano): prima di introdurre nuove API, è meglio discuterne con più utilizzatori possibili (se si ha la fortuna di averne) per trovare una soluzione “confortevole” per la maggioranza dei client.
Ciao! ^^
(*): non è una situazione così inverosimile come potrebbe sembrare. Cfr., a puro titolo d’esempio, ciò che emerse online dall’analisi di alcune porzioni del codice di Windows 2000, trafugate illegalmente sulla Rete nel 2004.

Comunicazione: Prima di introdurre nuove API, è meglio discuterne con più utilizzatori possibili (se si ha la fortuna di averne) per trovare una soluzione ‘confortevole’ per la maggioranza dei client.
Grazie! (aggiunto
) ^^
e state attenti a non farvi pungere!
Qui c’e’ un documento molto interessante firmato da mr. glibc, “Good Practices in Library Design, Implementation, and Maintenance”
http://people.redhat.com/drepper/goodpractice.pdf
La sua homepage raccoglie ormai una quantita’ di documentazione non indifferente su molti aspetti succosi della programmazione in ambiente Linux. Ce n’e’ per tutti i gusti.
http://people.redhat.com/~drepper/
Grazie per i link: avevo letto altri suoi documenti, ma quello mi mancava.
Drepper è certamente un grande programmatore, sfortunatamente (pare) propenso a litigare col prossimo “se non si fanno le cose come dice lui”. ^^’
@cavok – bel link, libro interessante.
Se può servire, aggiungo questo estratto.
> Drepper è certamente un grande programmatore, sfortunatamente (pare)
> propenso a litigare col prossimo “se non si fanno le cose come dice lui”. ^^
non si dice litigare… ma propugnare con forza le proprie idee
cheers
@Stefano: bello anche il tuo ^^
@Contezero: LOOOL
A proposito di protezione delle API nascoste e non ufficiali.
Ahahahah… Fantastico!
Grazie per il link! ^^