Technology Experience
Software

In fondo mi serve un GPS Logger

Il prodotto segnalato da Lorenzo non è davvero niente male, soprattutto per chi come me ogni tanto ha paura di perdersi nei boschi. L’unico difetto è che costa davvero troppo. Alla fin fine si tratta di un GPS Receiver + Logger, un device che quando lo si accende comincia a registrare su una propria memoria la posizione ogni 15 secondi. Lo scopo è quello di produrre un file .log da poter riversare su un PC Desktop e vedere il percorso su [Google|Virtual]Earth ed altri software simili. Il prezzo è 275 dollari americani, più spese di spedizione. La cosa carina è che questo aggeggio rileva e memorizza anche la temperatura durante il tragitto. L’altra cosa carina è che con 2 batterie AAA dura un mese.

Però ci sono altre soluzioni più economiche, ma più grezze. Io personalmente un palmare Windows Mobile ce l’ho già, e ho anche un ricevitore GPS. Mi basterebbe un software diverso da Tom Tom, un banale e semplice GPS Logger, dopotutto, che possa scrivere su SD un file di log da poter esportare e manipolare con qualche strumento esterno. L’unico dubbio è la longevità del palmare, ma sono convinto che mettere il display in stand-by possa servire ad allungare la durata. Se si va in automobile, 4 ore sono sufficienti, magari per una giornata di trekking no.

Ho trovato questo Franson GpsGate, costa 49,99 dollari e non è davvero niente male.

Technorati Tags:    

Send to Kindle
My personal life

E voi…dov’eravate?

6 anni fa, l’11 Settembre 2001, intendo ovviamente dire.

Io lavoravo già in proprio come consulente. Ero in piazza Lima, in un ufficio assieme ad un personaggio della politica milanese di centro-sinistra (MT), che mi aveva presentato il mio ex-titolare, che ringrazio tuttora per avermi pagato lo stipendio per diversi mesi. Quel pomeriggio…non ricordo esattamente cosa stavo facendo…probabilmente qualche sito ASP (ebbene sì) e chattavo con ICQ con una mia amica in Sardegna, Mary, che ho anche oggi tra i miei contatti Messenger. All’epoca avevo una meravigliosa abitudine: quella di partire da casa mia alle 6:30, riuscire a parcheggiare in corso Buenos Aires a Milano alle 7:15, lavorare e poi tornare a casa verso metà pomeriggio. Quando la prima delle due torri gemelle crollò io ero per strada, perchè con la Rete non si riusciva più a lavorare da un bel pezzo, dato l’intasamento dei mezzi di comunicazione. Quando arrivai a casa, seguii minuto per minuto i fatti davanti alla TV: che giornata!

E voi…dov’eravate? Cosa stavate facendo?

Send to Kindle
IV del Venerdì

[IV] del Venerdì (16)

Tutte le volte che ci lascia un personaggio pubblico di un certo spessore, nazionale o mondiale che sia, abbiamo l’impressione che non capiterà mai più in futuro di avere un personaggio della stessa fattura. In due soli giorni abbiamo perso Gigi Sabani, imitatore/presentatore/comico italiano, e Luciano Pavarotti, che invece di presentazioni non ha bisogno. Come ho detto qualche giorno fa, il primo non suscitava la mia simpatica e, se devo dirlo, nemmeno Pavarotti. Ma è un mio punto di vista assolutamente personale – e soprattutto non tiene assolutamente conto delle loro capacità artistica, quanto piuttosto della simpatia che suscitavano in me quando li vedevo in TV. Ma è innegabile che abbiano lasciato il loro fottuto segno, in Italia e nel Mondo.

E, bisogna dirlo, ci sarà per forza in futuro un altro qualcuno capace di eguagliare il loro valore. In passato sono scomparsi altri illustri personaggi…penso ad Albert Einstein, ad Enzo Ferrari, a Sandro Pertini, a Versace, a Marcello Mastroianni, a Massimo Troisi. Tutti uomini, tutti personaggi che l’Italia, ed in alcuni casi il mondo, ha pianto. Ma dobbiamo credere che un giorno, da qualche parte, arriverà qualcun’altro capace di portare avanti il made-in-Italy così come hanno fatto loro. Di meno, di più, non importa. Magari qualcuno è già tra noi sotto forma di bambino o bambina che domani incroceremo al supermercato o sulla metropolitana. Certi nomi entrano nella leggenda, ma abbiamo il dovere morale di guardare avanti. Sono pronto a scommettere che quando se ne andò Caruso, molti dissero: “Non ci sarà più alcun tenore come lui!“: poi arrivò Pavarotti, e la Storia è ripartita da dove si era interrotta.

