Visualizzazione post con etichetta università. Mostra tutti i post
Visualizzazione post con etichetta università. Mostra tutti i post

domenica 9 luglio 2017

POSSE è passato anche da Bologna

POSSE ovvero Professors' Open Source Software Experience è una sorta di linea guida per aiutare i professori universitari e, di riflesso, gli studenti ad avvicinarsi al mondo dell'Open Source. L'idea è abbastanza semplice: i professori devono arrivare ad insegnare agli studenti come collaborare in un progetto HFOSS (Humanitarian Free Open Source Software - software che abbia impatto sociale) attraverso l'apprendimento loro stessi degli strumenti e delle metodologie alla base della cultura Open Source.
POSSE si fonda su tre livelli, chiamati stage:
  1. in questa fase preliminare si prende conoscenza con gli strumenti e le licenze, nonché si inizia a valutare obbiettivi semplici e raggiungibili sui quali far lavorare gli studenti;
  2. in questa fase face-to-face si lavora tutti assieme in un workshop di due giorni per mostrare i risultati della fase 1, le esperienze, nonché valutare ed inserire obbiettivi di maggior impatto pratico per la fase successiva;
  3. in questa fase l'applicazione ad un progetto Open Source dovrebbe trovare risvolto pratico e dare soddisfazione a studenti e docenti che, nel frattempo, sono diventati membri effettivi della comunità Open Source.

Pur non avendo mai partecipato ad uno schedule POSSE mi immagino che gli stage possano essere così schematizzati:
  1. apprendimento di strumenti quali canali IRC, mailing list, revisione del codice, test;
  2. condivisione di esperienze e modalità di insegnamento degli strumenti di cui alla fase precedente, nonché loro applicazione pratica nei corsi di laurea;
  3. sviluppo di una o piu' patch per un progetto prescelto.

Francamente ritengo che i tempi per gli stage siano abbastanza lunghi, si parla ad esempio di 6 mesi per il solo stage 1!
Tuttavia occorre ricordare che si parla di didattica accademica, e quindi occorre anche avere il tempo di introdurre gli strumenti nel corso di laurea, e questo potrebbe spiegare la necessità di un simile periodo temporale.

Ma perché questa digressione su POSSE?

A Luglio si è svolto lo stage 2 dell'anno 2017 presso l'Università di Bologna, ma ahimé i partecipanti erano tutti stranieri e non leggo nessun nome italiano delle università limitrofe. Questa è secondo me una pessima notizia che dimostra ancora una volta l'arretratezza culturale alla quale sono sottoposti gli studenti delle università della mia zona.

Mi auguro che molti altri docenti e ricercatori italiani possano unirsi all'idea POSSE o a simili iniziative e possano mettere a frutto una maggiore esperienza nel mondo Open Source e nelle community ad esso collegate.

lunedì 10 aprile 2017

On learning thru Open Source Software

I read an interesting blog post on adopting open source at university as a way of teaching computer science, and I posted also a comment
on such article.
Here I would like to extend my point of view about the subject.
Having worked in an university for a few years, having done computer science at both sides of the desk, and having a quite good
experience in what became my day-to-day work, I believe I can express some opinion about.

Adopting open source as a teaching methodology should just be.
Period!
Instead of asking students to produce the same crappy software all over the time (a database layer, a GUI layer, a music store,
a calculator), put them on a real piece of software that someone in the world could use and adopt.
Why?
  1. motivation: students will be happy to work on some real stuff with the main author(s) thanking them for their help, time,
    and work;
  2. learn something useful: real programs do things in the real world, and things in the real world must work, and work fast, and work
    in accurate way. That is:
    • work on real data: nobody will ever notice your crappy homework do a full table scan each time you need to display one of your
      fake music titles out of ten, but a real program will freeze once you try to do a full table scan just to display out a detail
      out of a million records. This is something university cannot teach you, trust me!
    • deal with problems: university will teach you a lot of theory about using natural keys, algorithms to sort structures, avoid
      data replication, and so on. Not always these approaches will drive you to a manageable software: learn to deal
      with surrogate keys, duplicate data when it makes sense (e.g., network latency, historical reasons and so on).
    • learn the tools: developers around the world need to coordinate. Learn to use bug reports, stay on mailing lists, IRC channels,
      and alike. Don't ask stackoverflow for someone to do your homework, learn how to find documentation and search for answers. Become
      acquainted with revision control, compilers, linkers, and different platforms.
    • document for someone else: it is easy for you to explain what you have done to your teacher, in particular if you did it in the very
      previous period of time (typically a semester). But can you document something so that another developer, even another student like
      you, can understand one year later why and how you did a task?
  3. do not start a project from scratch: typically the university cycle during semesters is something like design-implement-compile-run-explain-throw away_
    and then you start over and over again every time you got an assignment, homework, or project. This is wrong! Real life does not work as such:
    in real life you are often assigned to maintain or refactor an existing piece of code without having to throw it away.
  4. learn idioms: developers around the globe are smarter than you. It is not they are more intelligent, it is just they are more expert
    and know better the subject. Reading someone else (smarter) code is a great way to improve your knowledge and become smarter too. Learning idioms,
    seeing patterns applied to real world code is a great start to become a professional coder.
  5. fun: developers have their habits. They meet together in so called conferences, and usually got beers while talking about code, travel
    around the world, and have a lot of fun. And even if you stay closed in your room, doing your homework, having a chat, a video call
    or an email in your in-box with a "thank you" or "good job!" is really fun.

There are other reasons, but the above are my main choices to push students to the open source world.
So far, it seems that you are going to have only advantages and no drawbacks, but that's not true.
Becoming an open source contributor you are going to become smarter than your own university teacher, and this is a drawback so far as
the teacher signs your curriculum. It is something that is really hard for a teacher to keep in mind, but it is so true.
I was always saying to my student, in the very beginning of each class, that at the end they will know better than me the subject, and the reason
for that is that "I'm not going to spend whole nights studying before the exam!".
So, if you are a teacher, simply accept that.
Accept that a student could prove a better algorithm, or an idiom you don't know that works. Ask him for the details, learn from him.
Learning is not a one-way process, with a god-like teacher and an idiot-like student; learning is a cooperation where someone expert provides the sparkle to someone else.
Would not be nice to see if both can grow during the path?

There is also another drawback: open source is not something you can teach without knowledge. You have to know the tools: revision control, IDEs,
bug tracking, issue tracking, wiki, testing and alike.
Most teachers urge teaching C pointers arhitmetic instead of basic tools, and that's not good.
Allow me to provide my very own example: I spent five years in a computer science degree, and nobody told me about revision control. While
doing my master thesis, being afraid of loosing some change or to mistakenly do a single line change (that will not blow up your project, right?),
I did my very own backup shell script that was running every hour to keep an historical copy of my work.
Shame on me, in the very same time I could have learnt rc or cvs (no, it was before git).

So my advice for students is be a part of an open source community, you will surely learn something that will make the difference in
your real job.
And my advice for teachers is accept smarter students and promote the adoption of an open source code base. There are a lot of "mini-hackers"
initiatives around the world (CPAN Pull Request, Hacktoberfest, etc.), pick one and try let your student do the rest.
You'll be happier, your student will be happier, the open source community will be happier and, who knows, your employer could also
become a partner in an open source community.

sabato 4 febbraio 2017

Hey students, don't buy the teachers' lies!

When I was an university student I had a teacher in the Operating Systems subject that teached me (and a lot of others) to program so bad in shell scripting! I will not name her, but I had to say that today I find the very same errors around the scripts that my colleagues write every day, and this is a kind of watermark of the damage she did.

Luckily I find my way out, studying on other books and practicing on my own (Linux) computer.

