venerdì 21 agosto 2015

Lezioni di leadership da Flo Rida

Nell'ultimo video del rapper nero Flo Rida, c'è una scena che secondo me insegna almeno quattro punti fondamentali nell'esercizio di una leadership vera.

Nel video, Flo Rida è seduto per strada con i suoi amici - il suo team, potremmo dire -  e a un certo punto succede qualcosa di notevolmente straordinario.



Passa un ambulante di gelati (54") e Flo Rida si alza e offre il gelato ai suoi amici. Fin qui, niente di strano. E' il come lo fa, che è straordinario.

Ordina un gelato per ciascuno dei suoi amici, poi se lo fa dare di persona, poi lo porge, con cura, personalmente a ciascuno dei suoi: Ecco questo è per te, Alessio, Questo è il tuo, Daniela. Non è notevole? Avremmo fatto lo stesso?

In questo brevissimo passaggio, il rapper esercita la leadership in quattro importanti modi: il vero leader:

  • ti indica la via e ti spiana la strada
  • ti coinvolge personalmente e ti chiama per nome
  • si prende cura di te, assicurandosi che tu abbia tutto il necessario per proseguire
  • si spende in prima persona e ci mette la faccia

Nella mia carriera ho lavorato con tanti leader, veri o presunti tali, leader naturali o imposti dall'alto. Ho notato nei primi, sempre rispettati, i quattro punti di cui sopra.




giovedì 28 agosto 2014

Cercare in un file in Windows 8

Vi sarà sicuramente capitato di ricercare i contenuti di un file in Windows 8... e di non trovarli mai! Fate il vostro bel "swype" come vi hanno insegnato, andate sulla lente di ingrandimento, mettete la parola da cercare e... mai che vi trovi il documento che contiene quella parola!

Avrete sicuramente mandato a quel paese gli ingegneri del software della Microsoft, e avrete pensato che quelli che dicono che Windows non funziona hanno ragione!

No, in realtà la ricerca indicizzata di Windows 8 (e 8.1 ovviamente) funziona molto bene, peccato che occorra personalizzarla - e questa è una delle prime cose che andrebbe fatte dopo aver installato il sistema operativo.

Per ovvi motivi, Windows appena installato indicizza solo alcune (poche!) cartelle, perché altrimenti le operazioni di indicizzazione sarebbero molto lunghe, e il file che contiene l'indice potrebbe diventare enorme.

Tuttavia, è molto semplice personalizzare le opzioni di ricerca e ottenere un'indicizzazione dei vostri contenuti, in modo da poterli trovare immediatamente.

Per prima cosa, swype (cioè passare il mouse sulla parte destra dello schermo), selezionare "Impostazioni" ("Settings") e poi "Pannello di Controllo" ("Control Panel").

In alto a sinistra nel box di ricerca scrivete, se avete Windows in inglese "index", altrimenti in italiano "indicizzazione". Verrete portati a questa schermata:


Attraverso questa schermata, premendo "Modify" ("Modifica"), è possibile selezionare le cartelle del PC i cui contenuti verranno indicizzati e saranno quindi disponibili per una ricerca veloce.

Unico consiglio: non esagerate! Immettete solamente le cartelle dove effettivamente archiviati i vostri documenti.

Se, come me, avete due dischi, e sul primo mettete solamente il sistema operativo, è buona norma cambiare la posizione del file di indice in modo che questo risieda sul vostro disco più capiente.

Per farlo andate su "Advanced" ("Impostazioni avanzate"):


Selezionate la cartella che conterrà i file di indice, e poi premete il tasto "Rebuild" ("Ricostruisci"). In questo modo, i vecchi file indice verranno cancellati, e quelli nuovi verranno salvati nella nuova posizione.

Infine, valutate se vi interessa che le ricerche fatte con lo swype includano o meno risultati dal Web. Per personalizzare quest'ultima opzione potete agire su: "Settings" ("Impostazioni"), "Change PC Settings" ("Cambia impostazioni"), "Search and Apps" ("Ricerca e App"), e poi mettete a "Off" (oppure "On") l'impostazione "Use Bing to search online" ("Usa Bing per cercare online").


 

mercoledì 14 maggio 2014

Clonare un repository da GitHub


Ecco una breve guida per effettuare il clone di un repository di codice sorgente da GitHub, modificarlo e poi sottomettere le modifiche. Il tutto direttamente da linea di comando. Com'è ovvio, occorre aver installato in locale git.

Per prima cosa occorre creare una directory e posizionarvisi sopra.

Quindi occorre effettuare il 'cloning':

git clone https://github.com/guildenstern70/cpp11learn.git
git status

Questa operazione crea un'esatta replica di tutti i file sul repository, non solo i sorgenti ma anche tutti i file ancillari, ad esempio la 'History'.

'git status' mi dà un feedback delle operazioni effettuate.

A questo punto posso cominciare a modificare i miei file. Quando ho finito il lavoro, occorre mettere in 'stage' le modifiche, che saranno così pronte per essere committate: lo si fa con il comando 'add':

git add <files...>
git status

Con il comando 'add' aggiungo i file che non erano presenti, oppure indico quali file esistenti sono stati modificati - esatto, è lo stesso comando per entrambe le operazioni.

Quando sono pronto per rendere operative le modifiche, effettuo il commit in locale:

git commit
git status

Ora occorre dare un nome al branch remoto, ad esempio: github. In questo modo posso indicare su quale repository lavorare, quello in locale, che normalmente è indicato come 'master' e quello in remoto, che qui chiamo 'github', ma che normalmente si indica come 'origin':

git remote add github https://github.com/[username]/[projectname].git
git remote -v

L'indirizzo https del repository si trova sul sito github del repository stesso.

Infine, per sincronizzare il repository locale con quello remoto, cioè in un certo senso per fare l'upload delle modifiche si dà il comando 'push':

git push -u github master

Viene chiesta la nostra username e password su GitHub, e dopo averle inserite, il gioco è fatto.

martedì 29 aprile 2014

Di che tipo è una Funzione Lambda?


Le funzioni lambda sono balzate agli onori delle cronache soprattutto perché l'ultima versione di Java le supporta direttamente, mentre sono molti altri i linguaggi che le integrano nella loro sintassi, ad esempio Ruby, Python e Scala.

Nel campo della programmazione una funzione lambda è una funzione anonima che può essere chiamata e passata direttamente, senza cioè essere nominata con un identificatore, come lo è una funzione normale, che ha un suo nome che rende possibile chiamarla nominalmente.

Ad esempio, in Scala, una funzione lambda ha questa sintassi:



val circleArea = (radius: Double) => 
                     { radius * radius * Math.PI }



in questo caso il nome "circleArea" non è il nome della funzione, ma è il nome dell'oggetto a cui si associa la funzione lambda. La differenza è sottile ma sostanziale: una funzione lambda può essere associata a molte diverse variabili con diverso nome, mentre una funzione normale ha uno e un solo nome.

Perché mai un programmatore dovrebbe usare funzioni senza nome? Il motivo principale risiede nell'immediatezza: sono parti di codice di facile scrittura, tipicamente formule matematiche, il cui uso è in porzioni di codice "vicine" a quello in cui vengono definite. Oppure ancora si tratta di shortcut, cioè di un modo veloce per passare mini-funzioni ad una super-funzione che le richiama all'interno di se stessa - il caso, nell'esempio sotto in Java8, della gestione degli eventi nei controlli:

// Lambda in Java 8
button.addActionListener( (e) -> {
        System.out.println("The button was clicked. From lambda expressions !");
});


C'è però una questione: quando passo una funzione anomima ad un'altra funzione, qual è il "tipo" con cui la identifico? In altre parole: se scrivo un metodo che prende come input una funzione lambda, come sarà la "firma" di quel metodo? Qual è insomma il tipo di una funzione lambda?

La questione è cruciale nei linguaggi fortemente tipizzati, dove è necessario identificare sempre il tipo di un oggetto per poterlo passare.

In Scala, che è un linguaggio fortemente tipizzato, la cosa viene risolta in modo elegante, cioè dando al tipo "funzione" una sintassi propria. Di seguito l'esempio di una High Order Function, cioè di una funzione che prende in input un'altra funzione:

function def highOrderFunction(func: Double => Double, v: Double ):String = {
        
        val result = func(v)
        result.toString();
        
}

Il primo parametro dice che deve essere passata una "funzione" che ritorna un numero decimale Double e prende in input un altro Double. Quindi, in Scala, la domanda non ha molto senso: il tipo di una funzione non è necessario specificarlo, perché il linguaggio ha una sintassi propria per definire un placeholder di funzione, che è il seguente:

(Input Parameters) => (Expression)


Però in altri linguaggi la questione si pone eccome. Ad esempio in C#. In questo linguaggio una funzione lambda viene definita come segue:

(double radius) => { radius * radius * Math.PI}


Ma se voglio "tradurre" la funzione Scala che abbiamo visto sopra (highOrderFunction) in C#, ho bisogno di sapere di che "tipo" è la funzione lambda.

Bene, in C# esistono due tipi (in realtà sono delegates) che rappresentano procedure e funzioni, sia che queste siano normali, e quindi nominali, sia che siano anonime, o lambda. Consideriamo di avere una procedura "VoidProcedure", che prende in input un intero, e una funzione "SimpleFunction" che prende in input un intero e ritorna un decimale:

static void VoidProcedure(int i)
{
    Console.WriteLine(i);
}

static double SimpleFunction(int i)
{
    return (double)i/2;
}


I tipi che le possono rappresentare sono:
Per cui si può scrivere un programma per invocarle indirettamente attraverso questi due nuovi tipi (delegati):

static void Main(string[] args)
{
    Action myAction = new Action(VoidProcedure);
    myAction.Invoke(123);           // Prints out "123"

    Func myFunc = new Func(SimpleFunction);
    Console.WriteLine(myFunc(5));   // Prints out "2.5"

    Console.ReadKey();
}


Ora, utilizzando al posto delle funzioni, le funzioni lambda, lo stesso programma diventa:

static void Main(string[] args)
{
    Action myAction = new Action(

        // Lambda procedure
        (i) => Console.WriteLine(i)

        );
    myAction.Invoke(123);           // Prints out "123"

    Func myFunc = new Func(
               
        // Lambda function
        (i) => (double)i/2
                
        );
    Console.WriteLine(myFunc(5));   // Prints out "2.5"

    Console.ReadKey();
}


In Java, i tipi lambda sono addirittura sei:

  • Predicate: una funzione che torna un booleano (normalmente per fare query)
  • Consumer: simile alla Action di cui sopra
  • Function: simile alla Func di cui sopra
  • Supplier: una funzione factory, che genera oggetti di tipo
  • UnaryOperator: funzione unaria che trasforma un oggetto
  • BinaryOperator: funzione binaria che trasforma due parametri in un valore di ritorno.

Cosicché il nostro esempio, in Java8, può scriversi come:

package lambdajava;

import java.util.function.Function;

public class LambdaJava {

    public static void main(String[] args) {

        byte[] ch = null;
        Function<Integer, Double> myFunc = i -> (double)i/2;
        System.out.println(myFunc.apply(5));
        
    }
      
}

 

martedì 20 agosto 2013

Funzioni "First Class" e "Higher Order" nella Programmazione Funzionale



In un recente post ho parlato della Programmazione Funzionale (FP) come di un paradigma di programmazione per computer che è sostanzialmente esente da side-effect, cioè a dirla in modo un po' brutale: è esente da comportamenti anomali a run-time.


In pratica, un programma scritto in FP pura si comporta come un foglio Excel. Si è mai visto un foglio Excel avere comportamenti anomali? Ci sono dei valori in input, ci sono delle formule e tutto quello che si ottiene sono dei valori di output che derivano dall'applicazione di quelle formule.

In modo simile, un programma FP è una funzione che prende come input una funzione - quindi, si potrebbe dire: una formula - e dà in output un certo risultato. A complicare le cose, c'è il fatto che una funzione FP solitamente prende in input una funzione che a sua volta prende in input una funzione e così via, fin quando ce ne sia bisogno per realizzare lo scopo del programma.

Per indicare questo tipo di comporamento, si dice che un generico linguaggio FP supporta le First Class Functions.

Una funzione, per essere "First Class", deve avere questa caratteristica: può essere passata ad un'altra funzione come qualsiasi altro valore.

Facciamo un esempio. (L'esempio in basso è scritto in linguaggio Scala, che è un linguaggio di programmazione che supporta molto bene il paradigma funzionale).


val areaDelCerchio = (raggio: Double) => { 
    raggio*raggio*Math.PI 
}
    
def printResult(result: Any) {
    println("L'area del cerchio e' : " + result.toString)
}
    
printResult( areaDelCerchio(10.0) )


La formula dell'area del cerchio viene memorizzata come valore (val). Questo basta per far sì che Scala possa dirsi un linguaggio dove le funzioni sono First Class, cioè vengono trattate come valori di prima classe, come lo sono solitamente gli interi o le stringhe. Significa che qualunque funzione può prendere come parametro un valore di prima classe: quindi, tipi elementari, oggetti e funzioni.

La funzione printResult è una funzione che si dice di ordine superiore, Higher Order Function, perché può prendere come parametro un qualsiasi valore e - anche! - una funzione.

Da un punto di vista di controllo dei tipi, la funzione/valore areaDelCerchio prende come parametro un Double (raggio, un valore decimale a doppia precisione) e ritorna un Double.

Qualsiasi oggetto in Scala - e quindi un Double, o una First Class Function - può essere convertito in Stringa. Ed ecco che printResult prende come parametro Any, cioè qualsiasi tipo o funzione, che possa essere rappresentato come stringa - che possegga il metodo .toString.

Poichè la funzione areaDelCerchio non mantiene variabili di stato e non accetta input dall'esterno che potrebbero modificarla, il suo comportamento è predicibile a priori ed esente da side-effect.

Una funzione Higher Order che prende come input tipi semplici o funzioni o funzioni di funzioni, ha un comportamento sempre predicibile e, una volta compilata, sarà esente da bug a run-time. Detto in altri termini: se un programma funzionale puro si compila - quindi non dà errori a compile-time - sarà esente da bug.

La capacità di esprimere un programma per computer, anche complesso, in termini di Higher Order Functions è dunque una garanzia che lo stesso, se si compila, avrà un comportamento predicibile e senza malfunzionamenti.

Se si pensa alle ingenti risorse che vengono impiegate normalmente in informatica per il test e il controllo della qualità del software, le implicazioni economiche di un simile approccio alla programmazione sono del tutto evidenti.


giovedì 7 marzo 2013

Programmazione asincrona in C# 5

C# versione 5 rende l'utilizzo della programmazione asincrona piuttosto agevole attraverso l'utilizzo di un pattern molto semplice e di due keyword: async e await.



Utilizzare codice "asincrono" è una necessità non solo quando si vuole parallelizzare l'esecuzione di procedure, ma anche quando si vuole rendere la logica di business indipendente dal codice che gestisce e muove l'interfaccia grafica. L'idea è che nessuna operazione debba "stoppare" l'esecuzione del codice deputato a gestire l'input dell'utente o a fornirgli un feedback.

Tanto più urgente è questa necessità quanto più il device ha processori poco potenti: che è il caso tipico dei device mobile. Ad esempio, il framework di programmazione di Windows Phone, WinRT, si basa pesantemente sul concetto di programmazione asincrona, ed il suo uso è obbligatorio. Non è possibile, giusto per citare un caso, in WinRTleggere un file in sincrono: è invece necessario predisporre il codice asincrono, in modo che mentre le operazioni di lettura del file sono in esecuzione, l'interfaccia e il resto del programma continuano a funzionare in parallelo.

La gestione della programmazione asincrona, benché semplice, è piuttosto controintuitiva. Su MSDN si legge che "l'operatore await dice al compilatore che il metodo marcato async non può continuare dopo quel punto fino a che il processo asincrono che si aspetta non è terminato". Cerchiamo di capire cosa significa con un esempio.

Supponiamo di avere una ipotetica funzione di business che ci impiega molto tempo per completare. Ad esempio questa, che su un portatile non troppo vecchio impiega qualche secondo:

static long LongRunningComputation(int i)
{
    Random cycleSeed = new Random();
    long result = 0; int rnd = 0;
    for (long j = 0; j < cycleSeed.Next() * 1E5 + 3E6; j++)
    {
        rnd = cycleSeed.Next(11);
        result += (rnd % 2 == 0) ? rnd : -rnd;
    }
    return result;
}

La prima cosa che occorre fare è incapsulare questa funzionalità in un metodo asincrono. Ogni metodo asincrono è tale se ritorna un oggetto Task. Un oggetto Task si costruisce con una Factory che si chiama Task.Run e prende in input una funzione lambda qualsiasi, con questa sintassi:

static async Task LongTaskAsync(int i)
{
    Task longOperation = 
            Task.Run(() > LongRunningComputation(i));

    return await longOperation;
}

La prima istruzione serve per costruire l'oggetto Task. Questo è un oggetto che mantiene lo stato e le informazioni sul processo asincrono che è in corso. Il fatto che la nostra operazione ritorni un intero viene riflesso nel fatto che Task è di fatto un contenitore generico (di un intero lungo).

La funzione lambda è in grado di "leggere" i parametri che sono in scope nel momento in cui è definita, quindi non c'è bisogno di specificare che intendiamo passargli l'intero "i" - questa cosa io ci ho messo francamente un po' per capirla... io avrei messo

((i) => LongRunningComputation(i))

 però il parametro di Task.Run è un delegato che non accetta parametri!

La norma vuole che ogni funzione "asincrona" abbia un nome che termina in "Async" e non ci adeguiamo. La parola "await" significa che questo metodo deve aspettare il termine dell'operazione "LongRunningComputation" prima di tornare un valore che abbia senso! Infatti il codice LongRunningComputation viene lanciato in asincrono, e quindi la linea di codice successiva viene eseguita immediatamente.

Senza la programmazione asincrona, si potrebbe pensare di costruire una funzione che esegue due chiamate all'operazione lunga e somma i loro risultati, così:

static long GoInLineNormally()
{
    Console.WriteLine("Going in sequence, normally");
    long x1 = LongRunningComputation(11);
    Console.WriteLine("X1 (NORMAL) = " + x1);
    long x2 = LongRunningComputation(22);
    Console.WriteLine("X2 (NORMAL) = " + x2);
    return (x1 + x2);
}

Siccome abbiamo detto che l'operazione lunga ci mette grossomodo due secondi, la procedura di cui sopra ci metterebbe circa quattro secondi per essere eseguita.

Ma abbiamo la programmazione asincrona, e quindi è lecito pensare che le due possano essere lanciate sue due thread differenti, e quando ciascun thread esce con un risultato, sommarli e stamparli a video.

static async Task GoInParallelAsync()
{
    Console.WriteLine("Going in parallel");

    var t1 = LongTaskAsync(11);
    var t2 = LongTaskAsync(22);

    await Task.WhenAll(t1, t2);

    Console.WriteLine("X1 (PARALLEL) = " + t1.Result);
    Console.WriteLine("X2 (PARALLEL) = " + t2.Result);
    return (t1.Result + t2.Result);
}


Per farlo abbiamo lanciato LongTaskAsync e poi, attraverso la funzione Task.WhenAll, abbiamo "aspettato" che entrambi finissero per raccogliere i risultati. L'esecuzione totale, come ci aspettavamo è di circa due secondi invece che quattro.

Ricapitolando. Se un metodo asincrono viene lanciato con l'operatore "await", l'esecuzione si ferma finché il metodo non ha ritornato un risultato - ma questo metodo viene comunque lanciato su un thread differente rispetto al programma che lo ha lanciato, il quale può ad esempio continuare così ad aggiornare l'interfaccia grafica e a rimanere in ascolto di eventuali eventi. Se invece un metodo asincrono viene lanciato senza l'operatore await, la linea successiva di codice viene eseguita immediatamente, e il controllo sull'esecuzione del task asincrono è demandato ai metodi della classe Task.

Infatti, se lanciamo con:

static async Task GoInLineAsync()
{
    Console.WriteLine("Going in sequence, but async");
    long x1 = await LongTaskAsync(11);
    Console.WriteLine("X1 (SEQUENCE) = " + x1);
    long x2 = await LongTaskAsync(22);
    Console.WriteLine("X2 (SEQUENCE) = " + x2);
    return (x1 + x2);
}


il codice esegue prima LongTaskAsync(11) e solamente dopo aver ottenuto il risultato (ciò che è espresso dall'operatore await), lancia il LongTaskAsync(22).

Questo codice, benché funzionalmente identico a GoInLineNormally è molto diverso dal punto di vista del comportamento! Il primo infatti è rigorosamente sincrono: ogni linea di codice viene eseguita solo e soltanto se quella precendente è terminata. Il secondo, invece, attraverso l'operatore "await" dice al compilatore: adesso esegui in asincrono su un thread differente LongTaskAsync, e aspetta che il metodo asincrono sia terminato prima di proseguire con la prossima linea di codice.

E' da notare in particolare il codice entry point, Main, che richiama le procedure scritte sopra:

static void Main(string[] args)
{
    Console.WriteLine("AYNC/AWAIT TEST v.1.0");
    Console.WriteLine();

    //long r = GoInLineNormally();
    var t = GoInLineAsync();
    //var t = GoInParallelAsync();

    Console.WriteLine("END TEST (Is it really ended?)");
    Console.WriteLine("Result = " + t.Result);
    Console.WriteLine();
    Console.ReadKey();

}

Domanda: quando viene stampata la linea "END TEST"?

Alla fine dell'esecuzione dei vari metodi GoIn...? La risposta è sì, se si tratta di GoInLineNormally(), ma è no in entrambi gli altri casi: si tratta di metodi asincroni che ritornano subito (non c'è await)! Quindi "END TEST" non è proprio un messaggio di End, perché viene stampato immediatamente, mentre i metodi asincroni sono in esecuzione. Viceversa, "Result =" viene stampato effettivamente alla fine dei calcoli, perché il valore di t è "awaited" da t.Result.

E se avessimo voluto "aspettare" l'esecuzione GoInLineAsync() prima di scrivere "END"? Non avremmo potuto farlo! Infatti un metodo che contiene una chiamata "await" deve per forza essere marcato "async". Ma il metodo Main non può essere "async"! Quindi non abbiamo potuto scrivere, per esempio:

var t = await GoInLineAsync()

Se avessimo marcato il metodo Main come "async", avremmo detto al compilatore che quel metodo va eseguito in asincrono e che deve ritornare immediatamente al chiamante, per poi "rientrare" quando il metodo sia terminato: due cose che un programma a console, evidentemente, non può fare.


giovedì 28 febbraio 2013

First Class Functions in Scala


A volte è necessario passare come argomenti dei metodi o delle funzioni non un parametro normale come un intero o una stringa, ma un'altra funzione. Ad esempio vorremmo scrivere un metodo che applica una somma o una moltiplicazione di due numeri, e vogliamo passargli come argomento la funzione "somma" o la funzione "moltiplicazione".

Un esempio meno banale: vorremmo scrivere una funzione di sorting che prende in input la collezione di oggetti da ordinare e l'algoritmo di sort. Questa funzione avrebbe quindi due parametri: la collezione e una funzione con l'implementazione dello specifico algoritmo.

Dunque vorremmo costruire una procedura che esegue una determinata operazione sui suoi parametri, e vorremmo passare come parametro l'operazione stessa, in modo da rendere la procedura del tutto generica, e perciò anche riutilizzabile.

Normalmente, nella programmazione orientata agli oggetti, questo si ottiene con un pattern che si chiama "Functor". Il Functor è un'interfaccia che espone un metodo che includerà la nostra funzione. Sta poi alla particolare implementazione dell'interfaccia stabilire se quella funzione è, ad esempio, una moltiplicazione o una somma.

Posto che in Scala le interfacce non esistono, ma esistono i "trait", di cui ho parlato in un altro post, si potrebbe pensare di scrivere due classi, Somma e Moltiplicazione, così fatte:

trait Functor {
  def function(x: Int, y: Int) : Int
}

class Somma extends Functor {
  def function(x: Int, y: Int) : Int = (x+y)
}

class Moltiplicazione extends Functor {
  def function(x: Int, y: Int) : Int = (x*y)
}

Cosa sono le "first class functions"? Sono una particolarità del linguaggio che ci permette di passare, come argomento di una funzione o di un metodo di classe, una funzione; esattamente quello che otteniamo con il pattern "Functor".

In questo caso però, noi non passiamo un oggetto che ha come metodo una specifica funzione: noi passiamo direttamente la funzione!

Questa è la sintassi da usare:

object FirstClassFunctions {
  val somma = (x: Int, y: Int) => (x+y)
  val moltiplicazione = (x: Int, y: Int) => (x*y)
}


La variabile "somma" non è né un tipo primitivo (intero o stringa, ad esempio), nè un oggetto. E' una funzione. La prima parte dice quali sono i tipi che la funzione manipola, e la seconda parte è la funzione vera e propria. Somma è una funzione che somma il valore x al valore y. Similmente per moltiplicazione.


object Main {

  // Functor
  val functSomma : Functor = new Somma()
  val functMoltiplicazione : Functor = new Moltiplicazione()

  def testFunctor(f:Functor, x:Int, y:Int) {
    println("Il risultato e' = " + f.function(x,y))
  }

  // First Class
  def testFirstClass(f: (Int,Int) => Int, x:Int, y:Int)  {
    println("Il risultato e' = %d".format(f(x,y)))
  }


  // Main
  def main(args: Array[String]) {

    testFunctor(functSomma, 6, 5)
    testFunctor(functMoltiplicazione, 6, 5)

    testFirstClass(FirstClassFunctions.somma, 6, 5)
    testFirstClass(FirstClassFunctions.moltiplicazione, 6, 5)

  }

}


Il codice di sopra richiama le funzioni sia sotto forma di Functor, che sotto forma di First Class Functions.
Com'è ovvio, la possibilità di passare direttamente funzioni come parametri di metodi, piuttosto che inventare una tassonomia apposita di classi, riduce la complessità del codice, aumenta la leggibilità e quindi in definitiva migliora la qualità del codice sorgente.


venerdì 8 febbraio 2013

Aiuto mi sono scomparsi i favoriti!


E' possibile che dal menù di apertura o salvataggio dei file in Windows 8 scompaia la selezione delle locazioni preferite, in inglese "Favourites", nella barra a sinistra, altrimenti detta "Places Bar"

Tra queste locazioni ci sono normalmente il Desktop, i Download e i Recent Places, in più lo shortcut è facilmente personalizzabile facendo drag'n'drop del folder che vogliamo aggiungere.

Pochi però sanno che è possibile eliminare i Favourites, anche inavvertitamente, spuntando l'opzione "Mostra Preferiti" della Places Bar.


Per ripristinarli, basta spostarsi in basso nella Places Bar e selezionare "Mostra Preferiti" (Show Favourites).




venerdì 28 dicembre 2012

Sviluppare codice migliore con la programmazione funzionale


Minimizzare gli impatti del cambiamento dovrebbe essere uno degli obiettivi prioritari nella produzione del software, soprattutto se in contesti di medio-alta complessità. Normalmente, infatti, si assiste al fenomeno dell'ingessatura del codice: nessuno si azzarda a introdurre cambiamenti migliorativi perché questo potrebbe portare a conseguenze inaspettate, potenzialmente drammatiche.

Per minimizzare gli impatti del cambiamento esistono strumenti e tecniche diverse: ad esempio il test driven development, oppure il defensive programming. Un altro metodo è quello di scrivere codice secondo il paradigma della programmazione funzionale (FP = Functional Programming).




Un programma scritto in un linguaggio FP puro è normalmente esente da "side-effect": cioè è un software che si comporta in un solo modo, predicibile, e che ha un comportamento identico una volta compilato. Questo perché si traduce sostanzialmente in una funzione che prende in input una qualunque serie di funzioni che agiscono su costanti. E' come un meccanismo di ruote e pulegge: una volta in movimento, si comporta sempre nello stesso identico modo.

Purtroppo solo una piccolissima parte di programmi può essere scritta in FP pura. Questo perché un programma per essere utile deve poter prevedere: 1) input dall'esterno e 2) mantenimento di uno stato. Queste però sono due cose che sono "inesprimibili" in FP puro.

Quello che possiamo fare è invece utilizzare un linguaggio ibrido, che permetta cioè sia la programmazione imperativa (magari ad oggetti) cui siamo abituati, sia la programmazione funzionale, cercando di minimizzare e confinare la parte imperativa in un punto noto - e ridotto - del codice sorgente. Eccellenti esempi di linguaggi ibridi sono oggi Scala e C#.

In Scala, le variabili vengono nominate in due modi diversi: var, la variabile "normale" cui siamo abituati, e val, una variabile che, una volta che abbia assegnato un valore, non lo modificherà mai per tutta la sua vita. (In C# le variabili val di Scala sono scritte come readonly) Un programma scritto in Scala che abbia molte var, è un programma che segue la logica imperativa, che crea oggetti che mantengono uno stato e che quindi è potenzialmente pieno di side-effects. Viceversa, un programma che abbia pochissime o nessuna var, e val al loro posto, è un programma scritto in logica funzionale, e che avrà pochi o nessun side-effect. Questo secondo tipo di programma è molto più facile da mantenere, dovrà essere testato di meno, e quindi avrà maggiore valore.

Come si possono scrivere normali costrutti in logica funzionale? E' difficile, perché il nostro cervello è abituato a pensare in termini di "oggetti" e di "stato", e molto poco in termini di "funzioni" e "funzioni di funzioni". Però con un po' di pratica l'obiettivo può essere centrato.

Vediamo un esempio. Supponiamo di voler scrivere una classe che prende in input una stringa e ne calcola il suo valore ASCII (il valore ASCII di una stringa è la somma dei suoi caratteri intesi secondo la codifica ASCII).


class TestClass(givenString: String) {

    require(givenString != null)
    private var gStr: String = givenString


    def getValue() = {
        this.compute()
    }

    private def compute(): Int = {
        var tempSum: Int = 0
        for (charV <this.gStr.toCharArray()) {
            tempSum += charV.toInt
        }
        tempSum
    }

}


Questo programma in Scala contiene due var: una per mantenere lo "stato", che è la variabile che contiene la stringa da trasformare in numero, e una per mantenere il numero associato alla stringa mentre viene calcolato, all'interno di un ciclo for.

Come trasformare questa classe in logica funzionale?

Dobbiamo come prima cosa far sparire lo "stato" dalla classe. La nostra classe deve comportarsi come una "funzione" e quindi non deve mantenere in memoria parametri che possono cambiare valore nel tempo. Farlo è molto semplice: invece che memorizzare givenString come variabile (var) lo memorizzeremo come costante (val). Oppure, potremmo non memorizzarlo del tutto e passarlo così com'è al metodo di calcolo compute().

Più difficile è invece sostituire il costrutto for che calcola il valore. Qui useremo invece una formula classica della FP. Creeremo un metodo che ritorna una collezione, cioè un array dinamico, di valori ASCII, ognuno per ciascun carattere che forma la stringa. Poi su questa collezione applicheremo una funzione di trasformazione: nel nostro caso "sum". Ogni collezione fornisce metodi operatore sui valori che la compongono, e in più può accettarne di nuovi appositamente scritti.

Ecco il nostro codice trasformato in logica funzionale:

class ImmutableTestClass(givenString: String) {

    require(givenString != null)
    private val gStr: String = givenString

    def getValue() = {
        this.compute(this.gStr)
    }

    private def listOfValues(valStr: String) = {
        for (j <- 0 until valStr.length()) yield {
            valStr.charAt(j).toInt
        }
    }

    // 1. Convert the sequence to actual collection
    // 2. Add "mapping" to collection, example: .sum, .mkString
    private def compute(valStr: String): Int = {
        val listOfVals: List[Int] = this.listOfValues(valStr).toList
        listOfVals.sum
    }

}


Abbiamo buttato via le var e le abbiamo sostituite con val. Il codice è ora puramente funzionale. (E, tra parentesi, funzionerà molto meglio in contesti multi-threading).

Naturalmente lo stesso risultato si può ottenere con C#:

class Immutable
{
    private readonly String tString;

    public Immutable(String testString)
    {
        this.tString = testString;
    }

    public int GetSum()
    {
        return this.CharList().Sum();
    }

    private IEnumerable<int> CharList()
    {
        foreach (char ch in this.tString)
        {
            yield return (int)ch;
        }
    }
}

sabato 22 dicembre 2012

Masterizzare e montare una ISO su Windows 8

Windows 8 supporta nativamente il formato ISO, cosicché è possibile sia montare un'immagine ISO come drive virtuale, sia masterizzarla su CD/DVD/BluRay.

ATTENZIONE: se si è installato un software che gestisce i file .ISO (ad esempio WinZip o Demon Tools), le opzioni per la gestione dei file ISO non sono più visibili da menù contestuale. Occorre modificare le impostazioni dei software di cui sopra, per togliere l'associazione con i file .ISO.

PER MONTARE UN FILE .ISO

Clickare con il tasto destro del mouse sul file .ISO e selezionare "Monta". Il nuovo drive apparirà tra le risorse del computer.




PER MASTERIZZARE UN FILE .ISO

Per prima cosa inserire un disco CD/DVD/BluRay vuoto nel masterizzatore. Quindi clickare con il tasto destro del mouse sul file .ISO e selezionare "Masterizza immagine disco". Il disco verrà masterizzato con i contenuti del file immagine .ISO












lunedì 22 ottobre 2012

Creare un'app per Google Chrome


Piuttosto sorprendentemente, non esiste in tutto il Chrome Web Store, un'app che aggiunga al browser di Google, la ricerca delle immagini attraverso il motore Google stesso.

Detto fatto, ne facciamo una noi. Con un solo, piuttosto importante limite: non potremo distribuirla sullo Store, poiché il sito in questione appartiene a Google.

La nostra "app" apparirà nella "Nuova Scheda" di default del browser, e assomiglierà all'icona col cerchio intorno:


Un "app" per Chrome è nel nostro caso - cioè se vogliamo tipicamente rendere un link - molto semplicemente l'unione di un file manifesto e di un'icona.

L'icona la potete scegliere liberamente tra le molte disponibili su Internet. Io ho scelto questa. Scaricatela come PNG e salvatela col nome di icon.png.

Create una cartella sul Desktop e nominatela "ImageSearch".

Adesso, occorre aprire un editor - a me ultimamente piace molto Sublime Text, ma il Notepad o Vim può andare lo stesso, e copiare il seguente testo.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{

"name": "ImageSearch",
"version": "1.1",
"manifest_version": 2,
"description": "Google Images",

"icons": 
{
"128": "icon.png"
},


"app": 
{
"urls": ["http://www.google.net/"],
"launch": 
{
"web_url": "http://www.google.it/imghp?hl=it&tab=wi"
}
},

"permissions": [ "http://www.google.it" ]

}

Infine, salvate il testo di cui sopra come "manifest.json". (Notate che nella sezione "urls" ho messo un indirizzo falso. Questo serve se voleste pubblicare la app su un sito di vostra appartenenza).

Per usare l'app, basta aprire il Menù di Chrome (il tasto a destra a fianco della URL) e scegliere Strumenti/Estensioni.

Dopo aver spuntato l'opzione "Modalità Sviluppatore", si clicka su "Crea Pacchetto Estensione". A questo punto basta dare in input la directory che contiene il file json e l'icona, e il gioco è fatto.


venerdì 31 agosto 2012

Come ti rimpiazzo iGoogle


iGoogle è stato la mia home page per quasi dieci anni. Mi ci trovavo molto bene. Era veloce, gradevole da vedere, aveva la toolbar di search di Google (fondamentale) e insomma tutto quello che secondo me la home page deve avere.

iGoogle

Dopo anni di ottimizzazioni varie, ci avevo messo dentro tutte le cose che volevo vedere dal Web appena collegato. Per esempio ci avevo messo:
  • News feed dei principali giornali italiani (Corriere, Repubblica, Sole 24 Ore)
  • Feed dei principali siti di gaming (Kotaku, Gamespot...)
  • Feed dei principali siti di programming (MSDNStackOverflow, CodeProject...)
  • Un traduttore online (il migliore: Google Translate)
  • Il meteo di Milano e dintorni
  • Una lista dei miei cinque link web preferiti
  • I blog miei e dei miei amici
  • Ultimi tweet che seguo
Cosa invece volutamente non ci avevo messo:
  • News feed sportive (terribili se per caso ho un evento "in registrazione")
  • Mail (troppo disturbo: meglio andarci di proposito)
  • Facebook (come sopra)
Poi improvvisamente una tragica notizia: iGoogle chiude! Pare che sarà a Novembre (2013, v.commenti), comunque è irrevocabile, han detto quelli di Google che chiude.

Così ho cominciato a guardarmi intorno per rimpiazzarlo, e ogni prova che facevo mi convinceva che iGoogle era meglio. Ad esempio ho provato:
Nessuno mi soddisfaceva. Allora ho cominciato a riflettere: ma insomma, cos'ha iGoogle di così speciale? O meglio, cosa deve avere una Home Page per essere una buona Home Page?

Fondamentalmente deve avere 3 cose:
  • Una toolbar di search (quella di Google va benissimo)
  • Link ai siti utili (Translate / Calendar / Mail...)
  • News dal mondo
Poi mi sono reso conto di una cosa: i primi due punti sono implementati direttamente dalla quasi totalità dei browser moderni. Ad esempio in Chrome la toolbar che mostra la URL di un sito, è anche una toolbar di ricerca in Google. Sempre in Chrome, la Home Page di default è una collezione di icone (apps) che portano ai siti di maggior interesse: ad esempio la mia è così:


Le "news dal mondo" sono sostanzialmente dei feed RSS. Quindi mi rimaneva solo da scegliere un buon "news reader", cioè un programma che mi mostrasse i feed RSS nel modo giusto, cioè che mi permettesse di categorizzarli (news, gaming, programming, blog...) e visualizzarli in modo piacevole.

Ne ho provati un po'. Google Reader è un po' troppo spartano, altri erano troppo "barocchi" o mancavano di funzionalità. Alla fine ho scelto Feedly e lo trovo perfetto (un po' ostica l'interfaccia utente, ma dopo qualche tentativo si riesce a fare quello che si vuole). Ecco la mia page di News:


In definitiva così ho rimpiazzato iGoogle: il browser Chrome mi toglie la necessità di partire da un sito di ricerca come Google. Come Home Page (e New Tab) ho la pagina di apps di Chrome che mi porta alla mail, a Facebook, a quant'altro mi interessa; infine per leggere le news clicko su Feedly, anch'esso disponibile come "app" di Chrome.





venerdì 24 agosto 2012

Convenzione invece che Configurazione


Una delle rivoluzioni silenziose più importanti degli ultimi anni in informatica è l'avvento di strumenti, linguaggi e sistemi che sposano il concetto di

Convention over Configuration (CoC)

ovvero, in italiano, potremmo dire: seguire una convenzione piuttosto che configurare.

I più eclatanti risultati di questa impostazione - ovviamente solo tra quelli che ho potuto provare - sono, ad esempio:

  • Maven
    Un tool di management dei sorgenti, che effettua l'organizzazione e la compilazione del codice e della documentazione di un progetto software
  • Ruby On Rails
    Un famoso framework per scrivere applicazioni Web data-intensive.
  • SBT
    Un tool per la compilazione di codice sorgente in Scala (e non solo...)

Che cos'hanno di speciale questi oggetti software che implementano la CoC? Be' è presto detto: funzionano "da soli" come per magìa, senza bisogno di:

  • parametri a linea di comando
  • file di configurazione

Li scarichi, li lanci, e funzionano. Così, senza far niente, magicamente appunto! Chiaramente, dopo una prima fase in cui il tool si comporta in default, è sempre possibile arricchire e dettagliare in modo che esso faccia esattamente ciò di cui si ha bisogno.

Faccio un esempio. Comincio a scrivere il mio codice in Scala, un progettino, niente di che, ma comunque un bel po' di file sorgenti e documentazione. Ho bisogno di compilare, e scelgo un tool CoC come SBT. Lo scarico e lo lancio, così, nudo, senza alcun parametro!

> sbt

  1. Come prima cosa, SBT si rende conto che gli mancano delle librerie per partire. Ok, le scarica tutte dalla rete e le installa.
  2. Poi vede che non ho l'ultima versione di Scala: me la scarica e la mette "a fianco" alla versione che uso io.
  3. Si accorge che l'ho lanciato in una directory che contiene codice Scala: fa il parsing dei sorgenti e individua il file che contiene il metodo principale (Main)
  4. Compila tutti i miei file 
  5. Trova le dipendenze (Scala e Java), le compila e le mette in una directory di libreria
  6. Esegue il mio programma compilato!
Fantastico, no?

Cos'ho fatto io per permettere a SBT di funzionare così bene? Nient'altro che seguire delle "convenzioni": ad esempio, ovviamente, i miei file in Scala hanno estensione .scala, ma non molto più di questo.

Allo stesso modo, se scarico Ruby On Rails e ho il database Pippo, mi basta lanciare:

> rails pippo

perché "lui" mi sondi il database e mi costruisca un sito Web completo con tutte le funzioni di front-end per gestire il DB Pippo.

In maniera analoga, Maven, è in grado di scandagliare un progetto in Java, identificare le dipendenze, scaricarle da Internet, aggiornare il sistema e infine compilare e lanciare il progetto. Basta ovviamente che io segua delle "convenzioni" (ad esempio, le librerie sono in una directory /lib).

Questo è il futuro dei tool per lo sviluppo software, e sempre maggiormente la comunità di sviluppatori si aspetterà di avere a che fare con sistemi CoC che funzionano bene out-of-the-box, senza dover leggere quintali di documentazione o seguire passo passo noiosissimi esempi.



lunedì 30 luglio 2012

Non molto Agili... fin qui!

Navigando sul sito http://agilemanifesto.org mi sono accorto che sono passati otto anni da quando firmai il manifesto sullo sviluppo agile.



Cos'è successo in questi otto anni? Si fa un gran parlare, è vero, delle tecniche di sviluppo agili e termini come Scrum ed eXtreme Programming sono molto di moda, ma di fatto nella realtà enterprise - specie in quella italiana - continuano a non vedersi progetti sviluppati secondo la filosofia Agile dello sviluppo del software. Viceversa, nel mondo Open Source, l'Agile è di fatto la norma.

Spesso si vedono applicate le tecniche agili, come ad esempio Pair programming o Feature Driven Programming, ma in contesti che sono quelli tradizionali, e cioè quelli dello sviluppo waterfall, che nella realtà enterprise è tuttora l'unico modello supportato.

Frequentemente ho proposto di utilizzare un approccio Agile in diversi progetti reali, ma al di là di un qualche superficiale apprezzamento non si è mai andati.

Perché dunque, nonostante l'entusiasmo, specie degli addetti ai lavori, la metodologia Agile non ha preso piede? Io credo che le cause siano principalmente tre.

1. Il sistema non recepisce processi iterativi

Quello che caratterizza principalmente l'approccio Agile rispetto al Waterfall è il suo essere iterativo by design. Il progettista Agile sa che lo sviluppo software è spesso un processo "prima volta-primo uso", caratterizzato da un altissimo grado di incertezza, per affrontare il quale deve applicarsi una metodologia di gestione del rischio che non può che essere iterativa. L'iterazione tipica dell'Agile è quella indicata in figura:


Normalmente, in un progetto complesso, le iterazioni possono essere decine. Ma il "sistema" non è in grado di gestire le iterazioni! Se da una parte il Cliente vuole subito sapere quanto costerà il suo nuovo sistema informativo e quanto durerà il suo sviluppo, anche dall'altra il Fornitore ha tutta una serie di strumenti che funzionano solo se vengono immessi valori "a preventivo": quante risorse il progetto occuperà e per quanto tempo. Come ho riportato in altri post, la stima del costo (tempo, denaro e altre risorse) di un progetto "prima volta-primo uso" è un esercizio di fantasia destinato al fallimento. Tipicamente perciò chi fornisce un servizio di sviluppo software applica dei coefficienti di rischio molto alti proprio per cercare di assorbire questa incognita. Di fatto, nei sistemi dove è "necessaria" una stima dei costi a preventivo, il metodo Agile è escluso a priori.


2. Un processo che ricicla è considerato un processo di "serie B"

Nella concezione del Project Management classico,  il "riciclo" - quindi la re-iterazione - è considerato come un "difetto", o meglio come la "conseguenza di un difetto". Il progetto perfetto non presenta ricicli: viene eseguito così com'era stato pensato la prima volta. Per chi non possiede una cultura informatica (direi, una cultura informatica recente) l'idea stessa che una metodologia preveda molti ricicli è semplicemente orrenda. E' orrendo dover immaginare di avere stime riviste, nuove implementazioni e nuovi test ad ogni riciclo. Impensabile immettere ad ogni nuova iterazione nuove funzioni e quindi nuovi bug! Il Cliente percepisce il metodo Agile come una mancanza di professionalità (non sviluppano: provano a sviluppare!) e lo staff non tecnico del Fornitore la percepisce come una intollerabile mancanza di certezze: quanto ci costerà il progetto, quante risorse impiegherà e per quanto tempo.
Bisogna però fare i conti con la dura realtà: che è tanto più vera e documentata quanto più i progetti aumentano in complessità e novità: all'inizio nessuno può sapere quanto costerà il progetto, nemmeno a grandi linee. Si possono fare delle stime, sulle quali però non può essere calcolato il prezzo al Cliente. Proprio per la grande aleatorietà di queste stime "a-priori", il prezzo sarà o largamente esagerato per assorbire il rischio, o sottostimato destinato cioè ad andare in perdita. Come dicevo, i sistemi (finanziari, di controllo e gestione e via dicendo) aziendali prevedono che questo prezzo venga calcolato all'inizio, sulla base del quale verranno poi derivati tutti i driver economici dell'azienda. Un calcolo basato, il più delle volte, sulla fantasia.


3. La metodologia Agile presuppone il Time&Materials

Esistono tipicamente due modi per vendere un servizio informatico: a pacchetto (turn-key o fixed bid) o a tempo (time&materials, T&M). Nel primo, chi offre "scommette" su quanto effettivamente gli costerà il servizio: applica alla scommessa il proprio coefficiente di profitto e ottiene il prezzo. Nel secondo, semplicemente vengono erogati dei servizi e il Cliente paga "il tempo" di erogazione.
Per quanto abbiamo detto sin qui, la metodologia Agile presuppone la seconda opzione. Perché per poter vendere qualcosa turn-key occorre essere confidenti sulla stima dei costi, cosa che abbiamo visto è molto difficile nel caso di progetti complessi. E perchè l'Agile è iterativo di suo.
Il committente di un progetto informatico complesso è molto poco propenso a iniziare a lavorare T&M, perché anche lui deve fornire una stima di quali saranno i suoi costi/tempi, e questo a priori! La naturale conseguenza di questo stato di cose è che si formulerà un'offerta turn-key molto sovrastimata nei costi, ed esageratamente lunga nei tempi.


Io credo che queste tre siano le cause principali che hanno bloccato l'introduzione dei modelli Agili nella pratica dello sviluppo software a livello enterprise. Sono convinto che un approccio iterativo e T&M possa permettere significative economie sia per chi vende, sia per chi compra soluzioni software. Tuttavia, perché lo sviluppo Agile possa essere effettivamente utilizzato, occorrono notevoli cambiamenti in termini di cultura, processi e strumenti di supporto aziendali.