In questo weblog ci sono molti attivisti del mondo di FireFox. Mi chiedevo se non ce ne fosse nemmeno uno che voglia cimentarsi nella realizzazione di una estensione per Firefox, Mozilla, Thunderbird che permetta di postare su IMHO. Qui è possibile trovare una buona spiegazione su come procedere per realizzarla: How to write Firefox extensions .

Solo un requisito: Deve aggiungere le stesse feature che sono già presenti in Internet Explorer. Post Link to IMHO e Quote in IMHO, con il medesimo comportamento, nei limiti del possibile. Se qualcuno si offre otterrà tutto il mio supporto, per sapere come integrarsi facilmente e vedrà il suo plugin aggiunto all'installazione di IMHO.

Simone, se ci sei batti un colpo...

powered by IMHO 1.1

tags: - categories:

Sono un po' di giorni che penso a questo post, ma fino ad ora non ero riuscito a trovare i 30 minuti consecutivi necessari per poterlo redarre. L'intento è quello di presentare un caso reale in cui il Refactoring mi è stato di aiuto nella realizzazione di una delle ultime features di IMHO, per l'appunto il sistema di upload dei file verso l'ftp.

Quando ho iniziato il lavoro, le uniche cose che realmente avevo chiare in testa erano i seguenti presupposti:

  1. L'unico modo veramente valido per implementare la feature era di usare il protocollo FTP. Svariate ricerche in rete mi avevano confermato che l'eterogeneità dei motori di blogging lasciava poco spazio a soluzioni più sfiziose.
  2. In secondo luogo era necessario comunque lasciare aperta la possibilità, in futuro di creare soluzioni ad-hoc per ogni motore di blogging.

Armato di pazienza e di queste labili certezze, il primo passo è stato quello di cercare una libreria per l'FTP. Di certo una cosa da escludere subito era la realizzazione ex-novo di tale libreria, non perchè impossibile, ma perchè la sua implementazione avrebbe fatto lievitare inutilmente i tempi di realizzazione. La libreria trovata come sapete è la' edtFTPnet, che alcuni test comparativi mi hanno confermato essere la più affidabile.

A questo punto avrei potuto mettermi davanti ad un foglio di carta e disegnare la soluzione del problema così come sarebbe dovuta nascere, tuttavia dato il tempo scarso, e la mia ormai grande fiducia nel refactoring, ho invece aperto Visual Studio e cercato il punto migliore per innestare il nuovo codice. Alla fine la scelta è caduta sull'aggiunta di un bel metodo virtuale alla classe base degli adapter con i parametri che sembravano più adeguati e nel farne l'override in un solo engine, cosciente del fatto che il codice che avrei scritto al limite andava copiato in tutti gli altri engine.

Questa era una soluzione evidentemente temporanea, non sia mai che io cada nella trappola mortale del cut&paste, ma che mi permetteva innanzitutto di approfondire la problematica facendo funzionare il sistema velocemente. Inoltre, evidenziava una bella questione, ovvero come fare in modo, dovendo fornire a tutti gli engine il medesimo protocollo, di astrarre l'implementazione del protocollo dall'engine stesso.

Ma tutto ciò era materia per i posteri. Innanzitutto occorreva scrivere il metodo che trasferiva i file. E già questa questione apriva altri problemi. Al termine del lavoro, quando l'engine di .TEXT già pubblicava i post mi sono reso conto che lo faceva in modo logicamente errato. Infatti l'engine apriva e chiudeva la connessione ad ogni file inviato. Con un protocollo come l'FTP questo era un problema dannatamente grave, perchè l'handshake iniziale causava un overhead eccessivo. Ovviamente pensandoci bene avrei anche potuto trovarmi in futuro con protocolli diversi (si pensi ad esempio ad un webservice) che non richiedessero una apertura e chiusura della connessione. A questo punto i metodi da uno sono divenuti tre. Due responsabile di aprire e chiudere la connessione, e il terzo che trasferiva i file uno per uno. Un protocollo non connesso, semplicemente poteva lasciare vuoti i metodi Open() e Close().