La Storia si ripete, e questo non vale solo per le guerre, ma anche per le cose belle che l’umanità ci regala, comprese le persone e quello che loro rappresentano. Sapete dov’è il difficile?: riconoscerle. Spesso ho sentito paragoni tra Valentino Rossi e Giacomo Agostini: c’è chi preferisce l’uno e chi l’altro. Si sentono paragoni tra Schumacher e Senna, tra Bugno e Coppi, tra X e Y: spesso si tende a privilegiare il passato, perchè fondamentalmente non si vuole credere che un Mito Vero possa diventare sorpassato. Il Mito Vero – quello che c’era e adesso non c’è più – è immortale, Lui sarà sempre il migliore. Fare un confronto fa sempre paura, non è vero? Mi piace pensare che non sia così. L’Attuale può battere il Passato. Voglio credere che sia così e devo esserlo. Se non lo fosse, risulterebbe che il mondo è condannato a deteriorarsi, a perdere uno ad uno i suoi Miti viventi e a non averne più. Che tristezza. Il mito entra a far parte di un universo di intoccabili, di pietre miliari della cultura mondiale, e non dobbiamo per forza fare paragoni con i personaggi di oggi.

Salutiamo Gigi Sabani e Luciano Pavarotti. Hanno una cosa in comune: ci hanno lasciato durante la stessa settimana. Salutiamoli e ricordiamoli per sempre, se lo meritano per quello che hanno fatto. Ma guardiamo avanti, e siamo pronti ad accogliere a braccia aperte ciò che il Destino, e la Storia, hanno in serbo per noi.

Ciao Gigi, Ciao Luciano!

Send to Kindle
.NET World

Domain Model, NHibernate (con lazy load = true) e WPF

Prevedo la stesura di un post piuttosto lungo. Cominciamo dagli ingredienti:

  1. Un’entità sul nostro domain model (Artista) definita in un assembly (DomainModel)
  2. Un assembly (DataAccessLayer) con un po’ di classi che, tramite NHibernate, si occupano di persistere le entità definite nell’assembly al punto (1) su database (SQL Server)
  3. Un altro assembly contenente un progetto WPF – dettagli più sotto

Tutto questo per garantire la separazione delle componenti software di un progetto: domain-model, dal e UI. Almeno queste. Non voglio fare il saccente, ma credo che la difficoltà sia Alta, ed i tempi di preparazione lunghi. E penso anche che darò un sacco di cose per scontate, e ciò non va bene. Pazienza. Mi piacerebbe estrapolare in un piccolo progetto la problematica che ho incontrato: e lo farò.

Introduzione
Supponiamo di avere una classe Artista che espone un certo numero di proprietà pubbliche. Tale classe fa parte del nostro domain-model. Tale classe è anche mappata, attraverso NHibernate, su un database SQL Server. Immaginatevi quindi proprietà come Cognome, Nome, DataNascita, Sesso, Disponibilita, tutte mappate su una tabella Anagrafica con i campi con lo stesso nome della proprietà, per semplicità.

Lo scopo è quello di far vivere un’istanza di Artista su una Window di WPF. Con “vivere” intendo l’intero ciclo di vita di un’istanza: creazione di un nuovo artista, inserimento valori, salvataggio. Oppure rilettura di una precedente istanza, modifica dei valori e salvataggio. Ignoriamo tutte le proprietà della classe Artista e teniamo solo Cognome.

Cominciamo.

La Window di WPF
Lo XAML è il seguente:

<Window x:Class="VivendoByte.CastingManager.TestWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Casting Manager" Height="300" Width="400" Background="LightCyan"> <TextBox x:Name="CognomeTextBox" Height="20" Margin="8" Text="{Binding Path=Cognome}" /> </Window>

