L’anno di Linux sul desktop sarà il 2096.

Microsoft cesserà il supporto di Windows XP a breve. Io nel 2006 scrivevo che quello era l’anno di Linux sul desktop (non su questo blog). In quell’anno qualcosa era cambiato, in effetti, probabilmente grazie alla crescente popolarità di Ubuntu. Siamo però ormai nel 2013 (2014 fra qualche ora) e ci chiediamo ancora quando sarà l’anno di Linux sul desktop. Ubuntu ha cambiato strada, pensa al mobile. Le altre distribuzioni non sono sostanzialmente diverse dal 2006 e non hanno guadagnato quell’appeal che attira le masse. Quale sarà dunque l’anno di Linux sul desktop? La risposta è mai. Oppure il 2096, che poi significa mai.

Gli utenti non passeranno in massa a Linux nell’arco di un anno per lo stesso motivo per cui non l’hanno fatto fino ad oggi: il prodotto migliore non è necessariamente il più usato. Fra qualche mese il 40% dei PC si troveranno con un Windows XP non più supportato. Gli utenti sommessamente, poco alla volta, acquisteranno un PC nuovo con Windows 8, non con Linux. Se ne lamenteranno, pagheranno per il PC nuovo, pagheranno per aggiornare tutti i software, pagheranno per cambiare la stampante che con XP funzionava ma che non ha un driver per Windows 8, pagheranno ancora per il tempo che ciò gli farà perdere, odieranno questa nuova versione di Windows perché completamente diversa dalla vecchia a loro nota e grideranno contro il cielo che il mondo è ingiusto. Tuttavia non installeranno Linux in massa.

Qualcuno, veramente stufo di essere maltrattato, cercherà di installare Linux dopo qualche mese dall’acquisto del PC nuovo, ma scoprirà di non poterlo fare a causa del SecureBoot di Microsoft. La colpa ovviamente sarà di Linux che non è compatibile.
Se Linux un giorno diventerà il sistema più usato sul desktop, sarà solo perché gli altri sistemi proprietari saranno lentamente passati di moda e non saranno più una fonte di guadagno interessante per chi li produce: a quel punto sarà Microsoft stessa a consigliare ai propri utenti di aggiornare da Windows 27 a Linux, fornendo tutte le istruzioni per farlo. Questo succederà quando i PC stessi saranno completamente passati di moda e di necessità. Di moda son già passati adesso, ma continuano ad essere una necessità, perché non mi si venga a raccontare che con un tablet si fa tutto quello che si fa con un PC, tanto non è vero. Un giorno, forse non lontano, potrebbe però diventare un po’ più vero: quel giorno i PC non interesseranno più a nessuno e Linux diventerà il sistema operativo più utilizzato sui PC.

Prima di allora ci sono troppi soldi in ballo e non succederà.

Eccezioni: prevedere l’imprevedibile.

Sale qb. Questa è la parte più antipatica di ogni ricetta di cucina per chi non ha esperienza di cuoco. Di solito arriva al fondo dell’elenco ingredienti. Cosa significa qb? Beh sì, significa “quanto basta”, ma a quanto corrisponde? Potremmo dire che il calcolo del valore della variabile qb procede per approssimazioni successive:

1. Assaggia l'impasto
2. È buono?
2A. Sì, allora non aggiungere sale, la ricetta è terminata
2B. No, allora aggiungi un pizzico di sale e torna al punto 1

Facile no? Magari è una procedura un po’ lenta e magari in alcuni casi si finisce per mangiarsi gran parte dell’impasto prima di raggiungere la quantità corretta di sale, ma nella maggior parte dei casi funziona. Non prevede però tutti i casi. Cosa succede se l’impasto è già troppo salato in partenza? Aggiungo zucchero? Butto via tutto e riparto da capo? Uso l’impasto per la cena del cane? Procediamo per passi. Prima di tutto traduciamo in codice la procedura descritta sopra. Faccio notare che ci sarebbero molti modi per tradurla in codice, questo è solo uno dei tanti:

public void adjustSalt()
{
  Recipe r = getRecipe();
  if (r.hasGoodTaste())
    return;
  else
  {
    r.addSalt(0.6);
    ajustSalt();
  }
}