Risolto questo problema era giunto il momento di estendere il funzionamento agli altri engine. Escluso a priori il cut&paste, in buona ottica oop non rimaneva che separare le responsabilità e creare una classe che si occupasse del trasferimento. E così è stato ed è nata la classe FtpPublisher. A questo punto tutti gli engine trasferivano immagini per mezzo dell'FTP. Il problema a prima vista era risolto. Ma ancora il requisito di cui al punto 2 non era del tutto soddisfatto. E' vero che è sempre possibile riscrivere un metodo, ma è anche vero che è di gran lunga meglio se non lo si fa. Inoltre, era evidente una duplicazione delle funzionalità. GLi engine così come il publisher ftp aveevano entrambi i metodi Open(), Close() e SendFile().

Quindi l'idea è stata quella di estrapolare completamente la logica di trasferimento dall'engine e semplicemente di consentire ad esso di fornire l'istanza di publisher da utilizzare per la pubblicazione. Perciò ho creato la classe astratta Publisher, e ho migrato i metodi Open(), Close() e SendFile() verso il publisher, in particolare l'ftp. A questo punto non rimaneva altro che fare in modo che l'engine creasse l'istanza di publisher e perciò ho creato una proprietà che lo restituisse a chi lo chiedeva. Tutto ciò adeguando poco a poco anche la logica che usava il publisher.

La soluzione era veramente buona. Ma ancora gli mancava qualcosa. Anche i questo caso, sostituire il publisher costringeva a ricompilare. E' stata la reflection alla fine che mi è corsa in aiuto. Modificare la proprietà degli engine per fare in modo che leggessero la classe publisher da file di configurazione è stato un gioco da ragazzi. E a questo punto ero veramente soddisfatto.

Ecco, a conclusione di questo post, vorrei rilevare come, partendo con poche certezze e armati della affilate spade dell'object-orientation e del refactoring si possa ottenere una soluzione ben congegnata, risparmiando di spremere le meningi su problemi che per ovvie ragioni all'inizio sfuggono. Ovviamente questo è il mio modo di procedere, suppongo che altri avrebbero ottenuto soluzioni differenti, ma ritengo che il succo del discorso sia davvero importante: non conta che riusciate a smontare il problema pezzo per pezzo da subito, è molto più probabile che, comportandovi come le onde del mare sulla roccia, riusciate più facilmente ad eroderlo mano a mano che esso presenta le sue parti più friabili.

powered by IMHO


Eccomi, immaginatemi vestito come Otelma, un po' più simpatico spero, che scruto nella mia sfera di cristallo e snocciolo le mie previsioni per l'anno venturo:

  • Visual Studio 2005 non uscirà prima di settembre. Poi non ditemi che porto sfiga, ma non ho mai visto rispettare un appuntamento
  • La gente che prima si lamentava che i SW Microsoft erano troppo permissivi in termini di sicurezza inizierà a lamentarsi perchè sono diventati troppo restrittivi (a dire la verità hanno già cominciato)
  • Quelli di Blackcomb faranno un bel po di ferie, tanto Longhorn continuerà a prendersela comoda
  • Firefox non salverà il mondo, ma non lo faranno nemmeno Java o Linux
  • Il refactoring salverà il mondo
  • Il referendum sulla fecondazione assistita verrà approvato dalla cassazione
  • Visto che il referendum è stato approvato ci saranno le elezioni anticipate e vincerà dinuovo Berlusconi... tanto finchè non esiste opposizione, non lo ferma nessuno.
  • Non sono un esperto di calcio, ma da quello che sento Andrea Saltarello si comprerà l'Inter. Ormai è alla sua portata.
  • IMHO verrà acquistato dalla Microsoft per integrarlo in MSN Messenger

Pant, pant.. che fatica.

powered by IMHO 1.1

tags: - categories:

Un intervista con il designer degli splendidi logo di Google.

Ecco un bel passaggio:

Hwang: Understandably, the "O" and the "L" are the easiest to deal with. The "O" has become a Halloween pumpkin, a Nobel Prize medal, the Korean flag symbol and the planet earth. The "L" has been used as a flagpole, the Olympic flame cauldron or a snow ski. The first "G" is the most difficult to deal with, and I don't think the "E" has gotten much action because of its location.

