Archivi
Auguri a tutti
Se il 2010 è stato un anno molto importante per me, ricco di occasioni perse e colte, vi assicuro che il 2011 si prospetta come un anno rivoluzionario da tanti punti di vista, che mi metterà alla prova sotto molteplici aspetti, prove che non vedo l'ora di affrontare.
E' con questo spirito di sfida che auguro a tutti voi un buon Natale ed un felice anno nuovo.
altro
Community Tour 2010: missione compiuta
Come vi avevo preannunciato, il 3 Dicembre ho partecipato al Community Tour 2010 di Microsoft organizzato dalla community DotNetSide e sono molto contento dell'esperienza fatta come speaker. Ho avuto l'occasione di conoscere nuove persone, di scambiare con loro impressioni e dubbi sulle nuove tecnologie, WIndows Azure su tutte e, dulcis in fundo (anzi "panzerottus in fundo"), di farmi un panzerotto da Di Cosimo, una vera e propria istituzione a Bari per chi non lo sapesse, in compagnia di tutta l'allegra compagnia.
E' stato molto interessante seguire gli interventi degli altri speaker che hanno tenuto sessioni che vanno da quelle più tecniche su Windows Phone 7, a quella più filosofico/culturale su Windows Azure.
Ammetto di non essere rimasto molto sorpreso quando all'inizio della mia sessione alla domanda "qualcuno ha mai sviluppato applicazioni con ASP.NET MVC?", nessuno ha alzato la mano. Mi auguro che la mia sessione abbia portato un po di chiarezza su questo nuovo modo di costruire applicazioni web con .NET e abbia fatto nascere nei partecipanti un briciolo di curiosità in più, che magari potrà sfociare nel tempo con la sua adozione.
Di seguito trovate un link da cui poter scaricare le slide e la demo che ho mostrato.
altroDotNetSide Community Tour 2010
Il prossimo 3 Dicembre, la community DotNetSide in collaborazione con Microsoft terrà l'evento Community Tour 2010. Benché quest'anno tale occasione sia incentrata principalmente su Windows Azure e Windows Phone 7, il sottoscritto debutterà come speaker tenendo una sessione su ASP.NET MVC 2.
L'evento si terrà presso il Best Western Hotel HR, SS 96 km 119,300, Bari - Modugno 70123.
Al seguente indirizzo potete trovare l'agenda completa e il link per registrarvi.
altroActivities integrate in Workflow Foundation 4
Oggi vi segnalo un mio nuovo articolo che è stato pubblicato su Dotnetside, il portale del primo user group del sud Italia dedicato al Microsoft .NET Framework. Da qualche mese ho iniziato a collaborare con questa community e, visto che scarseggiano informazioni esaurienti su Windows Workflow Foundation 4 (WF4) l'API integrata nel .NET Framework 4 per la realizzazione e gestione di workflow, ho deciso di dedicare all'argomento una serie di articoli.
Per il momento ho realizzato un paio di articoli base che hanno l'obiettivo di fornire una panoramica degli strumenti che mette a disposizione WF4. I prossimi articoli entreranno più nel dettaglio di alcune specifiche funzionalità.
Gli articoli attualmente disponibili sono i seguenti:
In entrambi i casi troverete in fondo alla pagina un allegato contenente una soluzione Visual Studio 2010 di esempio.
altroInstanceStore e WorkflowApplication in WF4
Quando si utilizza Workflow Foundation 4 si ha a disposizione più di un'opzione per l'hosting di un'istanza di workflow, cioè essenzialmente per avviare ed eseguire un workflow.
Una delle grandi funzionalità introdotte da Workflow Foundation 4 è la classe WorkflowServiceHost grazie alla quale è possibile esporre un workflow come servizio e, attraverso un meccanismo di correlation, legare l'input delle chiamate al servizio in modo da identificare l'istanza di workflow al quale la chiamata fa riferimento.
Tutto il sistema legato al WorkflowServiceHost è molto interessante e direi piuttosto facile da utilizzare considerando che gestisce in autonomia attività come il resuming di un'istanza di workflow, la gestione di timer che scadono per le istanze di idle, ecc...
Cosa accade, però, se si ha la necessità di ottenere maggior controllo sul runtime di Workflow Foundation 4? Supponiamo di dover realizzare un'infrastruttura che, dato uno standard di comunicazione tra i workflow e il mondo esterno, debba consentire di gestire più tipologie di un workflow? E' evidente che questo tipo di requisito è incompatibile con l'hosting via WorkflowServiceHost semplicemente perché tale hosting si basa sul presupposto che ogni tipologia di workflow ha i suoi specifici servizi e tale presupposto non consente una standardizzazione della comunicazione tra il runtime del workflow e il mondo esterno.
A che serve, vi chiederete voi, una cosa del genere? Beh, se dovete disaccoppiare la logica del workflow dall'interfaccia grafica, è buona norma evitare di legare le chiamate al workflow ai web service esposti dal workflow stesso. In caso contrario una minima modifica a questi contratti, comporterà la ricompilazione di tutta l'applicazione.
La classe WorkflowApplication è la scelta prediletta nel caso in cui vogliate gestire manualmente l'hosting e la comunicazione tra le istanze di workflow e le applicazioni che devono richiamarle.
Fondamentale a tal proposito è la gestione della persistenza. Se siete così fortunati da non avere la necessità di persistere le vostre istanze di workflow, allora, oltre ad invidiarvi molto, vi comunico che potete anche non proseguire la lettura di questo post :-)
La persistenza passa dalle classi che ereditano dalla classe base InstanceStore. Ovviamente Workflow Foundation 4 integra quella necessaria per utilizzare SqlServer come repository e pertanto utilizzeremo la classe SqlWorkflowInstanceStore.
var workflow = new Workflow1(); var workflowApplication = new WorkflowApplication(workflow); var instanceStore = new SqlWorkflowInstanceStore(connectionString); workflowApplication.InstanceStore = instanceStore;Il codice riportato funziona benissimo, ma ha un piccolo problema di efficienza: vi costringe a creare una nuova istanza di SqlWorkflowInstanceStore ogni volta che dovete gestire un'istanza di workflow. Se provate ad assegnare la stessa istanza di InstanceStore a più WorkflowApplication otterrete un bel InstancePersistenceCommandException con il seguente messaggio:
SqlWorkflowInstanceStore does not support creating more than one lock owner concurrently. Consider setting InstanceStore.DefaultInstanceOwner to share the store among many applications.
Il problema in sostanza è che un'istanza di SqlWorkflowInstanceStore funge anche da lock owner, cioè essenzialmente blocca un'istanza di workflow nel corso del suo ciclo di vita (dal caricamento alla persistenza) per impedire che parallelamente più host possano accedere alla medesima istanza.
Per fare in modo che un'istanza di SqlWorkflowInstanceStore possa caricare più istanze contemporanemente è necessario definire il ciclo di vita del lock owner e a tal proposito è necessario impostare la proprietà DefaultInstanceOwner con il risultato dell'esecuzione di un comando denominato CreateWorkflowOwnerCommand come segue:
var instanceHandle = instanceStore.CreateInstanceHandle(); var createOwnerCmd = new CreateWorkflowOwnerCommand(); var view = instanceStore.Execute(instanceHandle, createOwnerCmd, TimeSpan.FromSeconds(30)); instanceStore.DefaultInstanceOwner = view.InstanceOwner;Particolare importanza risiede nel InstanceHandle. Non sottovalutate la gestione di questo handle perché è da lui che dipende l'uso delle risorse del SqlWorkflowInstanceStore.
Una volta impostato il DefaultInstanceOwner potete far utilizzare questo InstanceStore a più istanze della classe WorkflowApplication. Non dovete, tuttavia, dimenticare di richiamare il comando DeleteWorkflowOwnerCommand quando avete completato le operazioni da eseguire sulle istanze di WorkflowApplication:
var deleteOwnerCmd = new DeleteWorkflowOwnerCommand(); instanceStore.Execute(instanceHandle, deleteOwnerCmd, TimeSpan.FromSeconds(30));
L'esecuzione di questo comando garantisce che l'owner non sia più attivo e, pertanto, consente ad altri lock owner di accedere alle istanze di workflow. Da notare che sia il comando di Create che quello di Delete abbiano in comune l'instanceHandle che, a seguito del comando di Delete, viene correttamente rilasciato insieme a tutte le risorse che identifica. Nel caso in cui vogliate rilasciare le risorse prima di richiamare il comando Delete, potete utilizzare il metodo Free.
altroADO.NET, DataTable e il metodo Load
Quando si studia .NET uno dei aspetti che più di altri spesso vengono rimarcati è la gestione delle risorse e, in particolare, di tutte le classi che implementano l'interfaccia IDisposable. Come molto di voi sapranno quasi sempre le classi che implementano queste interfacce utilizzano risorse unmanaged ed è per questo che il loro corretto trattamento è fondamentale al fine di liberare tali risorse. Gli esempi più classici sono gli stream come FileStream e NetworkStream che gestiscono rispettivamente l'accesso al file sistem e alla rete via socket.
Memore di questa buona pratica (sono quasi un fanatico dell'uso del costrutto using), ho spesso strutturato l'accesso al database in maniera tale da renderlo il più rapido ed efficiente possibile e in maniera da liberare al più presto la DbConnection utilizzata.
Tuttavia mi sono reso conto che una delle pratiche che ho spesso utilizzato per caricare i risultati di una query SELECT non è la più efficiente. In particolare, dopo aver correttamente costruito il mio DbCommand, averlo associato alla DbConnection, aver inserito eventuali DbParameter, mia comune pratica a seguito dell'esecuzione del metodo ExecuteReader, era quella di dichiarare una DataTable e di caricare il contenuto del DbDataReader attraverso il metodo Load della classe DataTable.
Come saprete la classe DataTable non è altro che una struttura dati disconnessa che rappresenta in memoria il risultato di una query che restituisce almeno un result set. Di per sé non ha molto senso utilizzarla al giorno d'oggi visto che spesso si usa un ORM per accedere al database, tuttavia esistono casi in cui è necessario affidarsi ancora al buon vecchio ADO.NET.
Il metodo Load della classe DataTable è molto comodo perché carica in memoria il risultato di una query strutturando correttamente la DataTable in maniera che ogni sua DataColumn contenga le informazioni (tipo, nome, ecc....) relative ad ogni colonna del result set.

Ho riscontato tuttavia un problema. Quando si utilizzano i Guid in Oracle, indipendentemente dal provider che utilizzate, che questo sia il Devart, ODP.NET o l'OracleClient del .NET Framework (a proposito quest'ultimo è ormai deprecated nella versione 4.0, quindi non usatelo più) nella vostra DataTable, in corrispondenza della colonna che dovrebbe contenere i Guid vi ritroverete un bel array di byte. Oracle gestisce i Guid come RAW(16), quindi effettivamente un array di 16 byte e, pertanto, il metodo Load della DataTable convertirà la colonna in un bel byte[].
Come risolvere questo problema? Inizialmente avevo pensato di scorrermi successivamente alla Load, nuovamente la DataTable per convertire le DataColumn di byte array in Guid. Inutile dirvi che questa è una pessima pensata perché le prestazioni risultano essere dannatamente penalizzanti, soprattutto in confronto all'esecuzione della medesima operazione su SQL Server dove questo problema non c'è e dove, pertanto, il passaggio di conversione non serve.
La soluzione a questo problema è stata di abbandonare il metodo Load della DataTable e di costruirsela a mano scorrendosi il DbDataReader come un bel ciclo while. Il DbDataReader contiene un metodo di Get per ogni tipo di dato supportato tra i quali il Guid. Poiché quando io carico il risultato dal DbDataReader so perfettamente a priori quale tipo di dato mi aspetto da ogni colonna, è stato sufficiente fare un bel switch case e richiamare il metodo di Get corretto.
Mentre implementavo questa soluzione pensavo di ottenere prestazioni molto basse rispetto all'uso del metodo Load della DataTable e, invece, mi sono dovuto ricredere. Non solo con questo nuovo sistema sono riuscito ad ottenere in ogni colonna i dati del giusto tipo (dovete usare il provider di Devart per poter usare la GetGuid su Oracle in quanto non è supportata dall'OracleClient e dall'ODP.NET), ma le prestazioni complessivamente sono aumentate notevolmente sia su Oracle, che su SQL Server di oltre 5 volte. Se prima per caricare 10.000 record la Load ci impiegava circa 400 ms, con la nuova soluzione ottengo il medesimo risultato in 70-80 ms, notevole non credete?
Certo, la quantità di codice scritta è molto più corposa (passiamo da 1 riga di codice, appunto la Load, ad una ventina di righe), ma poiché l'accesso ai dati è spesso uno dei maggiori colli di bottiglia in un sistema, incrementarne le prestazioni di oltre 5 volte non può che far bene.
altroSviluppo mobile cross-OS con .NET
Ultimamente mi sto cimentando nella programmazione per sistemi operativi mobile. In particolare, insieme ad un mio carissimo amico, stiamo tentando di concretizzare qualche progettino destinato al mercato degli smartphone.
Nella progettazione di queste soluzioni (beh si, non guardatemi male, io di solito inizio dalla progettazione e non scrivendo direttamente codice) abbiamo identificato la seguente architettura:
- Web Service esposti sul web contenti la logica di business
- Database server sul web server
- Applicazione mobile che richiama i servizi e si occupa essenzialmente della visualizzazione dei risultati e di gestire la UI
A questa organizzazione del lavoro, siamo giunti dopo aver analizzato i seguenti aspetti:
- Inserire la logica lato server ci permette di rendere il servizio disponibile su più tipologie diverse di client, cioè essenzialmente su più piattaforme
- Inserire la logica lato server ci permette di semplificare al massimo la logica lato client
- Inserire la logica lato server ci permette di programmare la logica in C# usando .NET, il che, fidatevi, è un enorme vantaggio
Il terzo punto in particolare va sottolineato perché se, come abbiamo intenzione di fare noi, si vogliono realizzare applicazioni su iPhone e iPad, è necessario imparare l'objective-c e buona parte della libreria Cocoa. Considerando che gran parte delle applicazioni per smartphone che riportano informazioni, lo fanno parserizzando selvaggiamente pagine HTML, volete mettere quando è semplice farlo utilizzando le API di .NET rispetto al SDK di iOS?
In realtà stiamo valutando anche la possibilità di scrivere le applicazioni lato client in C# utilizzando Monotouch. Questo ci permetterebbe di rendere l'applicazione facilmente "portabile" anche su Windows Phone 7 e, contestualmente, semplifica non poco effettuare operazioni come le chiamate ai web service che su iOS vanno praticamente costruite a manina. Pensate che nella roadmap di Mono è previsto perfino Monodroid per lo sviluppo in C# per Android :-)
altroORM per .NET: un'interessante comparativa
Nel corso dello sviluppo di un progetto utilizzando l'Entity Framework per il layer di accesso ai dati e LINQ to Entities come formalismo per l'interrogazione del database, mi sono imbattuto in alcuni problemi di performance che mi hanno spinto a fare qualche approfondimento su questa tecnologia per l'accesso ai dati.
Premetto subito che sto usando il .NET Framework 4 insieme ai POCO come modello, in maniera da slegare la materializzazione degli oggetti dalla specifica tecnologia di accesso ai dati scelta.
Navigando sul sito di Devart (il database server usato dal progetto è Oracle 11g) ho trovato un link a ORMBattle.NET, un'interessantissimo sito che effettua una comparazione tra molteplici ORM su .NET valutandole l'implementazione di LINQ e le performance.

