Massimo Oliviero

I deliri digitali di un programmatore informatico e aspirante fotografo…
novembre 5th, 2008

Le novità di .net 4.0

Sul BCL Team Blog è possibile leggere un post sulle novità del framework .net 4.0. Tra le tante novità sicuramente quella su cui sbavo di più  è questa:

Code Contracts
System.Diagnostics.Contracts provides a language-agnostic way to express coding assumptions in .NET programs.  The contracts take the form of pre-conditions, post-conditions, and object invariants.  Contracts act as checked documentation of your external and internal APIs.  The contracts are used to improve testing via runtime checking, enable static contract verification, and documentation generation.  We partnered with Microsoft Research to deliver this feature in .NET 4.0.  More information and tools are available on Microsoft Research’s code contracts website.  There’s also a highly-rated PDC sessionavailable online.

Finalmente un Design By Contract come dico io. E se le premesse sono queste c’è da sperare bene. Sbav sbav!!

novembre 5th, 2008

Subversion in .net

Per un progetto personale ho la necessità di collegarmi ad un repository subversion e fare delle semplici operazioni di update e checkuot in c#. Non ci sono molti framework che fanno questo. Io ne ho trovati due molto interessanti DotSvn, ma soprattutto SharpSvn. Il primo vanta una re-implementazione nativa in c# senza la necessità di librerie esterne. Pur essendo un ottimo prodotto, per il momento DotSvn supporta solo i file system repository, quindi niente http. Non fa al caso mio. SharpSvn invece è libreria completa sotto ogni punto di vista. Supporta diversi tipi di repository (http, file) e offre una gamma di funzionalità decisamente elevata. L’unico requisito richiesto è il Microsoft Visual C++ 2005 SP1 runtime. Che dal mio punto di vista non rappresenta un limite.

A questo punto non resta che provarlo. Ecco un semplice esempio.

using (SvnClient client = new SvnClient())
{
    // definisco un nuovo repository URI
    Uri repo = new Uri("http://sharpsvn.googlecode.com/svn/trunk/");
 
    // tramite SvnLogArgs e SvnRevisionRange è posibile impostare
    // un revision range per estrarre i log message
    // in questo caso dalla Revision 1 alla 100.
    SvnLogArgs arg = new SvnLogArgs();
    arg.Range = new SvnRevisionRange(1, 100);
 
    // estraggo una collezione di SvnLogEventArgs
    Collection col;
    client.GetLog(repo, arg, out col);
 
    // a questo punto visualizzo tutti i Log ritornati
    if (col != null)
    {
        foreach (SvnLogEventArgs args in col)
        {
            Trace.WriteLine(string.Format("rev: {0} - {1}", args.Revision, args.LogMessage));
        }
    }
}

Semplice no?! Favoloso!.

ottobre 27th, 2008

JSon, l’arcano è svelato…

Riprendendo il discorso del precedente post su JSon, devo fare mea culpa. Molto semplicemente bisognava “istruire” il serializzatore con i possibili type che ereditano dalla classe astratta. Per far questo è necessario aggiungere un attributo KnownType(“Funzione”) sulla classe astratta. Dove “Funzione” è il nome del metodo statico, della classe, che ritorna un array di tipi. In questo modo (partendo dall’esempio del post precedente):

    [Serializable]
    [DataContract]
    [KnownType("KnownTypes")]
    public abstract class Task
    {
        public static Type[] KnownTypes()
        {
            return new[] { typeof(Todo), typeof(Issue) };
        }
    }

Scoperto l’arcano, mi son reso conto che alla fine utilizzare JSon per implementare il pattern Memento non va bene, anche perché sporca troppo il Domain Model. Sto però valutando l’adozione di un altro framework json, JSon.Net, che sembra decisamente più promettente di quello nativo del framework .net.

ottobre 23rd, 2008

Sopprimere un warning di FxCop via codice

E’ possibile configurare FxCop in modo tale da non fargli analizzare parti di classi o di metodi o addirittura interi assembly. In questo modo è possibile, in gergo, far “sopprimere” un warning di FxCop, inserendo una riga di codice per ogni warning che vogliamo disabilitare.

Per fare questo ci sono due possibilità:

  1. Sopprimere un warning inline, cioè su un metodo, una classe o una proprietà specifica
  2. oppure un Global Suppressions creando un file cs (o vb) apposito
Per esempio con il seguente codice sopprimo un warning CA2227:CollectionPropertiesShouldBeReadOnly (appertenente alla categoria “Microsoft Usage”) solo per la proprietà Tasks, per tutte le altre proprietà la regola sarà valida.
#define CODE_ANALYSIS
class TaskList
{
   [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
   public IList<Task>
   {
       get { return this.tasks; }
       set { this.tasks = value; }
   }
}

Se invece volessimo sopprimere un warning su tutto il nostro assembly (ma magari solo per uno specifico namespace), possiamo creare un generico file GlobalSuppressions.cs e inserire il seguente codice:

#define CODE_ANALYSIS
 
using System.Diagnostics.CodeAnalysis;
 
// con questa direttiva sto disabilitando tutti warning di tipo
// CA1020:AvoidNamespacesWithFewTypes a livello di namespace
// per tutto il name space Azienda.Progetto.Service
[module: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "Azienda.Progetto.Service")]