So what were the problems?
To understand it must be clear the exercise schema the teacher was adopting, and that was pretty much always the same: a main script (let's call "coordinator" which aim is to parse the argument list and invoke, using recursion, a "worker" script.
Something that can be shown as the following code:

#!/bin/sh
# coordinator

# argument validation...

# export the current directory
# in the path to invoke the worker script
PATH=$PATH:`pwd`
export PATH

# first call of the worker
worker



#!/bin/sh
# worker

# recursion on myself
for f in *
do
if [ -d $f ]
then
worker f
fi
done

# do other work...



The first problem, in my opinion, is the usage of relative paths to invoke the worker script, and therefore the need for exporting the PATH variable. First of all, launching a script with a relative path makes it a little slower to launch, since the shell itself has to search for the script against each PATH entry. Second, and much more important, it is the key to exploitation: not having the control over the full path of the script it is possible to inject a malicious script somewhere in the PATH and use it as a worker.
When I objected the above to the teacher, the answer was to simply invert the PATH manipulation order:

PATH=`pwd`:$PATH
export PATH

But again, this is a kick in the ass of security: what if I name my script as another system wide command? I can alter the behaviour of this and other programs...
So what is the solution? Of course invoke the worker script with an absolute path and to not manipulate the PATH variable. After all, what is the point in showing (to the teacher) you can export a variable?

Another problem is the recursion on the worker script: usually such script was scanning a directory content, invoking itself each time a subdirectory was found. Now, while this can work in theory, you can easily imagine the worker script becoming a fork-bomb. It is quite easy to see how find(1), xargs(1) and friends can help in this situation.

Another oddity that comes into my mind is the way students were forced to test if an argument was an absolute path or a relative one:

case $1 in
/*) # absolute
;;
*) # relative
;;
esac


Do you believe the above is easy to read? Is it efficient and does it scale well? Why not using Unix tools and pipes, regular expressions and awk? even better, getopt anyone?

So, dear ex-teacher, what is the whole point in teaching such shit?

martedì 6 dicembre 2016

Quando scrivere gli articoli scientifici diventa un'arte

Un interessante articolo su come sia possibile utilizzare strumenti evoluti, anche se apparentemente antichi, per creare un workflow di editing degli articoli scientifici.
Ormai io non scrivo piu' molte pubblicazioni scientifiche, ma quando lo faccio uso strumenti molto simili. L'università invece, e paradossalmente, ha sempre cercato di condizionarmi mentalmente all'uso di strumenti di editing "piu' user-friendly" (leggasi Microsoft) e nessun controllo di gestione se non il Salva con nome e l'aggiunta di un numero progressivo...insomma, altro che approccio scientifico!

giovedì 20 novembre 2014

Richard Stallman a Modena

Richard Stallman non ha certo bisogno di presentazioni.
Ne è convinta anche l'Università di Modena, presso la quale il prossimo 24 Novembre, Stallman terrà un discrso sulla libertà digitale.
Resto un po' deluso dal vedere come l'incontro di Stallman sia riportato da una misera nota sul portale universitario, con anche evidenti errori di battitura. Fra le altre cose, nemmeno un link all'evento ufficiale della FSF, che richiede anche una registrazione anonima (cosa non richiesta dal sito dell'università)...

martedì 18 settembre 2012

Programmazione ad oggetti in C (ereditarieta')

Qualche giorno fa ho ricevuto un commento via e-mail ad uno dei primi post su questo blog, quello relativo all'utilizzo di casting fra i puntatori per simulare la programmazione OOP in linguaggio C.
Il commento in questione era relativo all'introduzione di uno o piu' metodi pubblici nella classe, che facendo riferimento a due strutture in overlapping, poteva risultare impossibile.
Per comprendere bene come procedere occorre anzitutto considerare la struttura stessa del sistema:
  • il fatto che esistano due strutture, una privata e una pubblica, non significa che vi siano due "istanze" separate: si deve pensare alla parte pubblica come al file header di una classe C++ e alla struttura privata come alla sua implementazione;
  • l'introduzione di un metodo pubblico, come pure di un qualsiasi altro attributo, e' una operazione che non va fatta nella classe base, ma in eventuali sottoclassi. Se venisse infatti fatta sulla classe base si farebbe una "banale" ristrutturazione della classe stessa, che a meno di ovvi problemi di compatibilita' binaria, continuerebbe a funzionare come prima.

Ho quindi deciso di estendere l'esempio del conto corrente creando una sottoclasse, chiamata ContoCorrenteConCarta (nei file CCX_pub.h e CCX_private.c) che estende le informazioni di base del conto corrente aggiungendo una carta di credito. Ho anche colto l'occasione per estendere il conto corrente stesso con alcune ovvie informazioni che avevo tralasciato, come ad esempio il titolare del conto.
Tutti i sorgenti nella loro nuova versione sono disponibili su uno dei miei repository su github.

Come per la classe conto corrente di base, la classe con carta di credito deve definire due strutture sovrapposte, una privata che contiene l'implementazione e una pubblica che contiene l'interfaccia.
La parte pubblica e' definita come:


typedef struct CCX_PUB {

  // riferimento ad un conto corrente normale
  ContoCorrentePub* super;

  // metodo che ritorna il numero della carta di credito
  char* (*m_numero_carta)( struct CCX_PUB * );

} ContoCorrenteConCartaPub;



Si noti che la struttura contiene un puntatore alla sua superclasse, o meglio ad una istanza della superclasse. Il puntatore e' stato volutamente denominato "super" per meglio indicare il legame con una istanza della superclasse.
La parte implementativa risulta come segue:


typedef struct CCX_private{
 
  // riferimento alla parte pubblica
  ContoCorrenteConCartaPub pub;

  /*------ dati nascosti ------------*/

 
  // numero della carta di credito
  char* numero_carta;
 
} ContoCorrenteConCartaPrivate;



dove, come al solito, il primo campo e' una variabile di tipo "pubblico" per fare in modo che il casting di puntatori fra ContoCorrenteConCartaPub e ContoCorrenteConCartaPrivate possa funzionare come nell'esempio del conto corrente semplice.
Al solito si definiscono dei metodi di conversione da parte pubblica a privata per il nuovo tipo di conto corrente. Occorre anche definire un metodo di inizializzazione, che ad esempio puo' essere come il seguente:


ContoCorrenteConCartaPub* abilitaCarta( ContoCorrentePub* contoNormale, char* numero_carta ){

  // controlli di sicurezza
  if( contoNormale == NULL || numero_carta == NULL )
    return NULL;


  printf("\n\t[abilitaCarta] Abilitazione carta %s su conto %s",
         numero_carta,
         contoNormale->m_titolare( contoNormale ) );

  // costruisco un nuovo conto corrente esteso
  ContoCorrenteConCartaPrivate *ccpriv = malloc( sizeof( ContoCorrenteConCartaPrivate ) );


 
 
  // inserisco il conto normale nella struttura pubblica
  ContoCorrentePub* superClass = aperturaContoCorrente( 

                          contoNormale->m_numero_conto( contoNormale ),                           contoNormale->m_titolare( contoNormale )
                              );
  ccpriv->pub.super = superClass;

  // Metodo getter per la carta di credito
  ccpriv->pub.m_numero_carta = getNumeroCartaDiCredito;

  // inserisco il numero di carta nella struttura privata
  ccpriv->numero_carta = numero_carta;

  // oggetto costruito!
  return Private2Public( ccpriv );
 

}




Si noti che il metodo abilitaCarta funge da costruttore di copia: dato un conto corrente normale (senza carta), si costruisce un oggetto con carta di credito "attorno" a un clone del conto corrente.
Questa operazione di copia e' una pura scelta implementativa, sarebbe stato possibile usare il conto passato come argomento invece che crearne un clone. Si noti comunque che il clone ha dei puntatori alla stessa area dati (es. il titolare), e quindi questo costruttore effettua una shallow copy. Ovviamente questa implementazione non raffinata e' per mantenere l'esempio semplice.
L'uso della parola "superClass" all'interno del metodo non e' a caso: il conto normale di partenza contiene infatti i dati (e i metodi) che faranno si che il conto carta di credito possa essere trattato anche come conto normale. Inoltre il conto con carta prevede una variabile di tipo conto corrente normale al suo interno, creando quindi un link fra le due implementazioni che e' appunto il legame di ereditarieta'.
Volendo essere piu' precisi si dovrebbe sostituire il nome "superClass" con "super", per seguire una terminologia Java, ad ogni modo e' il concetto che conta.

Alla fine della costruzione si ha quindi un conto corrente con carta di credito che contiene un link ad un conto normale, inglobato in esso, e gli attributi aggiuntivi definiti nell'estensione della classe stessa.
L'utilizzo del nuovo tipo di conto e' semplice, ad esempio:


        printf( "\nCostruzione di un conto con carta di credito\n");
        ContoCorrenteConCartaPub *ccCarta = abilitaCarta( C1, "123456789" );

        ContoCorrentePub* ccpub = ccCarta->contoCorrente;
        printf( "\nCarta di credito per il conto %s = %s\n",
                ccCarta->super->m_titolare( ccCarta->super ),
                ccCarta->m_numero_carta( ccCarta ) );