Dennis Hwang, Logo designer for Google

powered by IMHO

tags: - categories:

della mia vita e di altre amenità

Una questione di fondamentale importanza, quando si lavora con Javascript, è l'utilizzo delle più comuni librerie di terze parti. Se ne possono nominare innumerevoli - tra le più conosciute troviamo as esempio JQuery - e sicuramente ne rimarrebbero fuori altrettante. Gran parte del successo di Javascript in effetti dipende dalla disponibilità di questi insostituibili strumenti, più che dal linguaggio stesso. Nel passare a Typescript, non è possibile immaginare il successo di un linguaggio che non tenga conto di questa peculiarità, ed infatti, cardine nella progettazione del linguaggio è stato proprio il fatto che tali librerie potessero funzionare senza alcun tipo di modifica.

I definition file

Se si prova ad analizzare con calma quello che ci si presenta davanti agli occhi quando scriviamo in Typescript, diventa immediatamente chiaro che, aldilà di un linguaggio efficace, c'è anche dell'altro. Proviamo ad esempio, in un banale esercizio a scrivere quanto segue:

   1: var element: HTMLAnchorElement = 
   2:     <HTMLAnchorElement>document.getElementById('myLink');
   3: element.href = 'http://www.xamlplayground.org';

La specifica di HTMLAnchorElement, qui utilizzata sia come dichiarazione di una variabile che come cast, in effetti rivela che vi è un substrato di tipi definiti che ci supportano nella stesura del codice, consentendo al compilatore di verificare che alle chiamate di proprietà e metodi rispondano costrutti che esistono realmente. Ora, se siamo in Visual Studio 2012, possiamo semplicemente andare con il cursore al tipo HtmlAnchorElement e premere F12 (Go To Definition) per ottenere quanto segue:

   1: interface HTMLAnchorElement extends HTMLElement, MSHTMLAnchorElementExtensions, MSDataBindingExtensions {
   2:     rel: string;
   3:     protocol: string;
   4:     search: string;
   5:     coords: string;
   6:     hostname: string;
   7:     pathname: string;
   8:     target: string;
   9:     href: string;
  10:     name: string;
  11:     charset: string;
  12:     hreflang: string;
  13:     port: string;
  14:     host: string;
  15:     hash: string;
  16:     rev: string;
  17:     type: string;
  18:     shape: string;
  19:     toString(): string;
  20: }
  21: declare var HTMLAnchorElement: {
  22:     prototype: HTMLAnchorElement;
  23:     new(): HTMLAnchorElement;
  24: }

Il codice qui evidenziato, corrispondente alla dichiarazione del tipo suddetto, è estrapolato da un file denominato "lib.d.ts". Questo file è automaticamente incluso al momento della compilazione ed è anche riconosciuto dall'intellisense di Visual Studio. Come si vede si tratta di una semplice dichiarazione ma la sua utilità, assieme a le innumerevoli altre presenti nel file, è di grande utilità per supportare lo sviluppo all'interno di una pagina HTML, esponendo oggetti, metodi, proprietà ed eventi.

I file di definizione in effetti possono essere facilmente redatti e inclusi nella compilazione del proprio codice, per supportare qualunque libreria di terze parti oppure propria. Infatti è importante ricordare che qualunque spezzone di codice Javascript valido è anche un Typescript valido, pertanto con il supporto di un file di definizione saremo nettamente agevolati nell'utilizzo di tali librerie.

Una libreria a caso... JQuery

Chiunque abbia sviluppato recentemente in Javascript non può esimersi dal riconoscere le enormi potenzialità di JQuery, che consente facilmente di interagire con il DOM della pagina e ottenere con semplicità dei risultati anche molto efficaci e accattivanti. Ed è scontato che la prima tentazione sarà quella di usare questa libreria in congiunzione con Typescript. Vediamo quindi di soddisfare immediatamente questa legittima esigenza e di spiegare nel contempo come comportarsi in questo caso.

