mercoledì 27 agosto 2008
La notizia che Lutz Roeder, creatore di Reflector, non si occuperà più del tool PIU' IMPORTANTE per uno sviluppatore .net (Reflector, appunto) mi dispiace, ma del resto comprendo benissimo che non si può rimanere legati allo sviluppo di uno strumento per troppo tempo, pena una certa "fossilizzazione". Vorrei poter ringraziare pubblicamente Lutz per il lavoro che ha fatto in questi anni, per averci dato uno strumento potente, che ci permette di apprendere e comprendere il funzionamento del Framework .net.
Probabilmente ognuno di noi sarebbe uno sviluppatore meno capace, se non ci fosse stato .net Reflector. Grazie Lutz!
giovedì 24 luglio 2008
Ok, ok... Il buon Andrea Boschin mi ha taggato... e quindi non posso esimermi dal tediarvi con un pò di storia della mia vita "programmativa".
How old were you when you started programming?
A quale età hai cominciato a programmare?
Ho cominciato a programmare a 12 anni. Dopo aver pregato in turco i miei genitori di comprarmi un computer "perchè mi serviva per studiare" (alzino la mano quanti hanno usato questa sporchissima scusa per farsi regalare il computer solo per giocare, esattamente come avevo fatto io), ho ottenuto per natale un Commodore 128.
How did you get started in programming?
Come hai cominciato a programmare?
Lo stimolo, ancora una volta, furono i videogiochi. Da sempre appassionato di video games "da sala", ero un divoratore di Pac-Man, Ghosts'n'Goblins e Space Harrier, per cui volevo emulare le gesta dei programmatori dell'epoca, veri pionieri che facevano stare in 64 miseri Kb delle autentiche perle. Ricordo ancora con nostalgia il racconto dello sviluppo di un videogioco di Andrew Braybrook, su Zzap! (chi se lo ricorda?)
What was your first language?
Qual’è stato il tuo primo linguaggio di programmazione?
Ovviamente il Basic, anzi, il GW-Basic. Ricordo ancora un programma scritto in terza media che calcolava aree e perimetri di tutte le figure geometriche, dati in input i parametri di base della figura.
What was the first real program you wrote?
Qual’è stato il primo programma vero che hai scritto?
Probabilmente un programmino il cui listato era contenuto nel manuale del Commodore 128. Mi sembra di ricordare disegnasse dei cerchi di vari colori sullo schermo.
What languages have you used since you started programming?
Quali linguaggi hai usato da quando hai cominciato a programmare?
Mhhh... troppi per ricordarli tutti... GW-Basic, Logo, Quick-Basic, COBOL, C, C++, VB (dalla versione 1.0), VB.net, C# sono solo alcuni, senza contare quelli accessori (SQL, T-SQL, XML...)
What was your first professional programming gig?
Quando è stato il tuo primo vero lavoro da programmatore?
Ah... bellissima domanda! Ho scritto in Quick Basic e BTrieve (per i più giovani: Btrieve è un ISAM che poteva essere integrato con vari linguaggi) un software per un mio carissimo amico radioamatore per registrare le frequenze radio. Utilizzato tutt'oggi funziona che è un piacere! Il mio primo lavoro "pagato" però (500.000 lire!!) fu un sistema di catalogazione di Fotografie scritto con database Access e VB 5.0.
If you knew then what you know now, would you have started programming?
Con il senno di poi, rifaresti lo stesso il programmatore? Ricominceresti a programmare?
Penso che sviluppare software sia uno dei lavori più belli del mondo, soprattutto per chi, come me, ama creare. Devo però aggiungere anche che non è un lavoro che viene tenuto in considerazione, almeno non nel nostro paese. Un pò di rispetto in più per tutti i "programmatori" (che sono sempre un pò di più di semplici "scrittori di codice") non guasterebbe...
If there is one thing you learned along the way that you would tell new developers, what would it be?
Pensa prima di scrivere! La soluzione migliore è sempre la più semplice...
Se ci fosse una cosa che hai imparato nella tua carriera e che vorresti dire ai giovani programmatori, cosa diresti?
Non scriverti addosso per amore di soluzioni perfette e infinitamente flessibili. Ricorda che una soluzione infinitamente flessibile richiederà tempo infinito per essere implementata... quindi in una parola: concretezza!
What's the most fun you've ever had ... programming?
Qual’è la cosa più divertente che hai programmato?
Ce ne sono tante, ne scelgo due: un Tetris in QB 45 nel 1991, fatto per scommessa con in mio Prof di Informatica; SilverPacMan, scritto in Silverlight 1.1 a distanza di 18 anni dal Tetris, ma che tradisce ancora una volta il mio grande amore per i videogiochi.
Now, let’s tag someone else...
Adesso è l’ora di taggare qualcun’altro...
Andrea Dottor
Marco Trova
mercoledì 23 luglio 2008
Volevo pubblicamente ringraziare il grande Andrea Boschin, che mi ha letteralmente "spiazzato" con un gesto che solo una persona come lui poteva fare. Al CISA 2008, infatti, mi ha regalato "nientepopodimenoche" una Licenza MSDN Premium che include la Team Suite di VS 2008. Ammetto di essere rimasto basito per un pò...visto il valore che ha per noi sviluppatori/ricercatori una licenza di questo tipo.
Grazie di vero cuore, Andrea; farò fruttare questa licenza al meglio!
martedì 22 luglio 2008
Quest'anno ho avuto l'onore di presenziare come relatore alla Conferenza Italiana Sviluppatori Access per presentare i Reporting Services. Sono stato enormemente soddisfatto dell'interesse suscitato dalla sessione che ho presentato, perchè i presenti, sviluppatori molto sensibili alla manipolazione dei dati e delle informazioni, mi hanno subissato di domande. Ringrazio tutti per l'interesse dimostrato nell' argomento e il grandissimo Andrea Boschin che ha sacrificato un pò di tempo della sua sessione per permettermi di rispondere alle domande. Invito tutti i presenti (ed anche i non presenti, ovviamente) a continuare con le domande e le curiosità... sarò felice di rispondere!
venerdì 4 luglio 2008
Se anche a voi, come al sottoscritto, dopo aver installato il Service Pack 1 di Windows Vista, i Reporting Services non funzionano più, ovvero non si riesce più a connettersi nè con il browser, nè con il SQL Server Management Studio, sappiate che seguendo queste indicazioni riuscirete a ripristinare le funzionalità.
In pratica si tratta di riabilitare i permessi di Script sugli Handlers HTTP relativi alla Virtual Directory ReportServer utilizzando la MMC di IIS.
Nella pagina cercate il testo: Problem: Programmatically configuring a report server virtual directory
mercoledì 18 giugno 2008
Con l'arrivo della Beta2 di Silverlight è compresa una delle features da me più attese: la comunicazione full duplex. Una piccola premessa è d'obbligo, anche perchè non tutti possono conoscere le problematiche di una comunicazione full duplex ed è forse anche proficuo fare un confronto con la comunicazione half duplex.
Il paradigma Request/Response, cui tutti siamo abituati, può essere considerato a tutti gli effetti una comunicazione half duplex; essa cioè avviene in un solo senso, dal client al server. Le pagine ASP, i web services, sono tutti esempi di comunicazione half duplex, dove il client effettua una richiesta al server e quest'ultimo fornisce (a volte) una risposta.
Nella maggior parte dei casi, per applicazioni three-tier basate su Web Services, questo approccio è ottimale: l'applicazione server è scalabile, nel senso che una volta fornita la risposta le risorse impiegate per fornirla vengono rilasciate, ed il client è molto semplice; la comunicazione avviene attraverso una serie di metodi il più delle volte incorporati in una classe proxy autogenerata.
Ci sono dei casi, però, in cui questo tipo di comunicazione non è nè consigliabile, nè alle volte fattibile. Si tratta dei casi in cui si desidera che sia il server a comunicare con il client, e non viceversa. Si parla in questo caso anche di Server Push. Le applicazioni che possono avvalersi di una tale tecnologia sono innumerevoli, e vanno dalla semplice chat, all'applicazione che fornisce in tempo reale i dati di una partita di _______ (scegliete voi lo sport!), al gioco multiplayer, a semplici programmi di alerting, a complesse applicazioni di monitoraggio di impianti.
Questa funzionalità di comunicazione, peraltro già presente in prodotti come Flash, è ora incorporata in Silverlight, e basa il suo fondamento sulle solide basi di Windows Communication Foundation. La descrizione di come debba essere implementata una comunicazione full duplex, in cui i dati vengano inviati dal server al client, la potete trovare nella documentazione ufficiale di Silverlight, qui e qui.
Non voglio riportare inutilmente il codice, che potete trovare nell'esempio fornito dalla documentazione, perfettamente funzionante; bensì ho creato una piccola classe Duplex Helper, che agevola la parte più "fastidiosa" della comunicazione duplex di Silverlight, ovvero la gestione degli eventi sul client.
La classe in oggetto espone tre metodi e due eventi:
- OpenChannel(string URL): apre il canale all'URL specificato.
- CloseChannel(): chiude il canale.
- SendMessage(string messageId, string messageBody): invia il messaggio di tipo messageId con messageBody sul canale che deve essere stato aperto in precedenza. La stringa MessageId deve essere fomattata con il namespace del servizio, l'interfaccia che forma il contratto e il metodo che si vuole invocare, mentre non c'è nessuna limitazione per il messageBody.
Gli eventi sono:
- OnOpenChannelCompleted(): sollevato al completamento dell'apertura del canale. Utile per notificarlo all'utente.
- OnOpenChannelError(): sollevato se si verifica un errore durante l'apertura del canale.
- OnSendMessageCompleted(): sollevato al termine dell'invio di un messaggio.
- OnSendMessageError(): sollevato al verificarsi di un errore durante l'invio di un messaggio.
- OnMessageCallBackReceived(): sollevato all'arrivo di un messaggio dal server (server push). Può essere utilizzato per fare parse del messaggio.
Il codice per utilizzare questa classe è il seguente, da collocare in una pagina di un progetto Silverlight:
1: public DuplexClient()
2: {
3: InitializeComponent();
4: // Grab a reference to the UI thread. (Diagnostic purpose)
5: uiThread = SynchronizationContext.Current;
6:
7: _duplexHelper = new DuplexHelper();
8:
9: _duplexHelper.OnMessageCallBackReceived+=new DuplexHelper.MessageCallBackReceivedHandler(_duplexHelper_OnMessageCallBackReceived);
10: _duplexHelper.OnOpenChannelCompleted += new EventHandler(_duplexHelper_OnOpenChannelCompleted);
11: _duplexHelper.OnOpenChannelError += new DuplexHelper.OpenChannelErrorHandler(_duplexHelper_OnOpenChannelError);
12: _duplexHelper.OnSendMessageError += new DuplexHelper.SendMessageErrorHandler(_duplexHelper_OnSendMessageError);
13: //Apro il canale per la comunicazione
14: _duplexHelper.OpenChannel("http://localhost:9000/NorthwindService/Service.svc");
15: }
16:
17: void _duplexHelper_OnSendMessageError(object sender, DuplexCommunicationErrorEventArgs e)
18: {
19: uiThread.Post(WriteText, e.InnerException.Message + Environment.NewLine);
20: }
21:
22: void _duplexHelper_OnOpenChannelError(object sender, DuplexCommunicationErrorEventArgs e)
23: {
24: uiThread.Post(WriteText, e.InnerException.Message + Environment.NewLine);
25: }
26:
27: void _duplexHelper_OnOpenChannelCompleted(object sender, EventArgs e)
28: {
29: uiThread.Post(WriteText, "Channel opened and ready!" + Environment.NewLine);
30: }
31:
32: void _duplexHelper_OnMessageCallBackReceived(object sender, MessageCallBackReceivedEventArgs e)
33: {
34: //qui si può effettuare il parsing del messaggio
35: string text = e.ReceivedMessage.GetBody<string>();
36: uiThread.Post(WriteText, "Message from server: " + text + Environment.NewLine);
37: }
38:
39: private void Button_Click(object sender, RoutedEventArgs e)
40: {
41: //Questo è un esempio di chiamata. Ovviamente l'invio di un messaggio non ha valori di ritorno.
42: string _message = "My Goods";
43: _duplexHelper.SendMessage("Silverlight/IDuplexService/Order",_message);
44: uiThread.Post(WriteText, "Client says: Sent order of " + _message + Environment.NewLine);
45: uiThread.Post(WriteText, "Service will call back with updates" + Environment.NewLine);
46: }
47:
48: void WriteText(object text)
49: {
50: reply.Text += (string)text;
51: }
L'esempio riportato funziona con l'esempio di service presente nella documentazione ufficiale, che vi invito a consultare (MSDN docet!). La classe è "in via di realizzazione", per cui c'è sicuramente spazio per ottimizzazioni e/o aggiunte.
L'utilizzo della comunicazione FullDuplex è comunque da approfondire in termini di scalabilità. Potete trovare un articolo di Dan Wahlin che parla della parte "service" a questo indirizzo. Bisogna infatti capire quante e quali risorse vengano impiegate, soprattutto dal server, per mantenere attiva una simile infrastruttura. Spero di avere l'occasione di sondare in futuro, magari con la versione RTM, l'effettivo impiego di risorse e l'applicabilità di un'architettura così affascinante ed utile.
domenica 15 giugno 2008
Se anche voi come il sottoscritto, state facendo degli esperimenti con Silverlight, probabilmente siete già incappati (o incapperete) nel "problema" della cache delle DLL. L'applicazione Silverlight (.xap , per intenderci) viene scaricata nei Temporary Internet Files, ed è soggetta alle stesse regole di caching. Se state facendo del Debug, quindi, considerate il fatto che se la vostra applicazione Silverlight non rispecchia le ultime modifiche che le avete apportato, questo potrebbe dipendere dal fatto che essa è stata messa in cache e che quindi non verrà più scaricata fino a che la cache non scadrà. Per risolvere la cosa, rimuovete il file .xap corrispondente alla vostra applicazione dai Temporary Internet Files.
martedì 29 aprile 2008
Una delle cose più interessanti dell'infrastruttura WSUS (Windows Server Update Services) e WUA (Windows Update Agent), è data dalla possibilità di automatizzare molte attività dell'update agent per ricercare, scaricare ed installare gli update automatici pubblicati in un server WSUS. Ovviamente il client deve essere configurato correttamente e puntare ad un server WSUS anch'esso adeguatamente configurato e nel quale siano stati pubblicati degli "updates".
L'impiego di C# (o VB.net) per automatizzare la procedura, avviene previa creazione dell'assembly di interop con la libreria WUApiLib. Dopo averla referenziata nel nostro progetto avremo a disposizione il Namespace WUApiLib, che contiene molti oggetti utili al nostro scopo:
- UpdateSession: rappresenta una sessione di update. Deve sempre essere creato e da esso vengono generati gli altri oggetti.
- UpdateSearcher: oggetto per effettuare ricerche di updates sul server WSUS
- UpdateDownloader: oggetto utilizzato per scaricare gli updates. Lo scaricamento degli updates avviene tramite il servizio BITS (Background Intelligent Transfer Service). L'impiego di questo servizio ci permette di limitare la banda consumata dallo scaricamento, riprendere gli scaricamenti interrotti e molto altro.
- UpdateInstaller: oggetto per avviare l'installazione degli updates. Nella maggior parte dei casi questi updates sono di tipo "silent", ovvero non richiedono intervento dell'utente
La creazione di una sessione e la ricerca potrebbero avvenire così:
1: private UpdateSession _session;
2: _session = new UpdateSession();
3: UpdateSearcher _updateSearcher = (UpdateSearcher)_session.CreateUpdateSearcher();
4: ISearchResult _searchResult = _updateSearcher.Search("IsAssigned=1 and IsHidden=0 and IsInstalled=0 and Type='Software'");
Dopodichè, se si trovano degli update si può scandire la collection ottenuta in questo modo:
1: foreach (IUpdate _update in _searchResult.Updates)
2: {
3: Console.WriteLine(string.format("{0} - {1}",_update.Title,_update.Description);
4: }
Infine, selezionati gli updates da scaricare, si può avviare lo scaricamento mediante l'oggetto UpdateDownloader:
1: UpdateDownloader _downloader = _session.CreateUpdateDownloader();
2: _downloader.Updates.Add(_update);
3: IDownloadResult _downloadResult = _downloader.Download();
4:
5: UpdateInstaller _installer = (UpdateInstaller)_session.CreateUpdateInstaller();
6:
7: if (_update.IsDownloaded)
8: _installer.Install(_update);
Si può vedere come tutto dipenda dall'oggetto session. Ovviamente ognuno degli oggetti introdotti è ricchissimo di proprietà e di metodi, per cui la cosa migliore è quella di approfondirne lo studio. Un buon punto di partenza è:
http://msdn2.microsoft.com/en-us/library/aa387102(VS.85).aspx. Buon update!
mercoledì 23 aprile 2008
Stamattina ho odiato Visual Studio. Per me è strano, visto che lo considero strumento principe per lo sviluppo, ma tant'è.
Ecco spiegato il problema: i controlli relativi ai report RDLC sono scomparsi dalla toolbox; anzi, sono diventati tutte delle textbox. Niente più grafici, matrix, Tables, Liste... solo textboxes! Sono impazzito a resettare la toolbox, inserire i componenti, toglierli, fare il clean della soluzione... tutto inutile. Mi sono però imbattuto in una dritta, in un forum, che diceva di cancellare i files: toolbox.tbd, toolbox_reset.tbd, toolboxIndex.tbd, toolboxIndex_reset.tbd dalla directory "%USERPROFILE%\Local Settings\Application Data\Microsoft\VisualStudio\8.0" mentre VS2005 era chiuso. Che ci crediate o no, ho risolto il problema, assieme a quello che quasi tutti incontrano, ovvero le icone "scombinate" dei vari controlli della textbox.
Spero questo possa essere d' aiuto a chi come il sottoscritto, già meditava di reinstallare VS2005!!
giovedì 20 marzo 2008
Spesso mi imbatto in soluzioni software che non fanno uso della cache (in qualunque sua forma). Possono essere soluzioni Client-Server, Web, Multi Tier o anche semplici servizi. Abusare del caching è sempre sbagliato, ma è altrettanto sbagliato fare finta che la possibilità di impiegarla (con oculatezza) non esista. Sembrerà un discorso banale, ma se un dato si trova sul disco, alla meglio il tempo di accesso si aggira sull'ordine di millisecondi perchè fondamentalmente si basa sull'impiego di tecnologie elettromeccaniche per fornire esattamente il dato che richiediamo.
Quando invece accediamo alla memoria, i tempi di accesso sono dell'ordine dei nanosecondi. Una bella differenza. Questo ovviamente non significa che si debba cachare tutto in modo indiscriminato, ma se la vostra applicazione si basa su alcuni dati piuttosto "stabili", che possono essere mantenuti in memoria per essere consultati velocemente, considerate sempre l'opzione del caching.
Se i dati si trovano in un database, magari ad accesso concorrente, considerate che le query che vengono fatte per reperire dati "cachabili" intralceranno tutte le altre query che vengono fatte e causeranno un aumento di pressione sul database che può essere ridotto con grande soddisfazione per tutti gli utenti del sistema.
Concludo ribadendo che il caching è una tecnica molto utile, può essere impiegata dove si renda necessario, ma non se ne deve abusare mai.