logo_xedotnetCi siamo, dopo lunghi preparativi è finalmente pubblico il prossimo One Day Mobile 2014, un evento di una intera giornata, con ben 7 talk a proposito dello sviluppo mobile in ambito Microsoft. Sarà una ghiotta occasione di condividere esperienze pratiche e novità, in un ambito in cui la velocità di sviluppo è la chiave del successo. Avremo quindi sessioni ad ampio spettro, sia su Windows Phone e Windows 8, ma anche su argomenti cross-platform come Xamarin e PhoneGap. 

L'evento si terrà il prossimo 15 Maggio 2014 presso il Novotel Castellana di Venezia Mestre e vedrà la seguente agenda:

Andrea Dottor: App connesse con ASP.NET Web API

Realizzare applicazioni connesse può fare la differenza in un mercato in pieno sviluppo.
Aggiornare i dati di un catalogo, caricare/leggere gli score di un gioco, interfacciarsi con applicazioni/database esistenti...tutti validi motivi per non perdervi questa sessione, dove vedremo come sviluppare servizi ASP.NET Web API che implementino l'OAuth2 authentication ed OData, e vedremo come poterli consumare da applicazioni Windows Phone, Windows Store App e Xamarin App.

Andrea Boschin: Condivisione del codice tra W8 e WP8

Lo sviluppo mobile richiede sempre più spesso di fornire applicazioni che siano disponibili su diversi device, siano essi Windows Phone o Windows 8, sfruttando le peculiarità di ciascuno. Questo pone il problema di scrivere codice che possa in qualche modo essere riutilizzato su piattaforme che pur essendo simili hanno diversità marcate. In questa sessione vedremo alcune tecniche che possono aiutare nel migliorare la condivisione del codice quando si sviluppano applicazioni per questi sistemi.

Mirco Vanini: C++ in Windows Phone Apps

