Il questi giorni nel mainfeed di UgiDotNet è apparsa una notizia davvero brutta, sottolineata con poche righe da Alessandro nel suo blog. Si tratta del cambi della politica di licensing delle libreria grafiche prodotte dalla divelements, che personalmente uso da un bel po' non essendo mai abbastanza grato all'autore del software. La licenza che dapprima era free per chi realizzava software free (e questo mi ha spinto ad usarle per IMHO), da alcuni giorni è esclusivamente a pagamento.

Una brutta notizia merita indagine, soprattutto se la libreria in questione è alla base del software freeware che da più di un anno sto sviluppando. Per questo mi sono preoccupato di scrivere a Tim Dawson per chiarire la mia posizione nei confronti della divelements nel futuro. Tim mi ha cortesemente risposto quanto segue:

1) E' assolutamente confermato il cambio di politica. Tutto va naturalmente attribuito a qualche furbastro che ha interpretato in modo "elastico" la concessione che l'autore ha fatto alla community del software libero, causando un danno all'azienda che non ha visto il necessario ritorno economico. Certo è opinabile che la nuova politica probabilmente non cambierà i furbastri, tuttavia è comprensibile la scelta che è stata fatta.

2) Scordatevi che Tim faccia qualche eccezione: con un po' di faccia tosta gli ho chiesto se mi rilasciava una autorizzazione ad usare le librerie per IMHO dato l'esplicita natura free del mio software. La risposta (come mi aspettavo) è stata "picche", anche se molto generosamente mi ha offerto un consistente sconto, che purtroppo non mi ha lo stesso consentito di provvedere all'acquisto

3) Le librerie che fossero state scaricate prima del cambio di licenza mantengono la natura di free4free. Sarà perciò possibile distribuire software gratuiti basati sulle librerie, a patto che non si ridistribuiscano le librerie acquisite con tale licenza. Questo mi aveva posto qualche perplessità, ma mi è stato confermato. In sostanza si può realizzare e distribuire un software free con le divelements, e gli assembly delle stesse possono essere distribuiti con il software, ma non si possono distribuire i file zip che sono stati scaricati (e che contengono il contratto di licenza).

Mi trovo ora a dover affrontare una difficile decisione. Lo sviluppo di IMHO 2.0 ormai era partito adottando le divelements come base per la GUI, e ormai ero quasi in procinto di rilasciare qualche screenshot di preview, tuttavia mi corre l'obbligo di valutare l'abbandono di queste librerie. In questi giorni farò qualche test sul framework 2.0 per capire se gli assembly di cui dispongo ora sono compatibili con la nuova release, e poi deciderò se mantenere questo legame, sperando magari che i contributi in denaro siano tali da consentirmi l'acquisto. (Se considerate che in un anno mi sono arrivati solamente 20$ da un solo donatore, capirete bene che questo non succederà mai...)