Si noti che e' possibile "castare" il conto corrente con carta ad uno senza (ossia alla superclasse), accedendo al campo "super" della sua interfaccia.
Ne consegue che le due righe seguenti sono equivalenti:


ccCarta->super->m_titolare( ccCarta->super );
ccpub->m_titolare( ccpub );



E per il polimorfismo?
Avere un metodo polimorfico significa, lato pratico, che il puntato alla funzione contenuta nella implementazione (della superclasse) sia modificato.
In realtà la cosa e' leggermente piu' complessa: non deve essere infatti modificato il puntatore nella sueprclasse, ma un nuovo puntatore nella sottoclasse deve essere introdotto.
Infatti rimuovere/modificare il puntatore nella superclasse significa perdere ogni possibile legame con il metodo ridefinito, cosa che invece puo' tornare utile ad esempio se si deve invocare tale metodo.
Per semplicita' si supponga di voler sovrascrivere il metodo che fornisce il titolare di un conto corrente, in modo che nel caso ci sia una carta di credito venga stmapato il nome del titolare e il numero della carta.
La struttura pubblica del nuovo conto corrente con carta di credito viene quindi modificata come segue:


typedef struct CCX_PUB {

  // riferimento ad un conto corrente normale
  ContoCorrentePub* super;

  // metodo che ritorna il numero della carta di credito
  char* (*m_numero_carta)( struct CCX_PUB * );

  // overriding del metodo titolare di ContoCorrentePub
  char* (*m_titolare)( struct CCX_PUB * );

} ContoCorrenteConCartaPub;




La definizione del nuovo metodo e' la seguente, da inserire nella implementazione di ContoCorrenteConCartaPrivare:


static
char*
getTitolare( ContoCorrenteConCartaPub *ccpub ){
  if( ccpub == NULL )
    return NULL;

  ContoCorrenteConCartaPrivate *ccpriv = Public2Private( ccpub );
  ContoCorrentePub *super              = ccpub->super;
  char* titolare_super = super->m_titolare( super );
  char* titolare_desc  = malloc( sizeof( char ) * strlen( titolare_super ) * 2 );
  sprintf( titolare_desc, "%s (%s)", titolare_super, ccpriv->numero_carta );
  return titolare_desc;
}




Come si puo' notare il metodo combina della logica legata solo al conto con carta di credito a della logica della superclasse, andando infatti ad invocare il metodo della superclasse.
Il resto del codice viene modificato di conseguenza per inserire il nuovo puntatore a funzione e utilizzare il nuovo metodo.

Occorre fare una riflessione sul meccanismo del polimorfismo sopra descritto.
Anzitutto si noti come cambia l'argomento del metodo, che a seconda della posizione in cui si trova nella catena di ereditarieta' accetta un puntatore alla istanza di classe stessa. Questo e' anche il metodo con il quale molti linguaggi OOP implementano le chiamate di metodo.
Tuttavia questo rudimentale meccanismo non permette di effettuare una vera chiamata polimorfica: se si usa un puntatore alla superclasse (ContoCorrentePub) e si invoca il metodo si otterra' l'esecuzione del metodo della superclasse.
Affinche' anche la superclasse invochi il metodo definito per ultimo nella catena di ereditarieta' occorre modificare il puntatore alla funzione m_titolare di ContoCorrentePub affinche' punti alla nuova implementazione. All'interno del metodo si dovra' poi fare il cast esplicito da ContoCorrentePub a ContoCorrenteConCartaPub.
In questo modo pero' si rischia di perdere il legame al metodo precedente, e quindi di non poterlo piu' invocare. E' quindi compito della implementazione della sottoclasse mantenere i puntatori necessari e fare gli aggiustamenti ai pnntatori della superclasse stessa.

giovedì 1 marzo 2012

goto (2)

L'istruzione C goto è, come spesso si sente dire, sconsigliata in ogni contesto. Come mostrato in un mio vecchio post, il kernel di Linux include migliaia di istruzioni goto. Ebbene l'esecuzione della stessa ricerca all'interno del solo ramo sys di un kernel FreeBSD (8.2-RELEASE) mostra un totale di 20898 istruzioni goto! La cifra è grosso modo il doppio del corrispondente di un kernel Linux.
Ovviamente la cosa non deve trarre in inganno, non si è davanti ad un esempio di cattiva programmazione: le istruzioni goto si trovano infatti maggiormente nel codice specifico delle varie architetture supportate. Esse rappresentano un modo sintetico ed efficace di salto incondizionato.

mercoledì 10 agosto 2011

FLAP is now available as Open Source

A few days ago I created a repository on GitHub to host a few bits of source code: Ferrari Luca's Agent Platform (FLAP). This tiny project is a Java agent platform inspired by Aglets that I used during a course I did at the University of Modena and Reggio Emilia in late 2006. My idea was to present students with a simple agent platform, easy to understand and to debug, in order to make they understand the main concept behind concurrency, thread management and agent messaging a platform must accomplish. The platform represents also a good starting point to do experiments against agent algorithms and theories, and it is for this reason I'm releasing this as Open Source. You are free to experiment and improve the platform as much as you want, but please take into account that the platform is intended to be a didactic workbench, not a professional or complex product. The code compiles with Apache Maven, and if you run test you will actually prompted with a micro interactive shell.

The code is released under the BSD license, so you are really free to do whatever you want with it. But if you find it useful in your courses, studies, free time, please let me know.


venerdì 8 luglio 2011

Template, Generics e quello che non sempre viene spiegato

Anni fa, in occasione dell'uscita della versione 5 del linguaggio Java (release Tiger) tenni un seminario di dipartimento presso l'Universita' degli Studi di Modena e Reggio Emilia nel quale presentavo tutte le novita' introdotte nel linguaggio (qualche copia del seminario si trova ancora in giro, anche se non garantisco l'autenticita' - chi vuole averne una copia autentica mi contatti).
Una delle novita' di Java 5 erano i "Java Generics". In occasione della presentazione di generics, una eminenza grigia, professorone con anni di esperienza nella OOP e nella programmazione C++, con tono sprezzante e quasi schifato disse:

    hanno copiato i templates C++ e li hanno applicati a Java, nulla di nuovo!

All'epoca ero troppo educato per rispondere male! Con questo articolo pero' voglio mettere in chiaro le differenze fra i templates del C++ e i generics di Java, sottolineando come il pensiero sopra espresso dal professore universitario sia ben lontano dalla realta'.

Si consideri Java Generics, di cosa si tratta? Generics e' un modo per evitare errori grossolani di conversione di tipi facendo fare del lavoro sporco al compilatore. Il compilatore Java e' sempre stato fortemente tipizzato, ma solo per quello che riguarda i tipi primitivi. Nel caso degli oggetti, grazie al principio di sostituzione e alla base comune, Object, ogni oggetto potrebbe essere convertito in uno di un altro tipo passando per un Object. Questo genera una serie di errori di coerenza come il seguente:

   Persona madre = new Persona();
   Persona padre = new Persona();
   Animale cane  = new Animale();
   List famigliari = new LinkedList();
   famigliari.add( madre );
   famigliari.add( padre );
   famigliari.add( cane );    // disastro!

A meno che non si abbia una forte considerazione del proprio cane, esso non andrebbe inserito nella lista dei famigliari (il fatto che il proprio cane debba essere inserito o meno nella lista dei famigliari è un argomento che esula da generics!). Il problema nasce a run-time, quando si cerchera' di manipolare gli oggetti eseguendo dei cast che non saranno verificati.
Generics permette di intercettare tali errori permettendo ad una classe di definire dei "segnaposto" generici il cui tipo verra' specificato al momento della creazione dell'istanza. In altre parole il codice di cui sopra diviene:

   Persona madre = new Persona();
   Persona padre = new Persona();
   Animale cane  = new Animale();
   List famigliari = new LinkedList();
   famigliari.add( madre );
   famigliari.add( padre );
   famigliari.add( cane );    // errore di compilazione