L’unico elemento nella Window è una TextBox, che è bindata alla proprietà Cognome di un’ipotetica istanza di Artista. Diamo un’occhiata al code-behind di questa classe:

public partial class TestWindow : System.Windows.Window { Artista _artista; public TestWindow() { InitializeComponent(); _artista = new Artista("Liborio", "Damiani"); this.DataContext = _artista; } }

La Window ha un field privato _artista, che vive all’interno della Window stessa. Nel costruttore creo l’istanza, dando un nome ed un cognome fittizi. Poi dico che il DataContext della Window è l’istanza appena creata. Quando la Window appare su schermo, il risultato è il seguente:

La TextBox mostra il cognome. Adesso arriva il bello: passiamo ad usare NHibernate.

Utilizzare NHibernate con WPF
Senza scendere troppo nel dettaglio, usiamo NHibernate per caricare da db un’istanza precedentemente persistita. Nel costruttore, invece di fare new Artista(), diciamo ad un ipotetico data provider (ipotetico per voi, ma non per me) di caricare un’istanza: ad esempio, quella con ID = 11. Vediamo come modifichiamo il code-behind:

1 public partial class TestWindow : System.Windows.Window 2 { 3 Artista _artista; 4 DataProvider<Artista> _provider; 5 6 public TestWindow() 7 { 8 InitializeComponent(); 9 _provider = new DataProvider<Artista>(); 10 _artista = _provider.LoadObject(11); 11 this.DataContext = _artista; 12 } 13 }

Abbiamo un data provider generico, che viene istanziato nel costruttore. L’istanza di Artista viene caricata da database, prelevando quella con ID = 11. Infine viene impostato il DataContext della Window.

Qui abbiamo un grave problema. Se NHibernate è impostato per caricare le istanze con lazy=true, otteniamo un’exception, mentre se decidiamo di non utilizzare il lazy load tutto andrà a buon fine. Il tipo di oggetto ritornato dalla LoadObject(11) qui sopra dipende a seconda di come impostiamo il lazy:

Se Lazy Load = true, _artista.GetType() è CProxyTypeVivendoByte_CastingManager_DomainModelArtistaDomainModel_NHibernate_ProxyINHibernateProxy1

Se Lazy Load = false, _artista.GetType() è VivendoByte.CastingManager.DomainModel.Artista

Se utilizziamo il lazy load, quindi, NHibernate ci ritorna un tipo di oggetto che non è quello che ci aspettiamo per il data-binding. Ricordo in breve che il lazy load di NHibernate permette il caricamento ritardato di un’istanza di un oggetto – caricamento che avviene realmente solo nel momento in cui abbiamo effettivamente bisogno di utilizzarlo. Per esempio, se facciamo eseguire dal debugger la linea (10), vedremo come le proprietà non siano valorizzate come ci si aspetta, ma esse continuano a valore null; stessa cosa per i membri privati. In sostanza, il tipo ritornato con lazy=true non è nient’altro che una sorta di wrapper attorno all’istanza di Artista, un wrapper che si occupa di andare a leggere l’istanza tramite la session di NHibernate che deve rimanere aperta.
Il tipo di caricamento va impostato nel file di mapping di NHibernate, per ciascuna classe mappata:

<class name="Artista" table="Anagrafica" lazy="false"> ... ... </class>

Comunque, nel momento in cui tentiamo di impostare il DataContext della Window con un tipo non corretto, otteniamo una System.Reflection.AmbiguousMatchException. Un errore che sinceramente non sono riuscito a decifrare davvero fino in fondo. Ho litigato anche qui per un sacco di tempo, convintissimo che il problema fosse un mio non corretto utilizzo del DataContext di WPF, ma poi alla fin fine ho dovuto concentrarmi sul comportamento di NHibernate. E l’inghippo è saltato fuori, anche grazie all’aiuto di un amico.