Voglio chiudere questo post con un consiglio che mi sento di dare a chi sviluppa software WinForms. Comprate le divelements! Sono davvero le migliori librerie che io abbia mai utilizzato (in ufficio ne uso un'altra serie e non nemmeno paragonabili). La parte migliore non è nella bellezza dei componenti, ma soprattutto nel pregio del design e nella affidabilità impressionante.

powered by IMHO 1.2


Non ho mai sentito parlare su UgiDotNet di markers interfaces, non so se dipenda dal fatto che vi sono iscritto da relativamente poco tempo, o se proprio l'argomento non è mai stato toccato. Stasera, durante una sessione di sviluppo di IMHO 2.0 mi sono trovato di fronte all'esigenza di usarle per risolvere con eleganza un problema che mi si è presentato, perciò ho deciso di proporvi in questo breve post qualche spezzone di codice per illustrarvene l'utilità.

Innanzitutto vediamo di spiegare in due parole che cosa intendo quando parlo di markers interfaces. Chiunque abbia un po' di dimestichezza con la programmazione ad oggetti sa bene cosa sia un'interfaccia. Tipicamente nei libri viene definita come un contratto che stabilisce quali metodi dovranno contenere le classi che la implementano. In C#, e genericamente nel framework .NET una classe può implementare più di una interfaccia e questo permette di realizzare il polimorfismo delle classi. Non voglio ora dilungarmi in esempi in merito, ma darò per scontato che l'argomento sia ormai ben conosciuto. Ora vi pongo una domanda: cosa succede se dichiaro una interfaccia senza alcun metodo? Semplicemente nulla. Il compilatore non solleverà nemmeno uno warning per farci notare la bizzarria. Di primo acchito si potrebbe dire che una interfaccia senza metodi esposti non serve veramente a nulla, se non che, andando a spulciare l'SDK del framework si scoprirà che di interfacce di questo tipo ve ne sono e anche parecchie. Provate ad esempio a vedere la IReadOnlySessionState. Tale interfaccia è definita una marker interface e verrà implementata dalla classe che il compilatore crea quando compila una pagina aspx, se nella direttiva Page viene specificato EnableSessionState="ReadOnly". Questo è un modo rapido ed elegante di trasformare una proprietà in un comportamento. Usando un marker, nel codice si potrà fare uso dell'operatore "is" per verificare se la classe implementa l'interfaccia ed agire di conseguanza.

Ma visto che un esempio vale mille parole, eccovi come ho impiegato io una marker interface. Uno dei problemi tipici della programmazione ad oggetti è il mapping tra il mondo relazionale e quello oop. In IMHO 2.0 ho deciso di non adottare un framework di persistenza che si occupasse anche di questa problematica perchè in realtà non posso direche ne esistano di veramente maturi e per una questione di licenze nemmeno di praticamente usabili nel mio caso. Perciò mi sono "arrangiato" implementando un po' di patterns. Innanzitutto ho creato una Factory cui passo il tipo di oggetto da create è il DataReader da cui attingere:

public static ImhoObject Create(
    Type type,
    IDataReader reader)
{
    
if (type==typeof(User))
        
return CreateUser(reader);
    
else if (type==typeof(Role))
        
return CreateRole(reader);

    
throw new ApplicationException("Unknown type");
}

private static User CreateUser( IDataReader reader )
{
    
if ( reader.Read() )
    {
        User user = newUser();
 
        // omissis: popolo l'oggetto con il reader...

        
return user;
    }

    
return new UnknownUser();
}
 
Questo metodo è stato creato per poter estrarre da un reader un singolo oggetto. In questo modo è possibile riutilizzarlo sia nel caso di una lettura singola, sia nel caso di un reader contenente molti oggetti. Analizzando per bene il codice si vede anche che ho implementato il pattern SpeciaCase infatti nel caso in cui il reader non contenga alcun oggetto restituisco un'istanza di UnknownUser, una classe che eredita da User e che rappresenta il caso in cui un utente non esiste. A questo punto mi sono trovato nella necessità di creare un metodo che dato un reader lo scandisca da cima a fondo e restituisca un array di oggetti estratti da esso. Il problema risiedeva nel fatto che creando tale metodo, in modo che facesse uso al suo interno del metodo Create(), mi trovavo nella necessità di testare l'oggetto restituito e nel caso in cui esso fosse UnknownUser uscire dal loop. Però così facendo mi sarei anche trovato nella necessità di creare un metodo ad-hoc per ogni classe di oggetto, User, Role, Weblog, e cosi' via. Ho così immaginato che per ognuno di essi sarebbe esistito l'Unknown e preso atto del fatto che avevo predisposto una radice della gerarchia di oggetti in ImhoObject, ho deciso di marcare le classi di tipo Unknown con una interfaccia INonExistentImhoObject in questo modo:
 
[Serializable]
public class UnknownUser : 
    User, INotExistentImhoObject
{
    
public UnknownUser()
    {}
}
 
Così facendo mi sono finalmente potuto creare un metodo completamente generico che sfruttasse l'interfaccia marker per gestire il raggiungimento della fine del reader:
 
public static Array CreateArray( 
    Type type, 
    IDataReader reader )
{
    ArrayList list = 
new ArrayList();
    ImhoObject item;

    
while( !( ( item = Create( type, reader ) ) 
        
is INotExistentImhoObject ) )
        list.Add( item );

    
return list.ToArray( type ) as Array;
}
 
Et-voilà il gioco è fatto. Il metodo è del tutto generico tanto che basta passare il tipo di oggetto e il reader e puntualmente ritornerà un array contenente gli oggetti richiesti. Solo un rilievo. La condzione del ciclo while è scritta come piace a me, in puro stile "C", so che per molti risulterà antipatica, perchè soffre un po' di scarsa leggibilità, ma volete mettere: due righe e nemmeno una parentesi graffa!

powered by IMHO 1.2


Ieri è arrivato l'atteso annuncio, che VisualStudio 2005 sarà disponibile a partire dal 7 Novembre prossimo venturo. L'attesa è indubbiamente ancora lunga, e quindi mi sono chiesto perchè non fare un piccolo banner con il conto alla rovescia.

 

 

Chi lo volesse mettere nel proprio weblog potrà usare la seguente linea di HTML:

 

<script 
   src="http://www.boschin.it/blogs/radicalmente/vscount.aspx?utc=0200&b1=080&b2=5d5&f1=fff&f2=000"></script>
 
I parametri b1, b2, f1, f2 permettono di personalizzarne i colori, mentre con utc, si può impostare il proprio fuso orario, che per l'italia è 0200.
 
Aggiornamento: ho aggiunto un parametro wdt che di default è 200 che indica la larghezza in pixel del banner. Inoltre ora è possibile anche mettere più di un banner nella pagina senza che si creino conflitti.

powered by IMHO 1.2


In seguito alla pubblicazione del Replicator for Community Server, e alla conseguente domanda legittima che mi ha posto Stefano Demiliani in merito alla possibilità adattare il replicator anche a .TEXT, ho deciso di approfondire un po' la questione e di studiarmi meglio il codice sorgente del Community Server per capire come funziona lo scheduler di Job che ho sfruttato con successo per replicare il mio blog. Ne è uscito un interessante articolo la cui lettura non vi impegnerà più di pochi minuti, ma che sicuramente sarà utile a più di qualcuno.

Articolo: http://www.boschin.it/blogs/radicalmente/articles/aspnet_scheduler.aspx


Nel nuovo Framework .NET 2.0 molte cose hanno subito una revisione anche laddove a prima vista può essere meno evidente. E' questo il caso ad esempio del tipo DateTime che dal prossimo frameword disporrà di nuove caratteristiche quali ad esempio il supporto per l'ora legale e parzialmente per la timezone. Nel link che propongo in questo post, si trova una dettagliata spiegazione di queste novità, dei motivi che hanno spinto alla loro adozione ed un buon numero di link di approfondimento.

Link: What are the New DateTime Features in Whidbey [Anthony Moore]

powered by IMHO 1.2


Proseguendo l'indagine nella configurazione dell'applicazione del Framework 2.0, sono finalmente venuto a capo del SettingsProvider.

Il SettingsProvider è una classe, che si occupa della serializzazione/deserializzazione delle informazioni di configurazione, di una classe derivata da ApplicationSettingsBase. Un SettingsProvider si compone di un metodo GetPropertyValues() che riceve in input l'elenco delle proprietà della classe da deserializzare che sono marcate con un attributo di scope come UserScopedSettings o ApplicationScopedSetting e di uno speculare metodo SetPropertyValues() che invece riceve i valori da serializzare, corrispondenti alle suddette proprietà.

L'uso classico di un SettingsProvider potrebbe essere ad esempio quello di serializzare e deserializzare le informazioni di configurazione su un file crittato. Per fare questo si dovrà creare una classe che deriva da ApplicationSettingsBase che esponga tutte le informazioni di configurazione (vedi qui).

A questo punto si potrà realizzare una classe, derivandola da LocalFileSettingsProvider e fare l'override delle proprietà e dei metodi che la compongono, facendo particolare attenzione ai sopracitati GetPropertyValues() e SetPropertyValues(). Al loro interno si andrà a decrittare le informazioni di configurazione e a comporre una collection di valori o viceversa a serializzare le informazioni e poi a crittare il file.

Ecco un breve esempio:

public class CryptoSettingsProvider : LocalFileSettingsProvider
{
    
private string mName;

    
public override string ApplicationName
    {
        
get return mName;  }
        
set { mName = value; }
    }

    
public override string Name
    {
        
get return "CryptoSettingsProvider"; }
    }

    
public override SettingsPropertyValueCollection GetPropertyValues SettingsContext context, SettingsPropertyCollection ppc)
    {
        
// deserializzare il file crittato
    
}

    
public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection ppvc)
    {
        
// serializzare il file critato
    
}
}

Il collegamento tra il SettingsProvider e la classe di configurazione si ottiene per mezzo dell'attributo SettingsProviderAttribute nel cui costruttore andrà specificato come tipo da istanziare il provider appena creato. Ecco l'attributo

[SettingsProvider("Elite.Test.CryptoSettingsProvider,Elite.Test")]

Occorre fare importanza anche alle proprietà della classe, oltre ai metodi. Personalmente la proprietà "Name" ha dato parecchi problemi dato che non c'era scritto da nussuna parte che era obblogatorio farne l'override.

powered by IMHO