In questo caso il compilatore sa che la lista deve accettare solo istanze valide di Persona, e quindi rifiuta di compilare un programma con un simile errore di logica.
Si noti che il controllo di coerenza avviene solo a compile-time: a run-time l'informazione sui tipi viene totalmente rimossa (type erasure) e tutti i tipi generici sono sostituiti con Object. Questo e' dovuto al fatto che un programma compilato con Generics deve poter eseguire anche su una virtual machine che di generics non sa nulla.

I template C++ sono differenti. Anzitutto i template consentono due funzionalita': generics e meta-programming. La prima funzionalita' e' analoga a quella di Java: si definisce un marcaposto per un tipo e tale tipo verra' specificato al momento della istanziazione (nel codice). Il programma di cui sopra diventa:

  class Persona{};
  class Animale{};

  template< class L >
  class List{
  private:
   L elements[3];

   public:
   inline void add( L newElement ){
          // add code
   }
  };


  // quando occorre usare la lista
  List famigliari
< Persona >;
  famigliari.add( padre );
  famigliari.add( madre );
  famigliari.add( cane ); // errore di compilazione


Il sistema riporta un errore di compilazione simile al seguente:

   error: no matching function for call to ‘List::add(Animale&)’
   note: candidates are: void List::add(L) [with L = Persona]

Potrebbe sembrare che almeno nella implementazione di Generics Java e C++ siano identici, in realta' C++ permette la definizione di classi compilate in modo differente per ogni tipo specificato. Quindi mentre in Java esiste una sola classe List che accetta degli Object controllati dal compilatore, in C++ possono esistere piu' versioni della lista compilata ciascuna con ogni tipo richiesto.

Ma la differenza fra i templates C++ e Java Generics diventa ancora piu' evidente quando si parla di meta-programming. In sostanza i templates C++ possono essere applicati non solo a delle classi, ma anche a dei metodi:

   template
   T findMax (T a, T b) {
     T result;
     result = (a>b)? a : b;
     return (result);
   }

ovviamente per avere senso i template applicati ai metodi dovranno spesso  sfruttare anche l'overloading degli operatori.

Infine il C++ utilizza i template per "capire", a tempo di compilazione, come parametrizzare il codice che genera. E' quindi possibile forzare non solo il tipo di un parametro, ma anche il valore, in modo da costringere il compilatore a compilare il codice con un parametro inserito in modo hard-coded. Si consideri il seguente esempio:

template< int printCount, int spaces >
class Printer{
public:
  static void print(){
    string printString = "Hello World!";
    for( int i = 0; i < printCount; i++ ){

      // stampo gli spazi
      for( int j = 0; j < spaces; j++ )
        cout << " ";

      // stampo la linea e l'andata a capo
      cout << i << " " << printString << endl;
    }
  }


  void croack(){
    string printString = "Hello World!";
    for( int i = 0; i < printCount; i++ ){

      // stampo gli spazi
      for( int j = 0; j < spaces; j++ )
        cout << " ";

      // stampo la linea e l'andata a capo
      cout << i << " " << printString << endl;
    }
  }
};


  int main( int argc, char** argv ){
    cout << "Programma in esecuzione" << endl;
    Printer< 5, 5 >::print();

    Printer< 2 , 8> myPrinter;
    myPrinter.croack();
    cout << "Programma terminato" << endl;
  }

La classe Printer definisce due metodi identici: print (statico) e croack (di istanza). Tali metodi traggono vantaggio del valore di due parametri specificati come template (spaces e printCount) per stampare un certo numero di volte e con un certo numero di spazi di indentazione la famosa stringa "Hello World". La cosa interessante, e che Java non permette, e' che il valore dei parametri viene specificato direttamente al momento della chiamata della funzione statica o della creazione dell'istanza. In Java la classe Printer avrebbe dovuto avere una implementazione simile alla seguente:

public class Printer{
       PRINTCOUNT printCount;
       SPACES      spaces;

       public Printer( PRINTCOUNT count, SPACES spcs ){
                 printCount = count;
          spaces     = spcs;
       }
      
       // metodi analoghi alla classe C++
}

e la si sarebbe dovuta istanziare cosi':

  Printer printer = new Printer(5, 10);

senza la possibilita' di usare il metodo statico direttamente.
Riassumendo quindi Generics e' solo una branchia del template programming, che si estende ben oltre la semplice "specifica variabile dei tipi" e i "controlli di compilazione". L'idea dietro al templating e' si quella di creare classi generiche, ma anche algoritmi generici (come la funzione findMax di cui sopra) e dare la possibilita' al compilatore di capire cosa succedera' a run-time, generando codice specifico per il programma.

In considerazione di questi semplici esempi didattici, e considerata l'affermazione del professore riportata all'inizio, viene da chiedersi se tale professore sia maggiormente incompetente in Java, in C++ o in generale nella OOP. E la cosa che fa ancora piu' amarezza, e' che tale professore continuera' a formare studenti e programmatori che dovranno apprendere da soli cosa realmente siano i templates.


martedì 29 marzo 2011

Smettetela di proteggere le slide con le password!

Sembra divenuta ormai una moda quella di inserire delle password nelle presentazioni dei docenti universitari, e l'Universita' di Modena e Reggio Emilia non e' da meno. Per l'ennesima volta vengo rimbalzato ad un link dell'universita' che promette di mostrarmi le slide di un determinato argomento, per poi sbeffeggiarmi con una richiesta di password che ovviamente non conosco. E io inizio nuovamente a pormi l'interrogativo sull'utilita' di questo approccio, o meglio sulla sua inutilita'. Molti docenti, lo so per certo, adottano questa tecnica per tenere lontani i curiosi, diciamo studenti di altre facolta' e atenei, mettendo quindi i propri studenti in una posizione privilegiata. Cosa tutto sommato ragionevole, se non fosse che le stesse slide presentate dal docente si basano spesso su argomenti generali, abbastanza generali da essere trovati su Internet su un qualche altro sito, e spesso sono basate su altre presentazioni/lucidi/wiki/documenti liberamente disponibili. Non si vede quindi la ragione di prendere tali slide e farne una versione privata; se si teme che l'utilizzo delle slide non sia coerente con le volonta' del docente si studi un qualche metodo di licensing (es. Creative Commons). Inoltre e' indispensabile una nota riflessiva: possibile che tutti questi docenti si sentano cosi' superiori ai propri colleghi che rilasciano documentazione liberamente? Ad esempio, per un corso di database perche' le slide devono essere "blindate" quando magari si basano su documentazione liberamente disponibile su PostgreSQL (e magari su slide rese pubbliche da ITPug)? E ancora, perche' questi docenti che spiegano ed evangelizzano il free software non evangelizzano anche la free documentation? Il Free Document Day si sta avvicando, urge una riflessione....

giovedì 25 novembre 2010

Università e professionisti... alcune riflessioni (parte 2)

Dopo una settimana dall'articolo di giornale che mi aveva spinto a scrivere alcune considerazioni sul rapporto fra le Università e il mondo dei professionisti mi sono imbattuto in un altro articolo, questa volta sul Resto del Carlino di Modena, che tratta le proteste contro la "riforma Gelmini" presso il cinema teatro Raffaello.
L'articolo inizia evidenziando come ci sia l'assenza di 110 mila tecnici che le imprese in Italia non trovano, fatto questo che porta ad una semplice tesi: occorre maggiore supporto alla formazione di tali tecnici, ossia maggiore supporto alle scuole e agli atenei, asilo nido dove i giovani talenti possono crescere. Tesi troppo semplice, troppo banale. Anzitutto per formare dei buoni tecnici occorrono dei buoni insegnanti, e ricadiamo nel discorso che ho già affrontato sul collegamento docenti-mondo del lavoro. Dopotutto, quanti docenti si prendono un periodo sabbatico per migliorare e aumentare le proprie competenze? Quanti docenti prendono delle certificazioni? Ora voglio stendere una tesi piu' banale ancora di quella dell'articolo che ho letto: se adesso ci si lamenta per il mancato supporto alla didattica, cosa si è fatto di significativo nella didattica fino ad ora? Ovvero, se mancano 110000 tecnici qualificati significa che le persone formate fino a ieri non sono state abbastanza formate per far fronte alle reali necessità del mondo del lavoro. Quindi non può essere la riforma tanto protestata a creare questo ammanco, semplicemente perché l'ammanco esisteva già da prima. Sicuramente un taglio netto ai supporti non può diminuire la carenza di tecnici, anzi la potrà anche aumentare, ma, continuando sulla linea della "tesi-semplice", il supporto fornito fino ad ora a cosa è servito? Evidente a poco....
E per quale motivo i tecnici non possono essere formati direttamente sul campo? Perché al taglio delle ore di laboratorio non si fa fronte con collaborazioni nel mondo professionale? Ah già, i professionisti non vogliono perché è periodo di crisi...