Chiariamo subito che questo codice è incompleto, nulla si dice di cosa sia la classe Recipe o di come siano fatte le varie funzioni che vengono chiamate come se esistessero, a parte la adjustSalt() che è l’unica definita. Inoltre 0.6 è un numero arbitrario che ho deciso che significa “un pizzico di sale”. Quello che ho scritto è una via di mezzo fra codice Java e pseudocodice, serve solo a rendere l’idea ma così com’è non funzionerà mai da nessuna parte. È comunque utile ad illustrare il concetto.
Il problema di questa funzione è il fatto di dare per scontato che per rendere buono l’impasto basti aggiungere sale fino a quando la funzione hasGoodTaste() non ritorna true. Se la funziona hasGoodTaste() ritorna false, in realtà noi sappiamo che l’impasto non è buono, ma non sappiamo veramente il perché.
Un’alternativa potrebbe essere:

public void adjustSalt()
{
  Recipe r = getRecipe();
  try
  {
    r.taste();
    return;
  }
  catch(InsipidException ie)
  {
    r.addSalt(0.6);
  }
  catch(SaltyException se)
  {
    r.addPotato(0.4);
    r.addTomato(0.2);
    r.addCream(0.1);
    r.addWater(0.1);
  }
  adjustSalt();
}

Osserviamo che in questo codice non c’è più l’istruzione if. Al suo posto c’è una try, che significa: “prova a fare quel che ti dico, se succede qualcosa di strano, vediamo poi come arrangiarci”. Quello che si richiede di fare all’interno della try è assaggiare l’impasto, ovvero la chiamata alla funzione taste(). Se questa funzione termina il suo compito senza che accada nulla di strano, significa che l’impasto è buono: il programma prosegue normalmente con l’istruzione successiva che è una return e così la funzione adjustSalt() termina e il controllo ritorna al chiamante. Se invece l’impasto non è buono, la taste() lancia un’eccezione. La differenza, rispetto a prima, è che l’eccezione può essere ti qualsiasi tipo e portare con sè molte informazioni circa il problema che si è verificato, mentre prima il valore di ritorno della hasGoodTaste() poteva essere solo vero o falso, senza tanti perché.
L’istruzione try deve essere seguita da una o più istruzioni catch (non è del tutto vero, ma per ora prendiamolo per vero). Ogni istruzione catch specifica un tipo di problema che si può verificare all’interno del blocco try e la relativa soluzione. Per esempio se l’impasto è insipido (InsipidException) la soluzione è aggiungere sale, mentre se è già troppo salato la soluzione è stemperarlo con patate, pomodori, panna ed acqua.

Ci sono molti altri vantaggi nell’usare le eccezioni invece dei valori di ritorno contenenti codici di errore, ma per ora mi fermo qui. Il resto ve lo dirò in un prossimo post.

Tipizzazione forte, oltre lo scripting