I risultati non sono per nulla scontati. Innanzitutto l'Entity Framework non è l'ORM più efficiente del lotto. Si può dire che fornisce un supporto a LINQ nella media, mentre dal punto di vista delle performance è complessivamente il terzultimo. Peggio di lui fanno solo NHibernate e Subsonic.
Molto interessanti, invece, sono le soluzioni DataObjects.NET e BLToolkit. Quest'ultimo, tuttavia, non può essere considerato un vero e proprio ORM in quanto, da quello che ho potuto vedere, effettua più che altro una materializzazione degli oggetti risultanti da una query. L'effort in termini di configurazione è sicuramente più elevato rispetto alle altre soluzioni e la valutazione di questo aspetto è a mio parere il punto debole della comparativa: non si considera quanto tempo fa risparmiare l'uso di un ORM rispetto ad altro o rispetto a non usarne per niente. E' certamente una valutazione difficile da stimare, ma secondo me non impossibile.
In fin dei conti che le performance degli ORM siano inferiori rispetto a fare query a botta di DataReader è certamente scontato, ma del resto non è per questo motivo che si utilizzano tali strumenti.
Sempre nell'ambito del lavoro svolto in questo progetto ho avuto modo di valutare il comportamento del provider di Devart con l'Entity Framework e analizzando le query generate posso serenamente affermare che, a parte cambiare le parentesi quadre con le virgolette e sostituire il token parameter @ con i due punti, altre differenze non ci sono nelle query generate rispetto al provider Microsoft per SQL Server,
A questo punto mi chiedo: si tratta di una limitazione dell'Entity Framework che non consente ad ogni singolo provider di generare completamente le query oppure i signori di Devart hanno "preso spunto" dal provider Microsoft per realizzare il loro per Oracle?
altroInternet Explorer 9 beta