Conclusione
Sono arrivato fin troppo velocemente alla fine. Credo ci siano ancora un milione di cose da dire. Note varie: la classe Artista di questo esempio implementa l’interfaccia INotifyPropertyChanged, per poter gestire correttamente il meccanismo di data-binding. Non appena reimposto il DataContext della Window, quindi, tutti i controlli riflettono il cambiamento, sia che l’istanza di Artista venga caricata da database oppure che venga creata direttamente una nuova istanza.

Technorati Tags:      

Send to Kindle
Software

Se vi esplode Omea Reader, settate una regola di expiration

In Omea Reader ho sottoscritto un bel po’ di feeds, dal Muro di UGIdotNET a tutti gli altri amici di UGI (non faccio i nomi perchè sono un miliardo), dai vari blog delle altre community e developer italiani o stranieri che hanno il blog “in proprio” come me. Il numero di post da leggere questa mattina ha sfondato quota 6.000. Ho notato, per esempio, che il feed del blog di MSDN arrivava indietro nel tempo fino a marzo 2007: stessa cosa per tutti gli altri. Evidentemente, mi sono detto, è il giorno in cui ho installato Omea Reader sul notebook, o – meglio ancora – il giorno in cui ho sottoscritto il feed.

C’è un modo per fare in modo che Omea Reader cancelli automaticamente i post più vecchi, tenendo disponibili solo quelli, per esempio, degli ultimi 2 mesi? Certo che sì. Non chiedetemi però come far funzionare le “Auto Expiration Rules“: ho seguito step-by-step le indicazioni dell’help in linea, ma non c’è stato verso di farle funzionare! Per chi fosse interessato, le Auto Expiration Rules possono essere impostate da Tools –> Options –> Newsgroups, in fondo c’è una parte dedicata a questo: in bocca al lupo!

Per chi invece vuole risolvere il problema in modo rapido, faccia questo:

  1. Andare su Tools –> Manage Rules –> Actions Rules
  2. Dare un nome alla rule, ad esempio “Vecchie risorse”
  3. Cliccare su “Add Condition…”. Dal folder “RSS Conditions” selezionare “Post’s feed is in the folder”
  4. Cliccare su Ok. Cliccare su “folder” e spuntare uno alla volta i folder che avete impostato in Omea Reader (io ho Community, Developers, Friends e Technologies). Cliccare su Ok.
  5. Cliccare su “Add Exceptions”. Dal folder “Temporal Conditions” selezionare “Receveid within or dated by time span”
  6. Cliccare su Ok. Cliccare su “time span”. Spuntare “For last” ed impostare il periodo di tempo all’interno del quale volete tenere i post (io ho messo 2 mesi, ad esempio). Cliccare su Ok.
  7. Cliccare su “Add Action”. Spuntare sia “Delete resource” e “Delete resource permanently”. Cliccare su Ok.
  8. Cliccare su Ok per confermare la rule così come l’avete impostata. Potete comunque modificarla in seguito se non vi piace.

Tutto qua. Per lanciarla, andare sul menù Actions –> Apply Rules. La vostra rule apparirà nell’elenco: spuntatela ed indicate – se volete – anche l’insieme delle risorse su cui volete applicarla (tutti i feeds o solo uno in particolare).

Technorati Tags:  

Send to Kindle
.NET World

Usare un DateTimeConverter nei progetti WPF

Eventuali imprecisioni sono dovute all’ascolto, durante la stesura del post, di un concerto del Liga.
Chiedo scusa: aiutatemi con i vostri commenti. 🙂

La classe DateTimeConverter è definita nel namespace System.ComponentModel nell’assembly System.dll. Il primo pensiero che ho avuto quando ho scoperto la presenza di questa classe – con questo nome – è stato: cavolo, posso metterla nelle risorse di una Window e sfruttarla nel meccanismo di data-binding tra un tipo DateTime ed un semplice controllo come la TextBox.

Supponiamo di avere una Window semplice definita così:

1 <Window x:Class="StudyWPF.DataBindingWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:cnv="clr-namespace:System.ComponentModel;assembly=System" 5 Title="StudyWPF" Height="300" Width="300"> 6 <Window.Resources> 7 <cnv:DateTimeConverter x:Key="cnvDateTime" /> 8 </Window.Resources> 9 </Window>