Come si nota in entrambi gli esempi è necessario definire un simbolo CODE_ANALYSIS in modo da attivare questo tipo di funzionalità. Per avere la direttiva corretta con il warning da sopprimere in maniera facile è sufficente premere tasto destro sul messaggio di warning in FxCop Gui e selezionare Copy As -> SuppressMessage. Il codice necessario sarà copiato negli appunti.

ottobre 22nd, 2008

Serializzazione JSon e classi abstract

Predendo spunto da un interessante post di Marco Minerva, ho provato ad implemetare il pattern Memento utilizzando appunto la serializzazione JSON. Ebbene a parte il fatto che bisogna necessariamente decorare le classi e i membri con un attributo specifico (e questo come per XmlSerializer con l’attributo Serializable è un poco bruttino e poco pi), il tutto funziona bene finché non ci sono di mezzo classi abstract. Mi spiego meglio. Una delle doti del serializzatore JSON sta nel supporto alla serializzazione delle List<T> che invece XmlSerializer non gestisce.

Bene, se T della List<T> che si vuole serializzare è una classe abstract il processo fallisce miseramente. E’ ovvio che quando vado a fare un Add sulla lista lo faccio di una classe concreta che eredita dalla classe abstract. Questo mi da il vantaggio (ovvio della programmazione ad oggetti) di avere una collezione di una “famiglia” di oggetti e non di uno dei suoi figli specifici.

Facciamo un esempio:

// classe astratta che mi rappresenta un
// generico task da eseguire
public abstract class Task
{
   private string description;
 
   public string Description
   {
     get { return this.description; }
     set { this.description = value; }
   }
}
 
// classe che mi rappresenta un bug da risolvere
public class Bug : Task
{
   // proprietà e metodi specifici.
}
 
// classe che mi rappresenta una todo da completare
public class Todo : Task
{
   // proprietà e metodi specifici.
}
 
// classe Milestone che contiene sia Todo che Bug
// creando una IList di Task posso memorizzare entrambi in un
// unica collection
public class Milestone
{
   private IList<Task> tasks = new List<Task>();
 
   public IList<Task> Tasks
   {
     get { return this.task; }
     set { this.task = value; }
   }
}

Tento la serializzazione in questo modo:

public void Test()
{
    Milestone milestone = new Milestone();
 
    Todo td1 = new Todo();
    td1.Description = "Fare e disfare";
 
    Todo td2 = new Todo();
    td2.Description = "Rifare e non disfare";
 
    milestone.Tasks.Add(td1);
    milestone.Tasks.Add(td2);
 
    string ser = Serialize(milestone);
 
    Milestone newMilestone = Deserialize(ser);
}

Dove “Serialize” e “Deserialize” sono gli stessi metodi descritti nel post di Marco. All’esecuzione del precedente codice ottengo un bel “System.Runtime.Serialization.SerializationException” in quanto probabilemente non riesce correttamente a serialize IList di Task. Vedrò di approfondire il discorso.

ottobre 22nd, 2008

Spunti interessanti con StyleCop e FxCop

Ho iniziato da poco un progetto personale in c# per sperimentare una serie di metodologie. Tra le varie cose mi sono imposto di utilizzare due strumenti quali StyleCop e FxCop. Entrambi i tool della Microsoft prevedono una serie di regole di programmazione che vanno dalla documentazione al design del codice. Per un totale di circa 400 regole. Rispettarle tutte è davvero un’impresa ardua, ma i vantaggi sono enormi. Pulizia del codice, standard di scrittura, ottimizzazione delle prestazioni e tanto altro. Sia StyleCop che FxCop si integrano perfettamente in Visual Studio, ed è così possibile verificare in tempo reale le possibili violazioni di una delle regole scelte.

Sia con StyleCop che con FxCop è possibile scrivere, con estrema facilità, nuove regole (rules) custom in modo da espandere le potenzialità di questi due strumenti adattandoli alle nostre esigenze di progetto. Detto questo alcune delle regole che mi sono capitate di affrontare in questi giorni mi hanno lasciato da una parte perplesso e da un’altra stupito. Per esempio la regola CA1726: UsePreferredTerms, è una regola che prevede l’utilizzo di termini nuovi, rispetto a quelli più obsoleti, nei nomi dei membri e delle classi. E’ così che la mia simpatica classe Login non è gradita da StyleCop che mi suggerisce un più moderno termine come LogOn (tra l’altro rispettando il case). Davvero bizzarra come regola no?. Navigando sulla relativa pagina di descrizione della regola ci ritroviamo una tabella di nomi e termini obsoleti con i rispettivi termini moderni.

A parte questa regola le altre le ho trovate molto formative. Soprattutto le regole di StyleCop mi hanno aperto la strada verso un nuovo modo di scrivere codice e mi hanno fatto scoprire aspetti interessanti del framework. Per esempio la regola SA1200: UsingDirectivesMustBePlacedWithinNamespace, prevede che le direttive “using” (solo in c#) dovrebbero essere posizionate all’interno del namespace e non all’esterno come fanno ovviamente tutti e come anche visual studio propone nei suoi template. Perché? Ecco perché:

There are subtle differences between placing using directives within a namespace element, rather than outside of the namespace, including: 

1. Placing using-alias directives within the namespace eliminates compiler confusion between conflicting types. 
2. When multiple namespaces are defined within a single file, placing using directives within the namespace elements scopes references and aliases.

Interessante no? Per il momento le mie riflessioni terminano qui. Posso solo dire che questi due strumenti dovrebbero diventare un must per ogni programmatore che vuole creare codice robusto e di qualità, ma soprattutto standard!.