In questa sessione vedremmo una panoramica degli strumenti messi a disposizione per lo sviluppo nativo su Windows Phone 8. Verrà posta particolare attenzione al suo utilizzo per lo sviluppo di applicazioni ibride (C#/C++) che hanno la necessità di riutilizzare algoritmi sviluppati su piattaforme desktop.

Davide Vernole: Xamarin do it better!

Xamarin offre un’alternativa al “Write Once, Run Anywhere Approach” permettendo agli sviluppatori di realizzare applicazioni per le principali piattaforme mobile garantendo interfacce utente native, performance native e condivisione del codice tra le diverse piattaforme utilizzando C#, il .NET Framework e Visual Studio. Lo "Xamarin Unique Approach" è il filo conduttore di questa sessione in cui impareremo a conoscerlo meglio. Sfruttate conoscenze, potenzialità e sintassi di C# per ottenere il meglio dalle vostre applicazioni cross-platform; ovviamente con Xamarin!

Lorenzo Barbieri: Architettura WP8

Davide Senatore: PhoneGap & Cordova: building cross platform mobile applications

In questa sessione parleremo di sviluppo mobile cross platform con PhoneGap (AKA Cordova).
Prenderemo in esame tool, skill richieste per iniziare e best practice per non incorrere in spiacevoli scoperte.
Scopriremo come l'investimento in "poche" tecnologie standard possa abilitarci allo sviluppo su tutte le piattaforme mobile al momento disponibili.
Non ultimo, confronteremo anche pro, contro e costi di sviluppo di una soluzione di questo tipo con una soluzione nativa ed una soluzione web-based, prendendo in esame applicazioni realmente sviluppate.

Marco Dal Pino: Sviluppare e pubblicare applicazioni Gestionali (LOB) con Windows Phone

La piattaforma Windows Phone ha raggiunto una buona diffusione di mercato e sempre più si sente la necessità di implementare funzionalità gestionali utilizzando i device WP8. Inoltre la prossima versione di Windows Embedded 8 Handheld sarà basata proprio su Windows Phone, introducendo nuovi device industriali rugged con caratteristiche di lettura barcode o Carte magnetiche; il tutto già compreso nativamente nelle API di Windows Phone. Vediamo come affrontare lo sviluppo di queste applicazioni, quali tipici problemi vanno affrontati e come distribuire il prodotto ai nostri clienti.

Inutile dire che vi aspettiamo numerosi. Non aspettate a riservare la vostra poltrona perchè i posti sono davvero limitati.

https://communitydevtool.microsoft.it/public/frmRegister.aspx?eventid=1203PSOSREGTFTMLKGCQHT


Rilasciati all'interno di Blend 3.0, nel 2009, come un mero strumento a supporto dei designer che li poteva usare per inserire sulla superficie di Blend non solo componenti di interfaccia, ma anche dei "frammenti di logica", i behavior hanno immediatamente assunto un ruolo primario nello sviluppo di applicazioni, grazie alla loro capacità di favorire la netta separazione tra logica di business e interfaccia utente. Questa capacità è rappresentata dal fatto che essi sono in grado di racchiudere e isolare porzioni di codice - con accesso diretto ai componenti di interfaccia ma pilotati dalla logica di business - inseribili facilmente direttamente nello XAML senza che sia necessaria alcuna logica accessoria.

Nati in particolare all'interno di Silverlight, essi sono immediatamente diventati parte del kit di sopravvivenza dello sviluppatore, specialmente di quello che intendeva implementare il pattern MVVM con facilità ed in seguito hanno visto il porting verso Windows Phone e finalmente anche in WinRT, con il rilascio dell'ultima versione 8.1. Conoscerli e usarli opportunamente può davvero far risparmiare un sacco di tempo. Vediamo come.

Usare i behavior esistenti

Il primo passo nell'utilizzo dei behavior è quello di inserirli nel progetto di Visual Studio e cominciare ad usare quelli esistenti. In effetti la libreria - denominata "Behaviors SDK (XAML)" porta con se una serie di classi base da cui è possibile fare ereditare i propri behavior ma anche un set abbastanza nutrito di componenti già realizzati e pronti all'uso. Essi hanno la caratteristica di essere parametrizzabili e generici così da essere fortemente riutilizzabili e quindi sono anche una buona scuola per quando dovremo realizzarne di nostri

untitledPer inserirli nel progetto con Visual Studio 2013 è sufficiente selezionarli dalla libreria delle estensioni (vedi a lato) operando come se si dovesse aggiungere una referenza al progetto.

I Behavior sono una libreria di componenti nativi e managed, e come tali possono essere usati sia in progetti C#/VB.NET sia in C++. Non richiedono particolari cautele come avviene per altri tipi di componenti perciò, una volta inserita la referenza all'SDK sarà immediatamente possibile iniziare ad usarli. Non c'è dubbio che il modo migliore è quello di usare Blend, al cui interno vengono visualizzati nella scheda degli Assets, come dei piccoli componenti che possono essere trascinati sulla superficie del designer e agganciati ai vari elementi. Una volta collegati è possibile modificarne le proprietà usando la consueta finestra di blend.

Dal punto di vista dello sviluppatore un bahavior appare ne più ne meno che come una attached property che può essere valorizzata su qualunque elemento del DOM. La proprietà è dichiarata nel namespace "Microsoft.Xaml.Interactivity" e una volta inserito nel codice xaml essa appare come una collection:

   1: <Page
   2:     x:Class="App1.MainPage" mc:Ignorable="d"
   3:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   4:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    
   5:     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   6:     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   7:     xmlns:i="using:Microsoft.Xaml.Interactivity">
   8:     <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
   9:         <Rectangle x:Name="rect" Fill="Yellow" Width="100" Height="100">
  10:             <i:Interaction.Behaviors>
  11:                 <!-- aggiungere qui in behaviors -->
  12:             </i:Interaction.Behaviors>
  13:         </Rectangle>
  14:     </Grid>
  15: </Page>

A questo punto va referenziato un ulteriore namespace, chiamiamolo per brevità "core", il quale contiene i behavior predefiniti di cui parlavo poco fa. In particolare essi sono "EventTriggerBehavior" e "DataTriggerBehavior". I loro nomi dovrebbero essere autoesplicativi ma per completezza diciamo che il primo lo si può agganciare ad un singolo evento di un elemento mentre il secondo fa riferimento al un valore di una proprietà.

Poniamo ad esempio di voler fare in modo che il rettangolo giallo dell'esempio precedente debba diventare rosso quando cliccato. Potremmo semplicemente aggiungere il seguente snippet all'interno della collezione dei behaviors:

   1: <core:EventTriggerBehavior EventName="PointerPressed">
   2:     <core:ChangePropertyAction PropertyName="Fill" Value="Red" />
   3: </core:EventTriggerBehavior>

In buona sostanza, stiamo dicendo che al verificarsi di un evento PointerPressed venga eseguita una "action" che cambia il valore di una proprietà. Le action sono un secondo livello di componenti predefiniti di cui dirò tra poco. Questa action in particolare si occupa di variare la proprietà "Fill" impostandola a "Red". Mandando in esecuzione l'esempio si vedrà che l'effetto ottenuto è proprio quello desiderato, ma anche che, a differenza di quanto avviene per il VisualStateManager, il sistema non tiene traccia dello stato originario e quindi per riportarlo allo stato precedente dovremmo aggiungere l'operazione inversa:

   1: <Rectangle x:Name="rect" Fill="Yellow" Width="100" Height="100">
   2:     <i:Interaction.Behaviors>
   3:         <core:EventTriggerBehavior EventName="PointerPressed">
   4:             <core:ChangePropertyAction PropertyName="Fill" Value="Red" />
   5:         </core:EventTriggerBehavior>
   6:         <core:EventTriggerBehavior EventName="PointerReleased">
   7:             <core:ChangePropertyAction PropertyName="Fill" Value="Yellow" />
   8:         </core:EventTriggerBehavior>
   9:     </i:Interaction.Behaviors>
  10: </Rectangle>

Le action che si possono applicare sono molteplici e coprono un vasto numero di necessità:

  • CallMethodAction: L'action richiama un metodo dell'oggetto cui si riferisce. Assomiglia molto al collegamento di un EventHandler nel codebehind.

  • ControlStoryBoardAction: Consente di collegare una o più storyboard e avviarle, così come si fa con i trigger di WPF.

  • GoToStateAction: Consente di attivare uno stato del VisualStateManager.

  • InvokeCommandAction: Uno delle action più utilizzate, in ambito MVVM consente di attivare comandi in risposta a qualunque evento se usato in concomitanza con EventTriggerBehavior.

  • NavigateToPage: Attiva la navigazione verso una pagina dell'applicazione

  • PlaySoundAction: Esegue un suono,

Una nota a parte la merita sicuramente l'InvokeCommandAction, la cui esistenza è indispensabile in scenari MVVM. Esso infatti sopperisce alla mancanza dei consueti "Command" e "CommandParameter" relativi la maggioranza degli eventi dei controlli XAML. Come in Silverlight, anche nelle Windows Store apps solamente ButtonBase implementa queste proprietà. E qui viene in aiuto questa action che associata ad un opportuno EventTriggerBehavior è in grado di riportare ad un Command del ViewModel qualunque iterazione dell'utente, aprendo numerose strade.

L'uso del EventTriggerBehavior è sicuramente il più consueto ma non va dimenticata la presenza del meno intuitivo DataTriggerBehavior. Esso ha lo scopo di legare l'esecuzione di una o più action al cambiare del valore di una proprietà. Pensiamo ad esempio ad avere una proprietà che indica una soglia di pericolosità, aggiornata in tempo reale (magari via SignalR). L'utilizzo di un DataTriggerBehavior è specifico per questi casi e ci consente di attivare una action quando il valore va oltre una determinata soglia:

   1: <Rectangle Background="Green">
   2:     <Interactivity:Interaction.Behaviors>
   3:         <Core:DataTriggerBehavior Binding="{Binding Severity}" ComparisonCondition="GreaterThanOrEqual" Value="3">
   4:             <Core:ChangePropertyAction PropertyName="Background">
   5:                <Core:ChangePropertyAction.Value>
   6:                    <SolidColorBrush>Red</SolidColorBrush>
   7:                </Core:ChangePropertyAction.Value>
   8:             </Core:ChangePropertyAction>
   9:         </Core:DataTriggerBehavior>
  10:     </Interactivity:Interaction.Behaviors>
  11: </Rectangle>

Il codice qui sopra usa una condizione, indicata dalla proprietà “Comparison Condition” per definire quale sia il valore soglia che converte. il colore da Verde a Rosso.

I behavior come abbiamo visto sono uno strumento davvero insostituibile in molti casi. Ancor di più se, come vedremo nel prossimo articolo ne creiamo di nostri, con proprietà che ne parametrizzano l’azione.

tags: - categories:

Ormai più di una settimana ho tenuto il lab su Typescript su cui da tempo stavo lavorando. Vorrei ringraziare ancora una volta tutti quelli che hanno partecipato, per la solerzia con cui hanno seguito gli esempi e hanno provato ad implementare il codice che ho preparato. Ogni giorno che passa sono sempre più convinto che Typescript sia uno strumento insostituibile e ho trovato molte conferme in questo lab vedendo le persone progredire in fretta, mano a mano che prendevano confidenza con il linguaggio e si rendevano conto delle enormi potenzialità e tutela nei confronti del pure e semplice Javascript.

Ho pubblicato tutto il materiale nel repository di XeDotNet perciò potete scaricare tutto il necessario per provare voi stessi l'esempio. In particolare seguire il documento PDF - che ho cercato di rendere il più accurato ed autonomo possibile - nel quale troverete lo step-by-step e scaricate il progetto di base da cui partire. Se poi siete pigri troverete anche l'implementazione di tutti i vari passaggi.

Ecco il link al download: http://1drv.ms/1flJCDT

Al solito se avete problemi non esitate a contattarmi con la form del weblog.


Di fronte alla vostra prima applicazione con Typescript, vi sarete certamente chiesti quale sia il modo migliore per dare ad essa il primo avvio. Può sembrare una domanda banale ma, essa cela delle considerazioni che dovrebbero essere tenute nella dovuta attenzione. Prima di tutto, è certamente vero che del codice Javascript è anche del codice Typescript perfettamente valido ma, se ci lasciamo prendere la mano e iniziamo a scrivere così come eravamo abituati in precedenza rischiamo di perdere i benefici che Typescript può regalarci.

Primo fra tutti, sicuramente il fatto che Typescript accentua fortemente le caratteristiche object oriented e di conseguenza ci dovremmo attendere di rappresentare l’applicazione – intendendo con essa una singola pagina al cui interno gira il codice che le da vita – con una sola classe, che detenga i riferimenti ai vari elementi e naturalmente lo stato. Un po’ come avviene in una applicazione asp.net, in cui una sigola pagina è rappresentata dal suo “codebehind”.

Per avviare una applicazione del genere dovremmo di conseguenza creare al più presto l’istanza della classe e dare ad essa il controllo, lasciando che gestisca il ciclo di vita della pagina fino alla sua naturale conclusione. Per questo tipo di avvio sono abituato ad utilizzare un pattern ormai abbstanza consolidato. Creaimo una classe base per la pagina, in un namespace comune che i usialmente chiamo “sys”:

   1: module sys
   2: {
   3:     export class Page
   4:     {
   5:         public static run(page: Page): void
   6:         {
   7:             $(() => page.onLoad());
   8:         }
   9:  
  10:         public onLoad(): void { }
  11:     }
  12: }

Come di può vedere , la classe consta di un metodo statico “run” e di un metodo virtual “onLoad”. Attenzione che in Typescript il concetto di virtuale non esiste ma in realtà qualunque metodo pubblico è anche virtual. Diamo per assodato che sia presente jQuery e all’interno del metodo run usiamo l’evento “readystatechanged” con la classica sintatti $(…) dove all’interno delle parentesi va indicata una funzione eseguita all’occorrenza di questo evento. A questo punto possiamo ereditare il codebehind concreto della pagina da sys.Page:

   1: class DefaultPage extends sys.Page
   2: {
   3:     constructor()
   4:     {
   5:         super();
   6:  
   7:         // inizializazione della pagina
   8:     }
   9:  
  10:     public onLoad(): void
  11:     {
  12:         // iniziamo qui il ciclo di vita
  13:     }
  14: }

In particolare nella classe viene riferinito il metodo onLoad che sarà chiamato automaticamente quando viene eseguito il “readystatechanged”. Potremmo così nel costruttore inizializzare i campi della classe, i valori di default, e così via mentre nell’onLoad potremmo cercare gli elementi della pagina, ed avviare eventuali operazioni di download da un servizio rest. L’avvio della pagina avviene per mezzo di una singola riga, posta usualmente in coda alla pagina o in un file ts:

   1: sys.Page.run(new DefaultPage());

La singola riga crea l’istanza della classe DefaultPage e poi vi da avvio con il metodo statico “run”. Niente di più semplice e pulito. Per estensione, se identificate all’interno della pagina diverse aree, a ciascuna delle quali risponda una classe Typescript che ne incapsuli il funzionamento, potete tranquillamente usare la stessa tecnica e ciascuna classe sarà avviata separatamente con il medesimo ciclo.

Di questo e di altro parleremo in occasione del Community LAB che si terrà il prossimo 28/2/2014 a Mestre. Se vi unite a me con il vostro PC sarà mia cura guidarvi nello sviluppo con questo semplice ma “liberatorio” linguaggio.

Iscrizioni e dettagli: http://www.xedotnet.org/Home/Meeting/20140228



typescript-bannerGiusto quest’oggi si sono aperte le iscrizioni al LAB su Typescript che si terrà il prossimo 28 Febbraio a Mestre – Venezia. Nell’occasione avremo modo di affrontare questo interessante linguaggio che ha il non trascurabile scopo di semlificare lo sviluppo client side all’interno dei browser. Typescript infatti gode infatti di un compilatore (che curiosamente è scritto esso stesso in Typescript) che è in grado di convertire il codice in Javascript puro, capace di essere eseguito in qualunque browser, senza necessità di un plugin addizionale. Si tratta in effetti della nemesi, regalandoci un linguaggio di alto livello – anche se mantenendo degli interessanti risvolti semantici che lo rendono flessibile come Javascript – dotato di un set di tipi verificato a compile-time.

Chi desiderasse approfondire lo può fare nei seguenti post:

Chi di voi invece preferisse provare direttamente un esempio, può raggiungermi il 28/2 a Mestre, iscrivendosi al seguente link.

http://www.xedotnet.org/Home/Meeting/20140228

Durante il lab darò una infarinatura iniziale del linguaggio e in seguito potrete seguire un esercizio step-by-step, e porre le domande del caso per risolvere i vostri problemi reali.

A presto


ios_iPad-3rd-(6.0)_6.0_portrait_thumbEra un po' di tempo che ne sentivo la necessità ma, per varie ragioni - tra cui la cronica mancanza di tempo e un po' di sana pigrizia - la revisione della grafica del mio blog personale è sempre stata posposta a data da destinarsi. Oggi finalmente va online il lavoro degli ultimi giorni in cui ho rifatto completamente tutto lo stile del blog, aggiornandolo ai più innovativi concetti di responsività e alle tecnologie quali HTML5 e CSS3. Per farvi un'idea del lavoro provate a cambiare la dimensione del browser e vi renderete conto di come l'interfaccia si adegua allo spazio disponibile, rendendo di fatto frubile il sito sia su schermi di grandi dimensioni, sia su tablet e smartphone. Ora vi prego non siate troppo pignoli, non più di quanto lo sia stato io, dato che a ben vedere ho lavorato per vestire ex-novo BlogEngine il quale, vi assicuro, è tutto fuorchè predisposto alle interfacce responsive. Si tratta infatti di un engine webforms, che utilizza spesso e volentieri tabelle e, soprattutto, non consente una personalizzazione eccessiva del markup. In definitiva, fatta eccezione per la master page e gli spazi dedicati al post e al commento, il resto dell’interfaccia è rimasto sostanzialmente invariato se non per un lavoro di fino con i CSS. Alla fine Browserstack mi consola dandomi l’ok su tutti i browser ad eccezione di IE8. L’immagine qui a lato ad esempio è tratta dallo schermo di un iPhone5s. Gli utenti di IE8 sono vivamente pregati di entrare nell’era moderna e quindi aggiornare il proprio PC. A parte BlogEngine, lo strumento principale di questa rivoluzione responsiva è Boootstrap 3.0. Per chi non lo sapesse si tratta di un toolkit che consente di progettare le interfacce web basate su html5 e css3 perchè siano fruibili da tutti i dispositivi. Si basa su una struttura fatta di righe e colonne alle quali possono essere agganciate porzioni dell’interfaccia nelle varie risoluzioni. Questo meccanismo, dopo un po’ di pratica, diviene familiare e si riescono ad ottenere dei cospicui risultati in un tempo non eccessivo, anche se, lo devo proprio dire, avessi potuto farlo in XAML, avrei finito molto ma molto prima… Ma tant’è, HTML5 e CSS3 sono una vera soddisfazione, soprattutto per chi come me ha affrontato i problemi di compatibilità dalla fine degli anni ‘90 quando ancora Netscape era un agguerrito concorrente e l’idea di vedere lo stesso sito in modo simile su due browser era semplicemente una follia. I moderni strumenti in definitiva danno un aiuto veramente efficace e i risultati, pur se ancora faticosi, si raggiungono molto più agevolmente. Boostrap mi è piaciuto fin da subito, per qualche verso più che Foundation con il quale condivide gran parte della filosofia di funzionamento. Credo che non mancherà l’occasione per parlare in questa pagine di entrambe le librerie e dei problemi della responsività. Grazie fin d’ora per i commenti, i suggerimenti e spero i complimenti che mi vorrete postare.

Happy-2014-free-wallpaper1Tracciare un bilancio del 2013 è di certo difficile e si rischia di cadere nell’ovvio. Che non sia stato un anno positivo è sicuramente certo, e credetemi non solamente dal punto di vista della politica e dell’economia di questo disastrato paese. Nel mio piccolo è stato un anno di belle idee che non si sono concretizzate, di difficili momenti che poi si sono risolti di cose più o meno comuni che sono accadute, lasciando un po’ di amarezza e tentandomi nella recriminazione.

Ciascuna esperienza porta con se un insegnamento, una morale che ci dovrebbe in qualche modo guidare nel nostro futuro, e nel mio caso questa è la convinzione, sempre più radicata in me, che dovrei ascoltare di più il mio lato istintivo e accantonare per una volta quello che il “comune sentire” mi porta troppo spesso a fare. Sono una persona molto logica e razionale ma troppo spesso non sono in grado di trarre le ovvie conclusioni che l’applicazione di logica e razionalità mi suggeriscono. Per quanto esse apparissero strane e sconclusionate si è sempre dimostrato, alla fine, che erano quelle giuste.

Ma insomma, anche il 2013 ha avuto le sue belle soddisfazioni. Ho consolidato nel tempo il mio “peso forma” portandolo alla incredibile meta degli 88kg (-35kg) e, dedicando del tempo a me, alla mia famiglia credo di aver trovato una dimensione che riesce, almeno per ora, a preservare la mia salute e la mia condizione fisica.

Ho continuato a ballare, attività che molti ritengono inutile e triviale ma che non lo è più di dedicarsi a una qualunque attività che esuli la normale routine lavorativa. Grazie al ballare ho avuto modo di conoscere altre persone che hanno punti di vista diversi, uscendo dalla dannosa autoreferenzialità che c’è nel mio ambito dei lavoro.

Ora mi accingo ad entrare nel 2014, con il timore che richiede un periodo delicato come questo. Le esperienze concluse o che si stanno concludendo devono essere un monito ma non un ostacolo e in effetti, il fervore delle feste mi ha portato alla convinzione che bisognerà dedicare del tempo a qualche progetto che possa dare una chances alle aspettative che nell’anno scorso non si sono concretizzate.

Non so se questo sarà un anno positivo, ma forse qualche briciolo di energia per fare si che lo diventi ce l’ho ancora… fatemi gli auguri!

Io ricambio con tutto il calore che posso, augurandovi un immenso 2014.


In questi giorni, chi mi segue su facebook sa che mi trovo nel Cilento, e per la precisione in uno sperduto paesino nel bel mezzo del parco nazionale omonimo. Vi assicuro che, pur se carico di elementi storici che vengono dal secoli addietro, non è molto probabile che vi troviate in questo paese per caso, dato che non è compreso nelle guide turistiche del luogo. In effetti, a parte una fugace toccata di cinque anni fa, era dal 1984 che non ci venivo. Bosco in effetti è il paese che ha dato i natali al mio nonno materno e che per circa sedici anni è stato l'unica meta delle vacanze di famiglia. Poi le cose sono cambiate, i primi viaggi all'estero, le vacanze da solo, la ragazza, la moglie, una figlia e… 28 anni sono trascorsi e uno pensa che le cose lì fuori siano rimaste congelate nel tempo e che basti tornarci per rivivere quei tempi.

Non è così ovviamente, il tempo corre per tutti alla stessa velocità e, quando torni sui tuoi passi per vedere luoghi lontani nel tempo oltre che geograficamente, trovi tutto di dimensioni diverse, stranamente piccolo. Te lo ricordi il luogo, perché' la sua morfologia cambia ma non abbastanza in fretta, un particolare alla volta. Un viottolo che prima c'era ora non esiste più e viceversa nascono spazi, nuovi e strani che non ti sai spiegare da dove sono saltati fuori. A Bosco è successo così, la strada un po' più accidentata di come la ricordavo, un edificio "innaturale" che mal si accosta a quelli storici del luogo, una fermata dell'autobus e i tuoi ricordi inciampano qua e là dandoti l'impressione di una nota stonata che non combacia con quello che la mente suggerisce.

Poi però li senti, inconfondibili, palpabili. Sono gli odori del luogo che si fissano molto più profondamente. E la mente torna a momenti della tua infanzia, a quell'aroma delizioso di una cucina, a quello terso dei panni stesi ad asciugare, all'acredine di una traccia di un animale. Potenti e inarrestabili ti entrano in testa e ti scaraventano indietro nel tempo in un millesimo di secondo risvegliando sinapsi che ormai erano confinate in angoli remoti della mente. E con essi arriva, prepotente, la nostalgia di tempi che non potranno più essere, di ore trascorse nella felicità di un pomeriggio di luglio, di amici persi e ormai non più ritrovati, di un sorriso fugace che ti è rimasto impresso.

Bosco per me oggi è questo. Cammino per le sue vie, vedo luoghi che mano a mano tornano familiari, abitati da persone ormai sconosciute e perlopiù forse fugacemente incontrate lustri fa. Una passeggiata lieta ma al tempo stesso colma del dolore di questi ricordi annebbiati. E allora parlo a mia figlia. Glieli racconto come una storia, sperando che almeno lei possa in parte memorizzare queste mie sensazioni e un giorno farne tesoro. Credo ci riuscirò…


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.


L1040139

Ma questa non è una di quelle... il giorno dello scorso settembre, in cui mia moglie mi convinse a iscrivermi ad un corso di ballo, non avrei potuto essere lontano meno di 1000 anni luce dall'idea di calcare un palco per qualcosa di diverso da una presentazione con power point. Invece ieri sera, in compagnia di mia figlia Gaia ho affrontato un pubblico di circa 400 persone assieme ad un gruppo di amici che ha condiviso con noi il lavoro di questi ultimi mesi per scatenarci nei pochi minuti più emozionanti della nostra vita.

Si tratta probabilmente della cosa più folle, e per qualcuno senza senso, che io abbia mai fatto ma, vi sembrerà impossibile, la rifarei domani stesso. La capacità di unire le persone, il lavorare con mia figlia ad un allenamento comune, il supporto di mia moglie che purtroppo ha dovuto rinunciare per un problema alla spalla, è un qualcosa di impagabile che consiglio a tutti. Da ieri questa stranezza entra a tutto diritto nella hit parade delle 10 cose migliori della mia vita... Se volete gustare i momenti di questo saggio andate a vedere qui:

https://www.facebook.com/groups/rhpositivosalsa/

Un grazie immenso alla pazienza di Maria Rodriguez e alla forza di suo fratello Alay, a mia figlia Gaia, a mia moglie Daniela... e a tutto il gruppo dell'Intermedio Salsa!


Nel precedente articolo abbiamo visto rapidamante l'espressività che ci è consentita da Typescript nella dichiarazione di nostri tipi ed interfacce. Abbiamo anche evidenziato che il compilatore applica lo structured typing consentendoci di lavorare minimizzando le dichiarazioni, proprio perchè esso è in grado di identificare ricorrenze nella struttura dei tipi e verificare che siano soddisfatte. E' chiaro tuttavia che conoscere bene la semantica del linguaggio ci permette di sfruttarene al meglio l'espressività e adottare una migliore tecnica object oriented. L'obbiettivo di questo articolo è di approfondire l'utilizzo dei tipi, a partire dai semplici parametri fino alla definizione di classi e interfacce e nella loro ereditarietà.

I tipi e il loro utilizzo

Il caso più semplice e ricorrente nelle dichiarazioni è rappresentato da variabili e parametri di un metodo e da qui partiremo analizzando le peculiarità del linguaggi. Typescript ammette pochi e semplici tipi di base:

      1. number: numero reale. esso è trattato sempre come se si trattasse di un "double"

      2. string: stringa alfanumerica

      3. bool: valore booleano (true o false)

      4. any: è l'equivalente di una dichiarazione di tipo "variant" in quanto annulla il controllo del compilatore sui membri. Su un membro "any" può essere invocato qualunque metodo ma è onere del programmatore assicurarsi che esso esista.

      5. function: così come avviene per javascript, il compilatore ammette anche la dichiarazione di metodi che ammettano una funzione, consentendo ad esempio l'uso di callback.

    Tralasciano di tipi ovvi quali number, string e bool che dovrebbero essere di uso comune a chiunque e che obbiettivamente non presentano sorprese, vale la pena approfondire l'utilizzo di any e delle dichiarazioni di funzione:

       1: var theWindow : any = <any>window;
       2: theWindow.execute();

    La precedente dichiarazione rende la variabile myObject generica a tal punto che è possibile chiamare su di essa un metodo di cui typescript non conosce l'esistenza. Il caso illustrato è abbastanza comune quando in una pagina convive il codice javascript di una libreria di terze parti e il nostro typescript. Se una ipotetica libreria avesse dichiarato una funzione nel documento, Typescript non potrebbe conoscerla e di conseguenza il compilatore si interromperà con un errore. Ecco quindi che si effettua il cast di "window" ad "any" (il cast si indica con le parentesi angolari <any>) e a questo punto è possibile chiamare la funzione senza che il compilatore si impunti.

    Un altro caso particolare sono le variabili che ammettono come valore una funzione:

       1: var callback : (number) => string;
       2:  
       3: callback = function(n) 
       4: { 
       5:     return "The answer is " + n; 
       6: };
       7:  
       8: var result = callback(42);

    La variabile callback in questione viene dichiarata con una sintassi che mima quella delle lambda expression. La sintassi "(int) => string" identifica una funzione che ha un parametro intero e un valore di ritorno di tipo stringa.

    Inutile dire che è ammissibile avere funzioni senza parametri

    var callback : () => string

    con un valore di ritorno void

    var callback : (mynum: number) => void

    oppure con parametri multipli

    var callback : (mynum: number, mystring: string, mybool: bool) => string

    Interessante comunque notare che il compilatore non richiede che la funzione passata abbia esplicitato il tipo dei parametri ma, per mezzo dell'inferenza, applica automaticamente i tipi attesi. E' comunque sempre ammesso esplicitarli. Per passare una funzione alla variabile callback è possibile operare come nell'esempio, oppure utilizzare la sintassi lambda-expression come segue:

       1: var callback : (number) => string;
       2:  
       3: callback = (n) => { return "The answer is " + n };
       4:  
       5: var result = callback(42);

    Fin'ora per semplicità abbiamo visto le dichiarazioni applicate alle variabile, ma i medesimi tipi possono essere utilizzati anche per dichiare i parametri di un metodo piuttosto che le proprietà di una interfaccia o di una classe. Vediamo alcuni esempi:

       1: // metodo
       2:  
       3: function getRemoteData(callback: (result) => void) : void
       4: {
       5:     // download here
       6: }
       7:  
       8: // interfaccia
       9:  
      10: interface IHandler
      11: {
      12:     value: number;
      13:     callback : (result) => void;
      14: }
      15:  
      16: // costruttore di classe
      17:  
      18: class MyHandler implements IHandler
      19: {
      20:     value: number;
      21:  
      22:     constructor(public callback: (result) => void)
      23:     {}
      24: }

    In ordine di apparizione, nel primo esempio viene utilizzato un parametro denominato "callback" che è richiesto sia una funzione che accetta un parametro "result" ("any" visto che è omessa la dichiarazione di tipo) e non ritorna alcun valore. Nel secondo esempio invece abbiamo la definizione di una interfaccia che accetta una proprietà numerica e una seconda proprietà "callback" che richiede una function. Infine nel terzo esempio di da implementazione alla precedente interfaccia con una classe. In questo caso il metodo callback verrà fornito nel costruttore e la keyword public sul parametro da automaticamente implementazione alla proprietà pubblica (e questo basta per soddisfare l'interfaccia).

    Parametri opzionali

    Un problema ricorrente nella definizione di metodi sono i parametri opzionali. E' tipico, soprattuto di Javascript, l'avere funzioni i cui parametri non forniti sono automaticamente valorizzati a "null" e quindi con un semplice controllo è possibile simulare l'overloading che esiste nei linguaggi di più alto livello. In Typescript l'overloading dei metodi non esiste, se non nelle dichiarazioni delle interfacce, ma vige invece la possibilità di definire opzionali alcuni o tutti i parametri. Partendo da questa ultima abbiamo:

       1: function addItem(name: string, value?: number): void
       2: {
       3:     if (value == null)
       4:         value = 0;
       5: }

    L'indicazione di un "?" dopo il nome del parametro lo rende opzionale. E' chiaro che a questo punto abbiamo l'onere di verificare che esso sia valorizzato per evitare errori. Nell'esempio il parametro "value" viene valorizzato con un valore di default nel caso non sia stato specificato.

    La cosa interessante è che possiamo fare uso delle interfacce per simulare l'overload del metodo, fornendo una descrizione nell'intellisense che è di grande aiuto per lo sviluppatore. Prima di tutto dichiariamo una classe con il precedente metodo:

       1: class List
       2:     implements IList
       3: {
       4:     addItem(name: string, value?: number): void
       5:     {
       6:         if (value == null)
       7:             value = 0;
       8:     }
       9: }

    A questo punto, nell'interfaccia IList possiamo dare la definizione di due metodi con il medesimo nome. Attenzione che questa operazione nella classe darà adito ad un errore di compilazione mentre è perfettamente ammessa nell'interfaccia:

       1: interface IList
       2: {
       3:     addItem(name: string): void;
       4:     addItem(name: string, value: number): void;
       5: }

    In seguito a questa dichiarazione potremmo sfruttare l'interfaccia e l'intellisense di Visual Studio 2012 ci fornirà una descrizione del tutto simile a quella cui siamo abituati con C#:image

     

     

     

    Conclusione

    Il ridotto numero di tipi disponibile in Typescript non deve trarre in inganno. Così come in Javascript siamo in grado di trattare qualunque tipo abbastanza semplicemente, tanto più in Typescript saremo in grado di gestire agilmente qualunque informazione, con il supporto di una libreria di classi che sopperisce alla ristrettezza di tipi primitivi. E' il caso ad esempio del tipo "Date" che, come accade in Javascript, non è nativo del linguggio. Nella libreria automaticamente linkata dal compilatore troviamo le definizioni del tipo in termini di interfaccia e possiamo gestire correttamente il tipo in questione.


    Pur se lo static type checking è un elemento importante nell'utilizzo di Typescript, tanto da essere già una ragione più che valide nella sua adozione, è chiaro che si può fare di più nella semplificazione del codice Javascript e nella sua organizzazione. Nel corso degli anni si sono consolidate alcune pratiche comuni nella stesura di Javascript, per venire incontro alla carenza dei concetti di base dell'object orientation che sono particolarmente labili e limitati. Tra essi si possono annoverare alcune naming convention - ad esempio prependere un underscore ad una variabile la identifica come privata - e dei veri e propri pattern quali le closure. Tutto ciò in effetti è più che altro una notazione stilistica che una vera e propria caratteristica del linguaggio e spesso e volentieri tali pratiche tendono a renderlo di difficile comprensione e manutenzione. Typescript ha tra i suoi costrutti alcuni che hanno proprio lo scopo di semplificare nettamente il codice mascherando la vera e propria complessità che origina dalla sua compilazione.

    Interfacce e classi

    Nel precedente articolo abbiamo visto che grazie allo structured typing, Typescript è in grado di riconoscere i tipi semplicemente analizzando la corrispondenza delle proprietà. L'esempio seguente riassume in breve la questione:

       1: function getArea(s: { width: number; height: number; }): number
       2: {
       3:     return s.width * s.height / 2;
       4: }
       5:  
       6: var area = getArea({ width: 20, height: 30 });
       7: console.log(area.toString());

    E' del tutto chiaro che questo tipo di notazione, pur se tutelata dal compilatore, è eccessivamente prolissa e a lungo andare puà essere oggetto di errori e incomprensioni. Per questa ragione Typescript ammette innanzitutto la creazione di interfacce, che altro non sono che la definizione del contratto di un tipo, cui il valore deve conformarsi. Un concetto più che normale per chi mastica programmazione ad oggetti. Vediamo un esempio:

       1: interface Shape
       2: {
       3:     width: number;
       4:     height: number;
       5: }
       6:  
       7: function calculateArea(s: Shape): number
       8: {
       9:     return s.width * s.height  / 2;
      10: }
      11:  
      12: var area = calculateArea({ width: 20, height: 30 });
      13: console.log(area.toString());

    Nelle prime righe dello snippet è visibile la dichiarazione di una interfaccia "Shape". Essa riporta le proprietà "width" e "height" e viene usata come parametro della funzione calculateArea, al posto della precedente notazione estesa. L'argomento passato alla calculateArea è rimasto invariato, ma se provate a modificarne i nomi vi renderete contro che lo structured typing continua a funzionare come prima, validando il parametro contro la definizione dell'intefaccia. Le interfacce ammettono anche metodi e proprietà opzionali (usando il ?). Ecco un esempio:

       1: interface Shape
       2: {
       3:     width: number;
       4:     height: number;
       5:     color?: string;
       6:     getArea(): number;
       7: }
       8:  
       9: function calculateArea(s: Shape): number
      10: {
      11:     return s.getArea();
      12: }
      13:  
      14: var area = calculateArea(
      15:     {
      16:         width: 20,
      17:         height: 30,
      18:         getArea: function() { return this.width * this.height / 2; }
      19:     });
      20:  
      21: console.log(area.toString());

    L'esempio in questione estremizza la definizione dell'interfaccia Shape richiedendo una proprietà opzionale "color" (che poi non viene passata più sotto) e un metodo che effettua il calcolo dell'area. In tal modo la funzione calculateArea non deve fare altro che chiamare il metodo getArea dell'interfaccia per ottenere il valore calcolato. Si tratta di un primo passo verso una conversione object oriented dell'esempio. A questo punto potremmo voler implementare l'interfaccia Shape in diverse figure e fornire una diversa formula per il calcolo. Lo possiamo fare grazie alla presenza delle classi. Vediamo come:

       1: interface Shape
       2: {
       3:     width: number;
       4:     height: number;
       5:     getArea(): number;
       6: }
       7:  
       8: class Triangle implements Shape
       9: {
      10:     constructor(
      11:         public width: number,
      12:         public height: number) { }
      13:  
      14:     getArea(): number {
      15:         return this.width * this.height / 2;
      16:     }
      17: }
      18:  
      19: class Square implements Shape
      20: {
      21:     constructor(
      22:         public width: number,
      23:         public height: number) { }
      24:  
      25:     getArea(): number {
      26:         return this.width * this.height;
      27:     }
      28: }
      29:  
      30: function calculateArea(s: Shape): void
      31: {
      32:     var area = s.getArea();
      33:     console.log(area.toString());
      34: }
      35:  
      36: calculateArea(
      37:     new Square(20, 30));
      38: calculateArea(
      39:     new Triangle(20, 30));

    Grazie alla keyword "class" è possibile creare delle vere e proprie classi che, a differenza di quello che succede per le interfacce, che spariscono nel codice Javascript, generano una struttura che chi è avvezzo a Javascript riconoscerà sicuramente.

       1: var Triangle = (function () {
       2:     function Triangle(width, height) {
       3:         this.width = width;
       4:         this.height = height;
       5:     }
       6:     Triangle.prototype.getArea = function () {
       7:         return this.width * this.height / 2;
       8:     };
       9:     return Triangle;
      10: })();

    Nel precedente snippet abbiamo anche la dimostrazione che una classe può implementare una specifica interfaccia, per mezzo della keyword "implements" e così facendo il compilatore verificherà a tempo di compilazione che la classe supporti i metodi e le proprietà da essa richieste. Siamo a questo punto arrivati ad una programmazione ad oggetti del tutto raffinata, che poco ha a che vedere con la complessità cui si è abituati con Javascript, totalmente mascherata dal compilatore Typescript.

    Oltre all'implementazione di interfacce è del tutto possibile estendere classi esistenti. Per fare questo dovremo utilizzare la keywork "extends" al posto di "implements". Vediamo come usare l'ereditarietà per create una classe "Cube" derivando da "Square":

       1: class Cube
       2:     extends Square
       3: {
       4:     constructor(
       5:         width: number,
       6:         height: number,
       7:         public depth: number)
       8:     {
       9:         super(width, height);
      10:     }
      11:  
      12:     getArea(): number
      13:     {
      14:         return (super.getArea() * 2) +
      15:                (this.depth * this.width * 2) +
      16:                (this.depth * this.height * 2);
      17:     }
      18: }
    In questo esempio vediamo che al costruttore della classe viene aggiunto un ulteriore parametro "depth" che identifica l'altezza del parallelepipedo. Avendo modiificato la firma il compilatore richiede che la prima chiamata nel body del costruttore sia la funzione "super" che ha lo scopo di chiamare il costruttore della classe base. Questa deve essere specificata come faremmo usando "base" in C#. La medesima keyword può essere usata anche per chiamare i metodi della classe base. Ad esempio il metodo getArea richiama l'omonimo della classe base per poi sfruttare il risultato integrando la rimanente parte dell'area.

    Usare i moduli

    Una volta che abbiamo classi e interfacce i benefici che ne derivano sono numerosi, soprattutto in termini di organizzazione logica del codice e di manutenzione. Il passo successivo è di organizzare il codice in moduli - i programmatori C# li conosceranno meglio come "namespace" - per riuscire a creare vere e proprie librerie i cui nomi siano univoci. Anche in questo Typescript ci aiuta; grazie alla keyword "module" infatti sarà possibile creare dei veri e propri namespace:

       1: module Shapes
       2: {
       3:     export class Square implements Shape
       4:     {
       5:         constructor(
       6:             public width: number,
       7:             public height: number) { }
       8:  
       9:         getArea(): number
      10:         {
      11:             return this.width * this.height;
      12:         }
      13:     }
      14: }

    Interessante notare che la classe definita nel modulo "Shapes" è stata decorata con "export". Infatti, una volta che abbiamo messo una classe (o qualunque altro costrutto) in un modulo possiamo renderlo visibile o invisibile all'esterno beneficiando di un incapsulamento che in termini di librerie riutilizzabili è prezioso.

    Come si è abituati a fare con i namespace in C#, anche in Typescript i moduli possono essere annidati in modo del tutto analogo, creandoli effettivamente l'uno nell'altro:

       1: module Shapes
       2: {
       3:     export class Square implements Shape
       4:     {
       5:         constructor(
       6:             public width: number,
       7:             public height: number) { }
       8:  
       9:         getArea(): number
      10:         {
      11:             return this.width * this.height;
      12:         }
      13:     }
      14:  
      15:     export module ThreeD
      16:     {
      17:         export class Cube extends Square
      18:         {
      19:             // ... omissis
      20:         }
      21:     }
      22: }

    Oppure usando una notazione puntata

       1: module Shapes.ThreeD
       2: {
       3:     export class Cube extends Square
       4:     {
       5:         // ... omissis
       6:     }
       7: }

    Ciascuna delle due notazioni può essere tranquillamente utilizzata assieme all'altra creando vere e proprie composizioni in cui i moduli si combinano. Una volta che i moduli sono stati creati sarà possibile raggiungere i tipi definiti nei moduli specificando l'intero namespace:

       1: var square: Shapes.Square;
       2: var cube: Shapes.ThreeD.Cube;

    Data la notevole lunghezza e ridondanza che i nomi completi di namespace possono raggiungere è del tutto possibile creare degli shortcut che siano in grado di semplificare la scrittura del codice:

       1: import sh = Shapes;
       2: import sh3d = Shapes.ThreeD;
       3:  
       4: var square: sh.Square;
       5: var cube: sh3d.Cube;

    Come a casa propria

    Sono convinto che i programmatori C#, ma in generale qualunque sviluppatore sia avvezzo all'uso di un linguaggio evoluto basato sui paradigmi della programmazione ad oggetti, leggendo il codice Typescript si senta bene come a casa propria. In effetti se si da uno sguardo veloce al codice generato dal compilatore si comprende come Typescript sia in grado di fornire strumenti che la programmazione Javascript può dare solo a caro prezzo. Per intenderci vediamo un esempio di cosa sia possibile fare:

       1: module Shapes
       2: {
       3:     export interface Shape
       4:     {
       5:         width: number;
       6:         height: number;
       7:         getArea(): number;
       8:     }
       9:  
      10:     export enum ShapeType
      11:     {
      12:         Square,
      13:         Triangle
      14:     }
      15:  
      16:     export class ShapeFactory
      17:     {
      18:         static create(type: ShapeType, width: number, height: number): Shape
      19:         {
      20:             switch (type)
      21:             {
      22:                 case ShapeType.Square:
      23:                     return new Square(width, height);
      24:                 case ShapeType.Triangle:
      25:                     return new Triangle(width, height);
      26:             }
      27:  
      28:             return null;
      29:         }
      30:     }
      31:  
      32:     class Triangle implements Shape
      33:     {
      34:         constructor(
      35:             public width: number,
      36:             public height: number) { }
      37:  
      38:         getArea(): number
      39:         {
      40:             return this.width * this.height / 2;
      41:         }
      42:     }
      43:  
      44:     class Square implements Shape
      45:     {
      46:         constructor(
      47:             public width: number,
      48:             public height: number) { }
      49:  
      50:         getArea(): number
      51:         {
      52:             return this.width * this.height;
      53:         }
      54:     }
      55: }
      56:  
      57: import sh = Shapes;
      58: var sq = sh.ShapeFactory.create(sh.ShapeType.Square, 20, 30);
      59: console.log(sq.getArea());
    Credo che la combinazione di moduli, classi, interfacce ed enumeratori di questo esempio, assieme con l'applicazione di metodi statici e dell'incapsulamento nei moduli sia molto significativa di come si possa scrivere con proprietà un codice molto efficace.