Ho aggiunto un riferimento al namespace System.ComponentModel dentro l’assembly System.dll con i metodi di cui abbiamo parlato più o meno tutti in passato. Due note. Primo: occhio, la “a” di “assembly” alla riga (4) nel mapping del namespace deve essere obbligatoriamente minuscola. Secondo: il riferimento all’assembly, sempre alla riga (4) non deve avere estensione. Ogni volta ci perso mezz’ora, spero che scrivendolo questo tempo diminuisca. 🙂

Fatto questo, ho definito fra le risorse un’istanza di DateTimeConverter, usando come key la stringa “cnvDateTime”. Se provate a compilare, non avrete alcun errore. L’istanza del converter viene creata. Ma se provate ad usarla in un qualche data-binding, fallirà. Ve lo dimostro, sperando di non dire qualche stupidaggine (in tal caso, leggere il prologo all’inizio). Guardate il seguente XAML:

<Window x:Class="StudyWPF.DataBindingWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:StudyWPF" xmlns:cnv="clr-namespace:System.ComponentModel;assembly=System" Title="StudyWPF" Height="300" Width="300" DataContext="{DynamicResource player}"> <Window.Resources> <s:HockeyPlayer x:Key="player" /> <cnv:DateTimeConverter x:Key="cnvDateTime" /> </Window.Resources> <TextBox Text="{Binding Path=Data}" /> </Window>

E’ una sorta di evoluzione di quello di prima. Fra le risorse c’è ancora il DateTimeConverter di prima. Ho aggiunto un nuovo namespace ed una nuova risorsa, per avere a disposizione un oggetto di business che mi vada ad esporre una proprietà pubblica di tipo DateTime. Tale oggetto è uno HockeyPlayer (ve lo ricordate?) e mi espone una semplice proprietà Data. Ho impostato il DataContext della Window sulla risorsa player. In questo modo alla Window posso aggiungere una TextBox bindata all’oggetto secondo il Path=Data. Cosa mostra la TextBox? E’ presto detto…

Ovvero…una semplice ToString() sull’oggetto definita nella risorsa, che giustamente ha i valori di default per un’istanza di DateTime. Supponiamo adesso di voler sfruttare il converter: modifichiamo la definizione del data-binding sulla TextBox:

<TextBox Margin="4" Text="{Binding Path=Data, Converter={StaticResource cnvDateTime}}" />

Al data-binding ho detto di usare un converter, e nello specifico quello definito dalla risorsa. Il codice non compila: il messaggio di errore è:

Cannot convert the value in attribute ‘Converter’ to object of type ‘System.Windows.Data.IValueConverter’. Object of type ‘System.ComponentModel.DateTimeConverter’ cannot be converted to type ‘System.Windows.Data.IValueConverter’.  Error at object ‘System.Windows.Data.Binding’ in markup file ‘StudyWPF;component/databindingwindow.xaml’ Line 15 Position 23.

Il messaggio è chiaro. WPF si aspetta converter che implementino l’interfaccia IValueConverter del namespace System.Windows.Data. La classe DateTimeConverter che abbiamo usato noi non fa nulla di tutto questo: grazie ad un giro con Reflector, vedo che deriva da TypeConverter, e non c’entra nulla.

Le soluzioni sono almeno due: o vi scrivete voi un DateTimeConverter adatto a funzionare con WPF (operazione semplicissima, al punto che è la strada che ho seguito), oppure date un’occhiata a questo progetto su CodeProject.com, che oltre al DateTimeConverter vi dà altri converter che potrebbero esservi utili in altri contesti.

Technorati Tags:   

Send to Kindle
Software

Il lato desktop non morirà MAI (*)

Ho sempre sentito dire, da un po’ di tempo a questa parte, che un giorno il desktop morirà. Personaggi più o meno illustri ogni tanto saltano fuori a turno e ci vengono a dire che un giorno tutti i nostri PC saranno sulla Grande Rete, che i sistemi operativi verranno caricati dalla Rete, che useremo applicazioni via http on-demand, eccetera eccetera eccetera. Ci dicono che il “lato desktop” del nostro computer è destinato a morire. Non ho mai creduto a queste voci. Anzi, sono assolutamente convinto che con il passare del tempo il desktop diventi sempre più forte e, come ho avuto modo di dire in passato, sia l’unica vera parte che cresca davvero.