Ma non è che forse ci si sta lamentando troppo? Non è che in realtà quello che si vuole è un pezzo di carta firmato e timbrato che dia, a tavolino, una esperienza e delle capacità che comunque non si sarebbero acquisite nemmeno con maggior supporto? Non è che è ora di rimboccarsi le maniche e dimostrare che si è in grado di formare realmente dei tecnici, e chiedere a fatto compiuto maggiore supporto? Mi sembra si stia discutendo attorno ad un paradosso: dammi il supporto ($) e ti darò i tecnici. Prima però dimostrami che sei in grado di tirarne fuori almeno uno ben formato, e poi sarò ben lieto di darti il supporto ($) per tirarne fuori 110000.

Ma forse sono sempre io che sono troppo polemico e malizioso...
E a proposito di polemica: complimenti a tutti quegli acculturati che hanno imbrattato la città con uova. Ma forse loro fanno parte dei 110000 che non hanno avuto formazione, e con essa educazione.

giovedì 18 novembre 2010

Università e professionisti...alcune considerazioni

Disclaimer: come tutti i messaggi qui pubblicati, anche questo rappresenta solamente i miei pensieri e le mie riflessioni, a volte dure, spesso criticabili,
ma basate sulla mia esperienza diretta.

Durante una pausa fra le lezioni di informatica, ho sfogliato il giornale (Corriere della Sera - 13/11/2010) e la mia attenzione è stata attirata da un articolo di Isidoro Trovato che parla di come la Autorità di Vigilanza sui lavori pubblici possa far entrare l'Università nelle gare di appalto a fianco dei professionisti. In poche parole, questo significa che i docenti, i ricercatori e tutto il personale strutturato delle università potrebbe partecipare a gare di appalto pubbliche andando a minare pericolosamente, almeno così sostiene Gianni Rolando (presidente del Consiglio Nazionale degli Ingegneri), le posizioni oggi appannaggio esclusivo dei professionisti. Essendo io ingegnere, ed avendo lavorato per anni all'università, dovrei quindi trovarmi in accordo con Rolando, e invece ritengo che lo sbarramento di questa proposta sia semplicemente ridicolo.

Anzitutto ritengo che le università, in generale, siano troppo slegate dal mondo lavorativo senza quindi avere idea dei problemi che tale mondo sta affrontando. Ci si trova quindi nella condizione nella quale le università lavorano a progetti estremamente innovativi il piu' delle volte spinti non da problemi del mondo lavorativo ma da interessi puramente di ricerca. E per fortuna: sono un forte sostenitore dell'iniziativa individuale. Tuttavia ci si trova anche nella condizione ove, per dimostrare che il proprio lavoro scientifico è valido, si debbano trovare i problemi che la propria ricerca risolve. Ma questo è un modo sbagliato di ragionare: è meglio partire dal problema e trovare la soluzione, piuttosto che avere l'intuizione e cercare  il problema che risolve (o il contesto ove collocarla). Così facendo infatti si rischia solo di produrre soluzioni per un mercato non ancora pronto, e infatti molto spesso i risultati della ricerca scientifica vengono applicati diversi anni dopo al mondo lavorativo. E non si tratta di tempi canonici per la stabilizzazione della soluzione, ma semplicemente di tempi nei quali il mercato non è recettivo poiché occupato a risolvere altri problemi che le università reputano banali e quindi non prendono in considerazione.
Ulteriore ostacolo al dialogo fra il mondo del lavoro e delle università sono, molto spesso, i professori stessi: ogni professore ha un suo ambito di ricerca/interesse e tenta di forzare tale ambito ai suoi studenti, stabilendo spesso anche confini ben marcati che separino la propria ricerca da quella dei colleghi. Ci si ritrova quindi con studenti che svolgono attività di ricerca in un ambito (es. database) senza mettere il becco in altri ambiti (es. sistemi operativi) per volontà dei loro professori. I professori dovrebbero invece mettere a disposizione la loro esperienza affinché gli studenti, preso in carico un problema concreto del mondo del lavoro, possano affrontarlo e risolverlo agevolmente. E in questo modo si avrebbero diversi vantaggi:
  • le aziende acquisterebbero molta fiducia nelle università;
  • gli studenti acquisterebbero fiducia nelle proprie capacità (meglio 10 successi piccoli ma certi che un grande successo non applicabile al mercato);
  • gli studenti troverebbero da lavorare piu' facilmente, avendo maturato una esperienza diretta nel mondo del lavoro;
  • i professori resterebbero automaticamente aggiornati sulle problematiche del mercato.
Attualmente gli atenei informatici, come quello che io ho frequentato, hanno una grossa possibilità per dimostrare le proprie competenze e capacità: l'OpenSource. L'OpenSource è un qualcosa che le università temono molto per due motivi principalmente:
  • rilasciare un progetto come OpenSource significa dare al mondo (e quindi ad altre università) i propri sforzi di ricerca;
  • un progetto OpenSource potrebbe vedere la partecipazione di altri professionisti o università che mostrino una superiorità schiacciante in tale ambito.
Spaventati quindi dal vedersi rubare i propri sforzi o dal fare figuracce planetarie, le università preferiscono rimanere tranquillamente nascoste dietro qualche deliverable di qualche progetto strano che non permette la visione del codice e dei prototipi prodotti. Ovviamente non tutti gli atenei sono così, e sempre di piu' si evidenziano facoltà che abbracciano lo spirito OpenSource e riescono ad affermarsi nel panorama accademico e professionale. Tuttavia in Italia la paura è ancora alta, almeno questa è l'impressione che ho avuto girando per i vari atenei. Va comunque notato che, figuraccia o meno, il confronto è sempre un possibile spunto di crescita, e che esistono licenze e strumenti per tutelare il proprio lavoro. 

Torniamo ora all'argomento di discussione specifico: il possibile contrasto fra i professionisti e gli accademici. Di cosa dovrebbero avere paura i professionisti? Dopotutto, la loro professionalità non dovrebbe essere messa in discussione da un qualche professore o studente che si presenta sul mercato: quello che conta, che si tratti di professore, studente, o libero professionista, è l'esperienza e l'abilità, due qualità che non possono essere conquistate stando  solo dietro ad una cattedra o solo nel mondo del lavoro. Io, da ingegnere, non temo il confronto onesto con un altro ingegnere, e poco mi importa sia un docente, uno studente o un professionista: per quello che riguarda il confronto è solo un mio "sfidante". Quali scenari dunque si prospettano e perché spaventano tanto i professionisti? Io riesco ad individuare queste possiblità:
  • l'università inonda il mercato con personale a basso costo e alta qualità: il prezzo dei professionisti è costretto ad abbassarsi di conseguenza per poter reggere la concorrenza, e questo è un bene per chi richiede il servizio;
  • l'università inonda il mercato con personale a basso costo e bassa qualità: è evidente che tale personale non sarà in grado di fornire un servizio alla pari di quello di un professionista esperto, e quindi tale categoria non ha nulla da temere da questo confronto. Va inoltre notato che un professionista non può tutelarsi da questa problematica che non è infatti legata al mondo accademico.
  • l'università inonda il mercato con personale ad alto costo e di alta qualità: in questo caso i professionisti occupano la seconda posizione nelle scelte mission critical, ma il loro costo inferiore li rende una scelta papabile per tutti gli altri casi.
  • l'università inonda il mercato con personale a basso costo, bassa qualità da affiancare a personale professionale: in questo caso si assiste alla formazione di un nuovo professionista a "discapito" di un altro professionista. Ma occorre ricordare che quest'ultimo sarà stato a sua volta formato (si spera) a "discapito" di un docente universitario...