In questi giorni ho avuto modo di dare un'occhiata alla nuova beta di Internet Explorer 9. Beh io direi che questa volta Microsoft sembra aver fatto veramente un ottimo lavoro, il che non è semplice da affermare quando si accosta il nome Internet Explorer ad un qualsiasi aggettivo positivo.
Ho seguito abbastanza da vicino l'evoluzione di Internet Explorer 9, discutendone in un paio di occasioni anche su Appunti Digitali e ora che ho messo le mani sulla versione beta devo ammettere di non essere rimasto deluso nè dal punto di vista grafico, nè in termini di prestazioni.
Il primo elemento che mi ha colpito è che al primo avvio mi ha segnato una serie di componenti aggiuntive che rallentavano l'avvio del browser stesso, presentando un bel grafico con la comparazione dei tempi di inizializzazione di ogni componenti. Inutile dire che è stato semplicissimo individuare il problema (una componente della mia scheda TV che ignoravo di avere e che della quale tutt'ora non capisco il ruolo) e risolverlo.
L'aspetto della UI è molto pulito, direi abbastanza "Chrome style", il che non deve essere visto in modo negativo come avranno già pensato i tanti detrattori di Microsoft, ma piuttosto come una presa di coscienza da parte dell'azienda di Redmond che Google ha avuto una buona idea che valeva la pena riportarla nel nuovo browser esattamente come è accaduto con le ultime versioni di Opera e le ultime beta di Firefox 4. Riprendere uno stile, inoltre, è ben diverso dal copiarlo: Internet Explorer 9 resta ben riconoscibile e con una sua identità.
Ottime sono le prestazioni, infinitamente migliori di Explorer 8, probabilmente migliori anche delle ultime versioni di Chrome, Opera e Firefox. Per maggiori informazioni in merito vi rimando alla panoramica che ho fatto sul mio post di Appunti Digitali.
Un'unica nota dolente. Indovinate un po? Proprio il mio nuovo sito ha mostrato problemi di visualizzazione con Internet Explorer 9. E' la prima volta che mi sono affidato completamente ad un software per realizzare lo stile CSS, evitando di perdere tempo per farlo funzionare correttamente su tutte le versioni di Explorer, Firefox, Opera, Chrome e Safari, ed ecco che non funziona su IE9 che è molto più aderente agli standard di quanto non lo fosse la versione precedente. In attesa di trovare il tempo di investigare meglio il problema, ho risolto momentaneamente con il meta tag di compatibilità che fa funzionare il tutto in modalità Explorer 8 anche sull'ultima versione.
altroSito versione 3.0
Eccomi qua con una nuova versione del mio sito web personale. Il mio ultimo post su questo blog vi ha aggiornato sulla mia situazione professionale e se vogliamo il restyling di queste pagine è frutto della volontà di voler meglio rispecchiare tale situazione nella rete.
Adesso collaboro all'interno di un'organizzazione grazie alla quale mi occupo di consulenza, progettazione, sviluppo e formazione in tutto ciò che concerne lo sviluppo software su piattaforma Microsoft .NET. Ammetto che questa definizione è volutamente oscura visto che molti si chieranno quale è l'organizzazione e quale è il mio ruolo precisamente, ma vi deve bastare al momento. Del resto penso che rispetto alla definizione "The Dark Project" qualche elemento in più ve lo abbia fornito ;-)
Queste nuove attività, in particolare quelle di sviluppo di un progetto interno all'organizzazione, mi hanno permesso di approfondire notevolmente il .NET Framework 4.0 e, in particolare, Windows Workflow Foundation 4, il nuovo motore per la definizione ed esecuzione di workflow di Microsoft. Se siete interessati a questo ambito, vi consiglio caldamente di dargli un'occhiata in quanto penso che ne rimarrete piacevolmente sorpresi. Al riguardo ho anche scritto un articolo introduttivo su DotNetSide, il primo user group del sud italia dedicato al .NET Framework, al quale ne seguiranno altri.
Nonostante questo cambiamento, più di stampo professionale che personale (ammesso che una distinzione simile abbia senso nella vita), il presente sito resterà il mio blog personale nel quale vi terrò aggiornati (spero con maggiore frequenza) anche delle mie avventure personali.
Il sito è stato completamente sviluppato utilizzando ASP.NET MVC 2, tuttavia chi conosce queste API avrà sicuramente notato che rispetto al loro uso canonico, su alcune caratteristiche sono dovuto scendere a patti con il pessimo servizio di hosting che propone Aruba. Noterete, infatti, che le pagine continuano ad avere l'estensione .aspx nonostante le regole di routing di ASP.NET MVC garantiscano il completo disaccoppiamento delle view rispetto alle pagine fisiche deployate su IIS. Beh, andatelo a raccontare ai sistemisti di Aruba e al loro modo di impostare IIS!!! A proposito, conoscete qualche altro servizio di hosting decente che supporti magari il .NET Framework 4.0 e non abbia limitazioni di questo tipo? Se si, fatemelo presente perché alla scadenza di quest'anno ho intenzione di abbandonare Aruba.
altroUn'esperienza straordinaria
Oggi vi descriverò quella che per me è stata un'esperienza straordinaria vissuta nell'ultimo anno e mezzo.
Dovete sapere, infatti, che in questo periodo ho lavorato in Eurosoft, un'azienda che mi ha insegnato veramente moltissimo. Il mio ruolo è cresciuto in pochissimo tempo e sono partito dall'essere un "semplice" sviluppatore .NET senior, al diventare responsabile dello sviluppo software, svolgendo anche mansioni come il recruitment e la formazione per le nuove risorse junior.