Ci sono cose che faranno in modo che il “lato desktop” non morirà mai. Eccole.

  1. Non tutte le categorie di applicazioni sono adatte ad essere caricate dalla Rete. Ne dico una a caso: i videogiochi. E’ perfettamente normale che un videogioco usi la Rete per il multiplayer, per scaricare gli aggiornamenti o per uploadare gli high-scores. Ma l’idea di avere un terminale ultra-stupido che caricare il gioco dalla Rete è folle: oggi ci sono videogiochi che stanno su un certo numero di DVD, non è umanamente accettabile che tutte le volte debba scaricarli. Per poter giocare ad un gioco decente, ho bisogno di un’infrastruttura hw & sw lato client come si deve e gestita opportunamente: ciò significa hardware, sistema operativo, DirectX (nel caso di Windows), periferiche di gioco. Tutto lato client, è inevitabile, questo.
  2. Non sempre ho la Rete sottomano. Ok, questo potrebbe cambiare. Giriamo la frase: Non sempre voglio avere la Rete sottomano. Ci sono files personali e segreti, database con informazioni riservate, che non si vuole per definizione mettere su qualche server Web da qualche parte nel mondo. Certi files li vogliamo nei NOSTRI documenti, sul nostro disco fisso, in un posto fisico che abbiamo sotto gli occhi.
  3. La Rete può crollare. E’ inutile inventare nuovi protocolli più sicuri e più affidabili. Quando un router si spegne o si guasta, la Rete non funziona. Dobbiamo pensare a questo. Se ipotizzassimo un OS che si carica dalla Rete, con Word che si carica dalla Rete e via via tutti anche gli altri software…sarebbe un azzardo, un rischio che non possiamo correre. Non è accettabile non riuscire a bootare il PC solo perchè il server Web non è raggiungibile. Dobbiamo avere un’infrastruttura software lato client, che è quella che abbiamo oggi…che si chiami MacOS o Windows.
  4. Gli applicativi Web non sono nemmeno lontanamente paragonabili a quelli desktop. Solo oggi con Ajax le cose stanno cambiando, ma ci sono comunque problemi di compatibilità – non ne parlo per manifesta incapacità di farlo – e di prestazioni. Gli applicativi desktop in alcuni casi hanno bisogno di potenza di calcolo (rendering audio e video, insieme a tanti altri, tra cui…videogiochi), hanno bisogno di accedere a periferiche locali (stampanti in primo luogo), possono offrire contenuti multimediali (filmati): ok, si può fare anche via Web, ma solo tramite streaming (con tutti i vantaggi e svantaggi), e comunque tenendo conto del punto (3).
  5. Mantenere separati desktop e Web apre un miliardo di possibilità. Il Web mette a disposizione strumenti potentissimi, che il desktop non può raggiungere per definizione. Ma io voglio sfruttare blog/forum/newsgroup/feeds anche sul client, dove ho strumenti adatti. E’ l’interazione fra Web e Desktop che è vincente, non l’uno senza l’altro. Non avrebbe senso che esista solo il Web – si perderebbe un sacco di roba. Non avrebbe senso che esista solo il Desktop – torneremmo indietro agli anni 70/80.
  6. Altri motivi: http://www.visionpost.it/index.asp?C=2&I=2367

(*) : questa dichiarazione è da consumarsi preferibilmente entro il 31/12/2010. Grazie.

Technorati Tags:     

Send to Kindle
My personal life

Non mi era granchè simpatico, però mi dispiace

Mi riferisco alla scomparsa di Gigi Sabani, che è morto ieri sera alle 22:30. Non so dare una motivazione per la mia antipatia nei suoi confronti – probabilmente è una cosa immotivata, o una cosa “a pelle”. Però mi dispiace, perchè comunque Gigi Sabani è stato un personaggio che ha segnato la nostra televisione con le sue imitazioni e per i programmi televisivi che ha presentato. E la cosa che mi dispiace è che era davvero giovane: rimanere uccisi da un infarto a 54 anni fa davvero pensare. Mi dispiace. Ciao.

Send to Kindle