Francamente penso che una persona competente e preparata non debba temere il confronto con un'altra persona competente e preparata, poiché in un confronto onesto è giusto che "vinca" la persona migliore. Quindi impedire il confronto a priori è una scelta sbagliata e, soprattutto, che da una impressione sbagliata sulla categoria dei professionisti, che appaiono ora ai miei occhi come un branco di baroni che vogliono proteggere il proprio feudo. E non ho usato il termine "baroni" a caso: ritengo che dall'altro lato esista un altro gruppo di baroni impegnati a proteggere la propria scrivania. Ebbene se l'apertura al mondo del lavoro destabilizzera il loro regno, a maggior ragione ben venga l'iniziativa di cui si sta discutendo. DI baroni devono governare un impero proporzionale alle proprie capacità.

Anni fa una protesta analoga venne fatta dal lato accademico, spaventato dal possibile ingresso di industrie e professionisti nel loro "regno". E anche in quella occasione io evidenziai i miei dubbi su tanta rigidità: dopotutto aprire l'università all'industria significa, come già detto sopra, aprire la strada a nuovi posti di lavoro. Rolando, che a difesa della sua tesi sottolinea il periodo di crisi del mercato, dovrebbe tenere in considerazione anche questo fattore: dare spazio di lavoro ai giovani significa aumentare l'occupazione, non aumentare la disoccupazione dei professionisti. E quindi mi viene solo da ribadire come ognuno dovrebbe smettere di guardare al prioprio orticello, ma assumere una visione piu' ampia della questione.

Come riflessione conclusiva mi viene in mente che, se entrambe le parti, in tempi e con motivazioni diverse, non vogliono mischiarsi, forse il vero problema non è tanto sulle competenze, sulle capacità, sulla professionalità, ma sulla mancanza di un confronto onesto che tuteli entrambi i lati affinché solo chi è meritevole possa avere successo.