La prima attività da compiere è quella di includere nella pagina JQuery stesso, prima del punto in cui il codice Javascript output del nostro Typescript è incluso. Questa operazione è fatta come comune utilizzando il tag <script> impostandone l'attributo "src" e serve a consentire al browser di caricare la libreria. In termini di sviluppo essa ha esclusivamente l'obbiettivo di consentirci il normale funzionamento del software ma, dal punto di vista delle definizioni non ha alcun effetto pratico. Per consentire al compilatore Typescript di conoscere le definizioni occorre innanzitutto procurarsi il file di definizione "jquery.d.ts". Esso è reperibile all'interno del repository di Typescript, tra gli esempi.

http://typescript.codeplex.com/sourcecontrol/latest#typings/jquery.d.ts

Il file in questione è relativo la versione 1.7 della libreria quindi occorre caricare nella pagina la corrispondente versione per essere certi di non avere sorprese. Una volta che il file è incluso nella soluzione esso deve essere referenziato dal nostro file Typescript con una sintassi basata su un commento:

/// <reference path="../Libs/typings/jquery/jquery.d.ts" />

Grazie a queta referenza il compilatore inizierà ad accorgersi della presenza di tipi di JQuery e di conseguenza a fornire l'intellisense come atteso:

imageAttenzione che la presenza di un file di definizione non ha solo lo scopo di supportare lo sviluppo alimentando l'intellisense. La vera utilità sta nel fatto che solo se il compilatore conosce i tipi sarà in grado di validare il nostro codice. Scrivere del codice che usa JQuery senza un file si definizione è pari a tentare di scrivere una classe C# senza gli opportuni "using".

E' del tutto evidente che la medesima tecnica può essere utilizzata anche per creare delle proprie librerie da condividere tra differenti progetti. Ma in tale caso potremmo anche esimerci dal utilizzare un file di definizioni, per collegare direttamente la libreria al sorgente:

/// <reference path="../Libs/Utils.ts" />

E' chiaro che all'interno di questo file importato dovremo organizzare i tipi secondo dei namespace opportunamente organizzati per facilitarne l'utilizzo.

   1: /// <reference path="typings/jquery/jquery.d.ts" />
   2:  
   3: module Utils
   4: {
   5:     export class Page
   6:     {
   7:         run(): void
   8:         {
   9:             $(() => this.onLoad());
  10:         }
  11:  
  12:         onLoad(): void { }
  13:     }
  14: }

Nello snippet si vede l'utilizzo di "module" per creare un namespace. All'interno di esso ciascuna classe che è marcata con "export" (ma attenzione che vale anche per proprietà, metodi, tipi statici e anche semplici variabili) diverrà visibile all'esterno. Questo consente una ottima organizzazione, mediante un corretto incapsulamento di tipi privati che supportano tipi pubblici. Nello stesso esempio si può vedere anche l'uso di una referenza a jquery.d.ts.

Spesso e volentieri ci si trova nell'esigenza di includere sempre i medesimi file, e quindi a replicare potenzialmente all'infinito le referenze. In tale caso sarà consigliabile creare un file references.ts che contenga le referenze utilizzate da tutti i componenti. A questo punto sarà sufficiente collegare sempre tale file a tutti i sorgenti e avremmo il beneficio di aver accentrato la definizione in un unico punto.

E le altre librerie?

Una volta compreso il meccanismo che sta alla base dei definition file, l'ultima cosa che rimane da fare è procurarsi le definizioni per le librerie di cui si necessita. Dato che pensare di scriversi in proprio una definizione è piuttosto azzardato e richiede un tempo e una attenzione di cui raramente si dispone, bisogna indirizzarsi alla rete. In particolare, su github esiste una collezione di definizioni molto estesa e aggiornata che potete trovare a questo indirizzo: https://github.com/borisyankov/DefinitelyTyped. Ma, da utenti di Visual Studio la cosa migliore è di accedere a nuget e cercare "Definitelytyped" associato al nome della libreria di cui si cercano le definizioni. Grazie a nuget sarà possibile accedere direttamente alle definizioni ed agganciarle al progetto.


Aggiungi Commento