Apro, con questo articolo, una serie di suggerimenti sulla programmazione. Non è un corso, è una collezione di informazioni sperabilmente utili. Userò del codice Java quando sarà necessario fare esempi, ma esporrò concetti validi in tutti i linguaggi. Partiamo.
Quale differenza passa fra Java e JavaScript? A parte i nomi somiglianti ed una sintassi simile, tutto il resto. Ed è circa la stessa differenza che passa fra una ricetta cucinata da un famoso chef e la stessa ricetta cucinata da me. Avete mai cucinato? No? Vi svelo un segreto: al posto delle acciughe, se restate senza, si possono usare i capperi. Incredibile no? I capperi, un vegetale, al posto delle acciughe, un pesce. Certo, un vero chef probabilmente non lo farebbe mai, ma io sì.
Allo stesso modo in Java, ovvero un qualsiasi linguaggio con tipizzazione forte, non potete scambiare gli ingredienti a piacimento, mentre in JavaScript, un linguaggio con tipizzazione debole, potete. Bene, ma quando si programma, quali sono gli ingredienti? Naturalmente i dati in input del programma, o della singola funzione, o ancora della singola istruzione. I dati elaborati, ovvero quelli in output, sono l’equivalente della ricetta cucinata, ed a cucinare i dati ci pensa il computer seguendo le nostre istruzioni. Il codice che scriviamo sono come le istruzioni di una ricetta, in cui insegnamo al computer come cucinare i dati. I tipi di dati sono equivalenti, più o meno, ai tipi di ingredienti. Le acciughe sono pesci, quello è il tipo di ingrediente. I capperi sono vegetali. Il mio nome è una stringa, ovvero “Lucio”. La mia età è un numero, ovvero 40, nel momento in cui sto scrivendo.
In un linguaggio con tipizzazione debole, come per esempio JavaScript, io posso calcolare la mia età usando stringhe al posto di numeri, così:
eta = "2013" - "1973";
In questo caso il linguaggio, trovando l’operatore di sottrazione, ovvero il segno meno, sa che ha bisogno di numeri per poterlo eseguire e tenta una conversione automatica in numeri delle stringhe che abbiamo messo attorno al segno meno. Questo è utile per piccoli programmi (script) dove eventuali errori in questa conversione automatica non siano catastrofici. Per esempio, supponiamo che le due stringhe “2013” e “1973” siano frutto di una digitazione da tastiera richiesta all’utente che usa il programma e supponiamo quindi che il programma serva esattamente a dire quanti anni hai. Prima ti chiede in che anno siamo, poi ti chiede in che anno sei nato ed infine ti dice quanti anni hai. Ora supponiamo anche che l’utente, mentre inserisce i dati, per sbaglio metta una lettera I maiuscola al posto della cifra 1 (uno). Ci troveremmo a fare questo calcolo:
eta = "20I3" - "I973";
Nel caso di JavaScript, tipizzazione debole, il calcolo viene eseguito comunque, ma il risultato non è quello sperato, in quanto la variabile eta a questo punto vale NaN, cioè “Not A Number”. Un valore inutile, perché eta è un “non numero” (caspita mi sembra di parlare dei “non morti” di Monkey Island…), ma che cosa sia veramente non lo sappiamo. Peggio che mai, visto che il calcolo viene eseguito comunque ed il programma non viene fermato, potremmo accorgerci di questo “non numero” molto più avanti, quando ormai è troppo tardi per scoprire la causa del problema e correggere l’errore. Supponiamo per esempio di usare l’età per scrivere il nome dell’utente in un file e di avere un file diverso per ogni età, perché stiamo organizzando le cene dei coscritti di tutte le età del nostro paese. Ad un certo punto scriveremo il nome in un file che invece di chiamarsi “coscritti40.txt” si chiamerà “coscrittiNaN.txt”. In quel file ci finiranno tutti quelli che sbagliano a digitare i numeri. E non parteciperanno quindi ad alcuna cena dei costritti. Vogliamo veramente far morire di fame le persone?
Lo stesso programma, scritto in Java o in altro linguaggio con tipizzazione forte, non eseguirebbe la sottrazione. In Java non posso proprio scrivere
int eta = "2013" - "1973";
perché è sintatticamente errato. La sintassi Java impedisce di sottrarre stringhe. Java non fa conversioni automatiche di tipo se non in casi particolari e non pericolosi. Sicuramente non converte mai automaticamente da stringa a numero. Una riga di codice come quella, in Java, non viene neppure compilata: Java non ci permette neppure di provare il programma fino a quando non correggiamo quella riga:
int anno = Integer.parseInt("2013");
int nascita = Integer.parseInt("1973");
int eta = anno - nascita;

Ecco, questo è ciò che Java ci costringe a fare, ovvero ci costringe a scrivere esplicitamente il codice per convertire da stringa a numero intero. Lo fa perché è brutto e cattivo? Lo fa perché è antiquato? No, lo fa perché è un linguaggio con tipizzazione forte. E così facendo, da una parte scarica sul programmatore la responsabilità di eventuali errori di conversione, dall’altra può bloccare il programma e darci tutte le informazioni del caso, se quello che stiamo cercando di convertire non è convertibile nel tipo di dato che ci serve. Il principio è quello del “fail fast”, ovvero ottenere informazioni sugli errori prima possibile, in modo da poterli correggere (richiedere all’utente di digitare correttamente l’anno) prima che sia troppo tardi.
È evidente che il codice Java è più lungo, tre righe al posto di una sola. È anche evidente che il codice Java è più preciso, spiega passo passo cosa stiamo facendo. E, infine, risulta evidente come il programma sia più robusto, ovvero come sia più difficile fregarlo e mandarlo in una condizione di errore non prevista: Java fa di tutto per costringerci a prevedere le condizioni di errore. Resta un dubbio: come fa Java a bloccare il programma nel caso in cui non si possa tradurre la stringa in un numero intero? Solleva un’eccezione, ma di questo vi parlerò la prossima volta.