Sapete già che nel corso di questo periodo ho dedicato molte delle mie energie all'approfondimento di tutte le tecnologie Microsoft per lo sviluppo di applicazioni di classe enterprise e frutto di tale approfondimento sono state le certificazioni che ho conseguito.

Quello che non sapete e che, in fin dei conti, riveste a mio parere maggiore importanza, è la nascita di tante amicizie che nel corso di questi ultimi 18 mesi hanno sicuramente arricchito la mia persona.

Non so se leggeranno mai questo blog, ma in ogni caso non posso non salutare calorosamente tutte le persone con le quali ho stretto un'amicizia che, spero, non si perda del tempo.

Nel frattempo quello che ho denominato "The Dark Project" ha preso vita. I dettagli non li posso ancora divulgare, ma ben presto potrò dirvi qualcosa di più.
Sto anche lavorando ad un restyling di questo sito, ormai ancorato ad uno stile fatto oltre 4 anni fa (quando il tutto era ancora in PHP) e che, francamente, mi ha un po stancato.
altroThe Dark Project ha inizio
Questa volta l'ho fatta proprio grossa: non mi faccio vivo nel mio blog da oltre tre mesi ormai. Devo ammettere che non è la prima volta che mi metto di fronte alla tastiera per raccontarvi qualcosa che mi è accaduto o che trovo interessante, ma puntualmente qualcuno mi interrompe e/o sopraggiungono pensieri che mi distraggono.
La cosa più importante che voglio trasmettervi oggi è
The Dark Project ha inizio
Ulteriori dettagli seguiranno nel corso dei prossimi mesi, ma vi basti sapere che si tratta di una scelta nella mia vita di portata a dir poco storica
altro