Ma forse sono io che non ho ben capito il reale problema....

    giovedì 19 agosto 2010

    Be serious: don't use CRAPL! Use Open Source licenses!

    Surfing the Web I found another programming license: the CRAPL (Community Research and Academic Programming License). I don't know if the author is serious about this license, it seems he is,  or if he is joking, however I consider the license valid in the following discussion since it raises up a concrete problem about the coding done under research.
    The idea of this license is good: forcing academy to release its code as Open Source. The way is tremendously bad: there is no need, in my opinion, for another Open Source like license. 
    The aim of CRAPL seems to be the removal of embarrassment of the academic world for the publication of not-quality code due to deadline releases. The idea is to release the code even if it is just a proof of concept without being annoyed with code reviews, design patterns, and stuff like that.
    This is crap! It is really controversial!

    First of all consider the amount of theory (and practice) in the design and development of software and all the techniques that academy tries to force into industry, for instance eXtreme Programming (XP). A natural question could be: why are you teaching me this stuff if you are the first that do not use it? Academy cannot teach about quality when it is producing low quality software!

    Moreover there is no need to use another license at all! If you want to release the code, use an existing license, in particular BSD if your code is really advanced or a GPL like if you are afraid someone can stole it and do a commercial product based on it.
    Moreover consider the clause 2:
    You are permitted to use and/or modify the Program for the
       validation of novel scientific claims if You make a good-faith
       attempt to notify the Author of Your work and Your claims prior to 
    submission for publication.
    What does good-faith mean? Moreover, I cannot see any clause that the authors must be reported on modification, as almost every Open Source license states. This is a really important part, since it happened to me that some of my code was not released as Open Source and has been kept by the University I worked, that was so able to do what it wanted with it (even destroy it!).

    I really think academy should stop being embarrassed by low-quality code, and should start to produce a good quality Open Source culture. After all, I'm not surprise to see TODOs and FIXMEs in the code, I'm much more surprised to see projects without code.
    Finally, I don't find embarrassing to produce a proof of concept and release it as Open Source when the code is enough mature (or beauty, or quality, or your-favorite-adjective-here). But it is important that there is a deal to release (soon or later) the code as Open Source! And it is for this that I cannot understand how the research community can still do a peer review over code that is not (or will not) available in any way! In my opinion, every work that produces or derives code, should introduce the license and the terms of the code itself.

    Don't think about embarrassment, code and release at your best. 
    Someone else will be proud to fix your ugly-code!

    lunedì 12 luglio 2010

    Componenti o Plug-ins?

    Qual'è la differenza fra un componente e un plug-in? Molti degli studenti che si laureano non hanno questa nozione, eppure oggi si parla sempre piu' spesso di componenti e plug-ins, possibile che non venga insegnata correttamente? Eppure è piuttosto semplice!

    Componente: un componente è una black box fatta per essere riutilizzata in diversi contesti. Il componente non ha conoscenza del contesto in cui viene applicato. Un esempio di componente potrebbe essere un logger su file: il componente sa cosa deve fare (loggare), non sa però dove viene usato (ad esempio in un programma server, in un client, in una applicazione didattica,...) e può essere esteso (ad esempio per ottenere un logger su database).

    Plug-in: un plug-in è una black box che estende un componente o un altro plug-in, può essere usato in diversi contesti ma deve conoscere i contesti ove verrà usato. Un esempio di plug-in è un menù crafico che permette di accedere a determinate funzioni.

    La principale differenza è proprio nella conoscenza del contesto di utilizzo: il plug-in estende in una direzione specifica e quindi deve sapere Icosa e come estendere un altro sistema.

    martedì 30 giugno 2009

    Setter, Getter o entrambi?

    I Java Beans hanno introdotto diverse convenzioni, fra le quali quelle circa l'utilizzo dei metodi getter e setter: i primi sono metodi che ritornano il valore di un attributo d'istanza, i secondi sono mutator che impostano il valore di tale attributo. La convenzione vuole che il getter abbia un nome che inizia con get, seguito dal nome della proprietà (variabile di istanza) con la prima lettera maiuscola e non abbia alcun parametro, ma ritorni un tipo pari a quello della proprietà. Il setter segue regole simili, e ha il suo nome composto da set e il nome della proprietà (prima lettera maiuscola) e riceva esattamente un argomento del tipo della proprietà senza ritornare al chiamante nulla.
    Da quanto sopra si ha che per ogni proprietà servono almeno due metodi distinti, un getter e un setter, abbastanza semplici e rapidi da scrivere (addirittura gli IDE moderni consentono di creare tali metodi con un click). E' però possibile prendere in prestito da Perl il comportamento dei metodi e scrivere un metodo unico che svolga entrambe le funzioni.
    Si consideri la seguente semplice classe:

    public class Person {

    private String name = null;
    private String surname = null;
    ...
    }



    e si supponga di voler scrivere un unico metodo name che possa funzionare sia da getter che da setter a seconda del contesto in cui viene chiamato. In altre parole il seguente main deve funzionare:

    public static void main(String[] args) {
    Person p = new Person();
    p.name( "Luca" );
    System.out.println("Persona " + p.name() );

    }

    Come si può notare il metodo name viene chiamato in due contesti diversi: se gli viene passato un parametro si deve comportare come setter, altrimenti come getter.
    Come si puo' ottenere un simile comportamento? Usando gli argomenti opzionali introdotti da Java 5 è abbastanza semplice:

     public String name(String...newName){
    // controllo se e' stato passato
    // un parametro o meno
    if( newName != null && newName.length == 1 )
    // passato un parametro => metodo setter
    this.name = newName[0];

    // in ogni caso ritorno il valore
    // corrente come metodo getter
    return this.name;
    }

    Come si può notare il metodo si comporta come getter sempre, ovvero restituisce sempre il valore della proprietà name. Il metodo poi indovina il contesto di chiamata analizzando gli eventuali parametri: se ne sono stati passati al massimo uno allora il metodo si deve comportare come setter. E' possibile rilassare il test sul numero di parametri considerando valida una lista di parametri qualsivoglia lunga, e usando solo il primo come setter, ma questa scelta dipende dall'interfaccia che si vuole dare al metodo.
    Il fatto che il metodo restituisca sempre, anche se chiamato in un contesto di setter, il valore della proprietà non è una limitazione, anzi consente di effettuare un method-chain invocando piu' metodi in cascata.

    lunedì 22 giugno 2009

    Programmazione a oggetti in Perl

    Perl è un linguaggio molto elegante e potente, che viene spesso insegnato per evidenziare concetti un po' più evoluti riguardo lo scripting.
    Pur supportando la programmazione ad oggetti, Perl non fornisce alcun costrutto particolare per la realizzazione di classi e tipi di dato astratto. Si può paragonare Perl a un C che viene programmato ad-hoc per implementare un comportamento ad oggetti.
    Imparare a programmare Perl a oggetti è molto interessante, soprattutto perché permette di vedere effettivamente come molti compilatori a oggetti si comportano. Inoltre gran parte della libreria Perl/CPAN è orientata agli oggetti, e quindi è indispensabile avere nozioni di OOP. Non è comunque facile trovare una guida sulla programmazione OOP in Perl, perciò ho deciso di scrivere questo articolo introduttivo. Da notare che farò riferimento a versioni di Perl inferiori alla 6, dove la scrittura di classi e oggetti cambierà grazie alla presenza di apposite parole chiave.

    Il seguente elenco mostra i punti per me fondamentali da tenere a mente quando si vuole implementare una classe e di conseguenza usare degli oggetti.

    Gli oggetti possono essere acceduti solo per riferimento.

    Ogni istanza di oggetto viene mantenuta in un riferimento, in maniera simile a come avviene in Java.

    Un riferimento ad un oggetto è un normale riferimento scalare
    .
    Come i riferimenti alle strutture dati native (hash, array) sono contenuti in variabili scalari, così pure i riferimenti agli oggetti sono mantenuti in variabili scalari.

    Una classe corrisponde ad uno spazio dei nomi, e quindi si implementa tramite un package.

    In Perl una classe è una entità sul quale sono richiamati dei metodi. Per la precisione, un metodo di classe è un metodo al quale viene passato un parametro che indica lo spazio dei nomi nel quale si agisce. Ecco quindi che assegnare un metodo ad una classe corrisponde ad inserire un metodo in un determinato package: il metodo potrà essere invocato solo nell'ambito di quello spazio dei nomi (classe/package).

    Se la struttura dati dell'oggetto è complessa, allora essa deve essere realizzata tramite un array o un hash, e il riferimento all'oggetto diventa il riferimento all'array/hash.
    Questo punto va chiarito bene: in Perl esistono solo tre tipi di variabili (scalari, array, hash) e una classe sarà presumibilmente composta da diverse variabili di tale tipo. Dovendo però usare un riferimento ordinario (si vedano i punti precedenti) per l'oggetto, si ha che tale riferimento deve essere il punto di ingresso di una struttura più complessa. Di conseguenza, il riferimento all'oggetto deve essere un riferimento ad un array/hash che contenga tutte le altre variabili di istanza. Per meglio comprendere, se in Java una definizione di classe Person potrebbe essere così strutturata:
    public class Person{
    private String name = null;
    private String surname = null;
    }

    In Perl non potrebbe avere la definizione duale, ossia:

    package Person;

    $name = undef();
    $surname = undef();
    poiché, così facendo, si avrebbe che lo spazio dei nomi della persona (Person) contiene due variabili scalari, ed è impossibile ritornare un singolo riferimento che fornisca accesso ad entrambe le variabili. E' quindi necessario incapsulare le variabili di classe all'interno di un unico contenitore e fornire accesso attraverso tale contenitore:

    package Person;
    ...
    $this = { name => undef(),
    surname => undef(),
    };


    In questo modo la variabile $this consente accesso ai valori di name e surname, ed è possibile ritornare all'esterno un singolo riferimento a $this.
    Da notare che la seguente traduzione non funziona come ci si aspetta:

    package Person;

    $name = undef();
    $surname = undef();

    $this = { name => \$name,
    surname => \$surname,
    };

    Infatti così facendo si ha l'esistenza di uniche variabili $name e $surname e di conseguenza i riferimenti di ogni oggetto creato puntano alle stesse variabili globali (all'interno del package) e quindi agli stessi valori. La soluzione di cui sopra è invece appropriata per variabili statiche (ossia condivise all'interno di ogni classe).

    Un metodo di classe o di oggetto riceve sempre in automatico un primo argomento che specifica la classe o l'istanza
    .
    Questa cosa non dovrebbe stupire particolarmente, poiché è già quello che avviene nei normali compilatori ad oggetti: il primo parametro di un metodo di istanza è il puntatore/riferimento all'istanza stessa. E' in questo modo che i compilatori predispongono la variabile this. In altre parole, il metodo Java seguente:
    public class MyClass{
    public void instanceMethod(String arg1, int arg2){
    this.stringVariable = arg1;
    this.integerVariable = arg2;
    }
    }

    viene mutato dal compilatore silenziosamente nel seguente:

    public class MyClass{
    public void instanceMethod(MyClass this, String arg1, int arg2){
    this.stringVariable = arg1;
    this.integerVariable = arg2;
    }
    }

    Da notare che il primo parametro, di nome simbolico this, è un riferimento all'oggetto stesso. In altre parole i metodi di istanza ottengon come parametro la zona di memoria (o meglio il riferimento a tale zona) dove risiede l'oggetto sul quale si agisce. Perl segue lo stesso percorso: il primo argomento di un metodo di istanza contiene il riferimento all'oggetto stesso, di modo che il metodo possa essere scritto come:

    sub instanceMethod{
    my ($this, $arg1, $arg2) = @_;
    ...
    }
    La differenza è che qui è compito del programmatore ricordarsi che il primo argomento è il riferimento all'istanza; il compilatore Perl infatti fa solo la prima parte del lavoro (passare al metodo il riferimento come primo argomento).
    Quanto sopra per quello che riguarda gli oggetti, ma per le classi?
    In un linguaggio OOP come Java/C++ i metodi di classe (es. static) non necessitano di nessun argomento particolare o di modifiche da parte del compilatore. Infatti quello che avviene è che viene tenuta in memoria la tabella di dispatching dei metodi e l'invocazione di un metodo corrisponde al salto all'indirizzo fornito da questa tabella. Ma il metodo non ha bisogno di sapere se appartiene ad una classe oppure no, come non ha bisogno di sapere a che classe appartiene poiché per forza di cose, se non è di istanza, deve essere di classe.
    In Perl questo non è vero: essendo una classe implementata tramite un package, i metodi all'interno del package potrebbero essere di istanza, oppure di classe, oppure nessuno dei due (normali metodi globali). Perl allora fornisce un modo per informare un metodo che è stato invocato in un contesto di classe (ossia come se fosse un metodo di classe): questo metodo riceverà infatti come primo argomento il nome (stringa) della classe/package al quale appartiene.
    Riassumendo quindi, tutti i metodi di classe o di oggetto in Perl ricevono come primo argomento una variabile che indica il nome della classe (metodo di classe) o il riferimento all'oggetto stesso (metodo di oggetto) e non ricevono nulla se sono chiamati in un normale contesto di package.

    In Perl non esiste il concetto di costruttore (e di distruttore)
    .
    Siccome Perl non fornisce nessuna parole chiave per definire una classe, i metodi costruttori (e distruttori) non esistono. Questo non significa che non si possano creare dei metodi appositi per l'inizializzazione delle variabili di un oggetto. Tali metodi dovranno ovviamente restituire al chiamante il riferimento alla struttura dati dell'oggetto.

    Un metodo usato come costruttore non deve avere lo stesso nome della classe
    .
    Siccome questi metodi non sono dei veri e propri costruttori, non devono seguire le regole standard dei costruttori Java e C++: essi possono (o meglio devono) avere un tipo di ritorno (solitamente il riferimento alla struttura dati dell'oggetto) e possono avere un nome non vincolante (solitamente new).

    In Perl non esiste l'operatore new
    .
    Quando si incontra qualcosa che assomiglia all'operatore new per l'allocazione di un oggetto, si sta in effetti osservando la chiamata di un metodo di nome new (si veda il punto precedente).
    Il compilatore passa automaticamente ad un metodo il primo argomento (nome della classe o riferimento ai dati) quando si usa l'operatore freccia.
    Quando la chiamata ad un metodo avviene attraverso l'operatore freccia, il compilatore passa come primo argomento del metodo l'oggetto lvalue su cui viene applicato l'operatore freccia. In altre parole:
    LVALUE->method(arg1, arg2, arg3);

    corrisponde a:
    method(LVALUE, arg1, arg2, arg3);
    Questo significa quindi che usando l'operatore freccia su i metodi di un package si ha automaticamente una chiamata a metodo di classe, mentre usando l'operatore freccia su dei riferimenti ad oggetti si ha una chiamata ad un metodo di istanza. Quindi ad esempio, per creare un nuovo oggetto, si può invocare il metodo new nei due modi equivalenti:
    $objectReference = Person->new('Luca', 'Ferrari'); # sintassi di classe
    $objectReference = new( Person, 'Luca', 'Ferrari'); # sintassi di package


    e analogamente, una invocazione di metodo di oggetto può essere scritta come:

    $objectReference->setName('Giovanni'); # sintassi di oggetto
    Person::setName( $objectReference, 'Giovanni'); # sintassi di package

    Perl deve sapere quali riferimenti puntano ad un oggetto e quali no.
    Il costruttore di un oggetto non deve solo inizializzare l'oggetto e il suo stato, ma deve anche informare Perl che il riferimento non è un normale riferimento ma un collegamento ad un oggetto. Questo avviene tramite l'operatore bless, che accetta il riferimento ad una struttura dati e la classe/package a cui la struttura dati appartiene. L'operatore memorizza in una tabella il collegamento fra il riferimento e il nome del package/classe a cui è associato, in modo da poter individuare a quale classe il riferimento appartiene. In particolare, in seguito al blessing, l'operatore ref applicato ad un riferimento di oggetto restituisce il nome della classe per la quale è stato fatto il blessing.
    Sulla base di questa considerazione, il template generale per un costruttore di oggetto è il seguente:

    sub new
    {
    my ($class, @args) = @_;
    # inizializza i valori dell'oggetto
    $this = { arg1 => $args[0],
    arg2 => $args[1],
    ...
    };

    bless( $this, $class );
    return $this;
    }





    Sulla base di tutti i punti di cui sopra, è possibile paragonare la creazione di una classe/oggetto fra un linguaggio OOP (es. Java) e Perl. Supponiamo di avere la seguente classe Java:

    public class Person{
    public static int personCounter = 0;

    private String nome = null;
    private String cognome = null;

    public Person(String nome, String cognome){
    this.nome = nome;
    this.cognome = cognome;
    Person.personCounter++;
    }


    public String getNome(){
    return this.nome;
    }

    public String getCognome(){
    return this.cognome;
    }
    }

    e di volerla tradurre in Perl. La sua definizione diviene la seguente:

    #!/usr/bin/perl

    package Person;

    # variabile statica (la stessa
    # condivisa fra tutte le istanze)
    $personCounter = 0;


    sub new
    {
    my ($class, $name, $surname) = @_;

    # creazione nuovo riferimento ad hash
    # con i dati (stato) dell'oggetto
    $this = { name => $name,
    surname => $surname,
    };



    # associo il riferimento alla classe
    bless( $this, $class );

    # incremento il contatore di istanze create
    $personCounter++;

    print "\nCreazione di un nuovo oggetto di tipo $class (numero $personCounter)\n";

    # restituisco il riferimento appena creato
    return $this;
    }




    sub getNome
    {
    my ($this) = @_;

    # restituisco il dato richiesto
    return $this->{name};
    }


    sub getCognome
    {
    my ($this) = @_;

    # restituisco il dato richiesto
    return $this->{surname};
    }




    che può essere testato con il seguente main:

    package main;

    $person1 = Person->new('Luca','Ferrari');
    $person2 = Person->new('Paperon','De Paperoni');

    print "\nPersona con nome ", $person1->getNome();
    print "\nAltra persona con nome ", $person2->getNome(), " ", $person2->getCognome();
    print "\n\n";


    che produce il seguente output:

    Creazione di un nuovo oggetto di tipo Person (numero 1)

    Creazione di un nuovo oggetto di tipo Person (numero 2)

    Persona con nome Luca
    Altra persona con nome Paperon De Paperoni


    Ereditarietà e Polimorfismo
    L'ereditarietà in Perl viene implementata in modo molto semplice: è disponibile un array globale all'interno dello spazio dei nomi di un package, denominato ISA, che contiene le classi/package dalle quali si vuole ereditare. L'idea quindi è semplice: ogni package definisce una lista di ulteriori package in cui cercare dati e/o metodi. Quando Perl non trova un attributo nel package specificato inizia ad esplorare (sequenzialmente) l'array ISA al fine di trovare in ogni classe specificata il simbolo, e quindi lo utilizza.
    Per meglio comprendere questo concetto, si consideri di estendere la classe Person con una classe Male che implementa una persona di sesso maschile:


    package Male;

    @ISA=(Person);

    sub new
    {
    my ($class, $name, $surname) = @_;

    # creazione nuovo riferimento ad hash
    # con i dati (stato) dell'oggetto
    $this = { name => $name,
    surname => $surname,
    };



    # associo il riferimento alla classe
    bless( $this, $class );

    # incremento il contatore di istanze create
    $personCounter++;

    print "\nCreazione di un nuovo oggetto di tipo $class (numero $personCounter)\n";

    # restituisco il riferimento appena creato
    return $this;
    }


    Come si può notare la definizione del costruttore è praticamente la stessa della classe Person, addirittura si referenzia un simbolo ($personCounter) che qui non è stato ancora definito. Ora se un programma crea un nuovo oggetto di tipo Male:

    $maschio = Male->new( $person1->getNome(), $person1->getCognome() );
    print "\nPersona maschio con nome ", $maschio->getNome(), " ", $maschio->getCognome();


    l'output di esecuzione è del tutto simile a quello del programma precedente, e addirittura la variabile $personCounter inizia il suo conteggio come fosse separata dalla classe Person (ovvero come fosse stata definita singolarmente di classe). Tutta la magia viene fatta nella ricerca dei simboli, che anziché passare per una vtable passa per l'array ISA del package corrente (ogni package può ridefinire il proprio @ISA).

    La ridefinizione dei metodi è automatica, quindi se si ridefinisce il seguente metodo nella classe Male si ha che la chiamata a getNome() verrà risolta da tale metodo:

    package Male;

    @ISA=(Person);

    sub new
    {
    my ($class, $name, $surname) = @_;

    # creazione nuovo riferimento ad hash
    # con i dati (stato) dell'oggetto
    $this = { name => $name,
    surname => $surname,
    };



    # associo il riferimento alla classe
    bless( $this, $class );

    # incremento il contatore di istanze create
    $personCounter++;

    print "\nCreazione di un nuovo oggetto di tipo $class (numero $personCounter)\n";

    # restituisco il riferimento appena creato
    return $this;
    }



    sub getNome
    {
    my ($this) = @_;

    return $this->{name} ." (maschio) ";
    }


    E' inoltre possibile riferirsi alle proprietà della classe base mediante l'uso di SUPER. Si presti attenzione poiché qui super è un operatore che si preoccupa di salire di un livello nella scala dei riferimenti, ma il nome della classe deve essere sempre specificato come primo argomento: SUPER deve quindi essere usato in combinazione con l'operatore freccia.

    package Male;

    @ISA=(Person);

    sub new
    {
    my ($class, $name, $surname) = @_;

    $this->SUPER::new( $name, $surname );


    # associo il riferimento alla classe
    bless( $this, $class );

    # incremento il contatore di istanze create
    $personCounter++;

    print "\nCreazione di un nuovo oggetto di tipo $class (numero $personCounter)\n";

    # restituisco il riferimento appena creato
    return $this;
    }



    sub getNome
    {
    my ($this) = @_;

    return $this->SUPER::getNome() ." (maschio) ";
    }


    Si noti che quando si usa SUPER la parte a destra viene sempre invocata con la sintassi di package (::) mentre quella di sinistra con la sintassi ad oggetto (->).


    Per concludere
    Riassumendo quindi si ha che in Perl la programmazione ad oggetti viene attualmente implementata tenendo separati i metodi e i dati, in modo piuttosto esplicito. Il riferimento ai dati rappresenta il riferimento all'oggetto (e quindi al suo stato), mentre l'invocazione dei metodi avviene grazie all'operatore freccia, che impone al compilatore di passare l'entità di sinistra (il riferimento o il nome della classe) come primo argomento. Grazie poi ad una tabella dei simboli gestita tramite l'operatore bless si ha l'associazione fra riferimento ai dati e classe, e questo consente, in combinazione all'array @ISA di sfruttare anche l'ereditarietà e il polimorfismo.