Rilevare codice duplicato

Clone Detective for Visual Studio è una integrazione dell’ambiente Visual Studio (completamente free) in gradi di rilevare porzioni di codice duplicato tra i vari progetti che compongono una solution. Il fine è ambizioso, poichè come dice la stessa presentazione del prodotto presente su CodePlex

“Having duplicates can easily lead to inconsistencies and often is an indicator for poorly factored code”

Un componente del genere può davvero essere utilissimo, anche oltre lo scopo che si prefigge. Ad esempio, conoscendo accuratamente il numero di cloni presenti all’interno di un software con parecchie linee di codice, è possibile valutarne il costo di manutenzione, ovvero il costo a cui si va incontro se si decidesse di apportarvi delle modifiche.

Il componente si basa su ConQAT (Continuous Quality Assessment Toolkit) per rilevare le parti di codice duplicato. Questo toolkit fornisce una serie di tools e linee guida per il controllo della qualità del software

Snippet Code

Gli Snippet Code possono davvero far risparmiare tempo di sviluppo, soprattutto su operazioni ripetitive. Visual Studio, come è noto, fornisce un add-in per la gestione degli stessi su PC, e codificati in un file xml. Chi come me non usa sempre lo stesso PC per lavorare è costretto a sincronizzare gli snippet code su tutti i PC su cui sviluppa, operazione molto noiosa e anche molto soggetta ad errori. Sarebbe comodo in questi casi non avere il repository in  locale, ma averli centralizzati all’esterno.

<Code:Keep> fornisce appunto uno storage centralizzato  da cui attingere snippet code suddivisi per categoria ed in cui inserire i propri, ovviamente rendendoli usufruibili anche agli altri visitatori del sito, previa registrazione. Inoltre, viene messo a disposizione il download di un add-in per Visual Studio 2008, ovviamente gratuito, che permette di consultare ed utilizzare gli Snippet Code presenti nel sito direttamente dall’IDE, senza neanche aprire il browser.

Visual Studio 2008 Tip #1

In Visual Studio 2008 la pressione del tasto F12 rappresenta la scorciatoia da tastiera del comando Edit.GoToDefinition, che, come è noto, permette di “saltare” direttamente alla dichiarazione del simbolo selezionato nel codice. Non è però cosi evidente che il simbolo selezionato potrebbe anche risiedere nella pagina aspx. Ad esempio, se selezioniamo la classe CSS associata ad un controllo in una pagina aspx, o se semplicemente posizioniamo il puntatore del mouse all’interno della stringa della classe CSS, alla pressione del tasto F12 verrà automaticamente  aperto il file CSS contentente la definizione del simbolo selezionato e verrà interamente evidenziata la classe stessa con tutti gli attributi grafici associati,

Decisamente molto utile!

Visual studio ide crash #2

Avevo già parlato qui (post immediatamente sotto :-)) di uno strano crash di Visual Studio 2008 SP1, a seguito dell’esecuzione comando “Choose items” della toolbox.

Il problema sembrava essere dovuto alla presenza dei PowerCommands e di una loro presunta incompatibilità con il Service Pack 1. Infatti per poter tornare alla “normalità” era necessario un’azione estrema, ovvero rimuovere i PowerCommands, ed a quel punto il problema spariva.

Oggi scopro che attraverso un assemply redirection nel file di configurazione di Visual Studio (devenv.exe.config) il problema si risolve definitivamente, e che il crash si verificava anche nell’editor XAML. Maggiori info qui.

Quindi la soluzione è inserire questo frammento XML nel file di configurazione di Visual Studio:

Visual studio 2008 ide crash dopo "Choose items" dalla toolbox

Qualche giorno fa mi sono imbattuto in uno strano crash di Visual Studio 2008, dopo aver installato il Service Pack 1, vale a dire che il comando “Choose items” della toolbox era capace di mandare in crash l’intero IDE, scrivendo un laconico messaggio nell’Event viewer, del tipo

NET Runtime version 2.0.50727.3053 – Fatal Execution Engine Error (7A035E00) (80131506)

di nessuna utilità per la risoluzione del problema,  senza possibilità di scampo quindi. Dopo aver cercato invano per la rete per evitare di perdere ulteriore tempo ho evitato di disporre del controllo che mi interessava nella toolbox (precisamente una PropertyGrid) e l’ho inserito direttamente nel markup XAML della mia applicazione (una XBAP application).

Oggi ho letto questo post di Nazareno e speravo veramente di risolvere il problema, anche perchè questa volta la toolbox era indispensabile poichè dovevo inserire una intera suite di controlli.

Purtroppo non c’è stato niente da fare. Il problema sparisce solo dopo aver disinstallato i Power Commands, senza più reinstallarli.  Ma sono abituato ai Power Commands  e li trovo veramente utili.

Vale a dire che li disintallerò solo per utilizzare la toolbox, e poi li reinstallerò di nuovo…:-)

Mole, visualizer integrato per visual studio

Segnalo un gran bel Visualizer per Visual Studio 2005/2008. Trattasi di Mole v.4.2, un visualizer in grado di funzionare con diversi oggetti di diverse tipologie di progetto, che comprendono WinForms, WPF, WCF, WF, ASP.NET, XBAP. Io lo trovo molto utile soprattutto per progetti WCF, WPF, dove gli oggetti con cui si ha a che fare sono abbastanza complessi e strutturati. Uno strumento del genere, molto ben fatto e performante, può far risparmiare diversi “mal di testa” quando si effettua il debugging di progetti di questo tipo.

Download

Impossibile aggiungere una service reference in visual studio 2008

Questo workaround spero sia utile a chi si è trovato nella stessa mia situazione, e cioè che improvvisamente Visual Studio 2008 si rifiuta di aggiungere una Service Reference ad un servizio WCF, dando questo errore:

The components required to enumerate web references are not installed on this computer. Please re-install Visual studio.

Ho poi scoperto che il problema si presentava anche aggiungendo semplici web reference (ASP .NET web services) a progetti creati con Visual Studio 2005.

Per risolvere il problema non è mica necessario reinstallare Visual Studio 🙂

Basta lanciare l’ambiente di sviluppo da prompt dei comandi (quello di Visual Studio) con il parametro /resetskippkgs, quindi in questo modo:

devenv /resetskippkgs

Il parametro /resetskippkgs impedisce che siano caricati eventuali VSPackages aggiuntivi, che potrebbero creare problemi con lo startup dei componenti di Visual Studio. Era proprio quello che accadeva a me. Chiaramente basta lanciare solo una volta Visual Studio in quel modo, giusto per disabilitare il caricamento dei VSPackages.

Le direttive using devono essere poste all’interno del namespace

Questo post inizia con una frase tratta da un post di Scott Hanselmann con cui mi trovo completamente d’accordo:

Don’t believe everything you read, even on a Microsoft Blog.             

Don’t believe this blog, either!

Decide  for yourself with experiments if you need a tiebreaker!

Credo sia proprio vero, mai fidarsi ciecamente di quello che si legge in giro, soprattutto quando seri dubbi farebbero pensare il contrario.

Il motivo è presto detto: utilizzo normalmente FxCop come strumento di analisi del codice sorgente, lo trovo molto completo e ben fatto. Spinto dalla curiosità ho voluto utilizzare Source Analysis, un tool gratuito fornito da Microsoft ed integrato nell’IDE di Visual Studio. Dopo la primissima prova fatta mi ha incuriosito una sua segnalazione:

SA1200 – All using directives must be placed inside of the namaspace.

Per farla breve, tutti i files sorgenti del mio progetto provocavano una segnalazione di questo tipo poichè le direttive using erano poste esternamente alla definizione del namespace, così come automaticamente viene creato uno scheletro di una classe all’interno dell’IDE. La segnalazione in questione invita invece ad includere le direttive using all’interno della definizione del namespace, semprecchè sia presente. Facendo qualche ricerca in giro ho scoperto che in questo modo il compilatore segnala immediatamente una eventuale ambiguità tra i nomi dei tipi creati all’interno del proprio namespace e i tipi presenti nei vari namespace del .NET Framework. E fin qui nulla di strano.

Ho scoperto inoltre che questa guideline servirebbe anche ad aumentare le prestazioni, almeno nei casi specifici, in quanto forzarebbe il “lazy loading” degli assembly e non il caricamento immediato. In altre parole, quando il viene invocato un metodo di una classe e viene compilato il codice “just in time” (JITTED) il lazy loading permette di caricare in memoria solo gli assembly referenziati che servono all’invocazione del metodo stesso, e non tutti gli assembly referenziati da una classe, a prescindere se utilizzati o no da una specifica invocazione di un metodo. Questo permette di caricare solo lo stretto necessario anche se una classe referenzia un assemby non utilizzato da un metodo.

Sinceramente non mi è venuto in mente un solo valido motivo per cui una direttiva using posta in un certo modo potesse influenzare l’attività del CRL a runtime, e sono rimasto alquanto dubbioso sulla effettiva validità. Prima che potessi avere il tempo di fare una prova specifica mi son trovato questo post di Scott Hanselmann, al quale rimando per una esauriente spiegazione, che dimostra come purtroppo ciò non sia affatto vero, cioè gli assembly referenziati vengono caricati tutti i memoria immediatamente, a prescindere se il metodo in questione li usa oppure no, ed a prescindere se le direttive using vengono poste all’interno o all’esterno della definizione di namespace.

Quindi la morale è: non credere mai a quello che leggi, neanche se lo leggi da questo blog :), ma sperimenta sempre.

Automatic properties in c# 3.0

Utilizzando C# 3.0 è possibile scrivere le proprietà di una classe in modo estremamente compatto, in questo modo:

Public string Nome {get; set;}

Questa modalità, chiamata “Automatic properties” permette quindi di omettere il riferimento al membro privato che normalmente viene “wrappato” dalla proprietà stessa.

Sarà compito del compilatore autogenerare al volo il membro privato al momento della compilazione. Questa caratteristica impone che il codice della classe non può in nessun modo accedere alla variabile privata, appunto perchè al momento della stesura del codice essa non esiste ancora in quanto sarà autogenerata in fase di compilazione. E’ quindi necessario utilizzare direttamente il nome della proprietà nel codice della classe per accedere al suo contenuto e/o modificarlo.

L’impossibilità del codice ad accedere alla variabile privata è dovuta al fatto che, poichè è possibile in qualsiasi momento tornare alla dichiarazione classica della proprietà indicando esplicitamente una variabile privata, è necessario assicurare al codice la piena compatibilità tra le due modalità. In altre parole, se si trasforma una “Automatic property” in una proprietà diciamo così “classica”, il codice che la utilizza continuerà a funzionare senza problemi perchè è certo che non avrà in nessun modo potuto utilizzare la variabile privata autogenerata. Per lo stesso motivo, non è possibile indicare un solo “accessor” per la proprietà ma dovranno essere indicati obbligatoriamente entrambi (get; set;), fermo restando che è sempre possibile indicare un ambito di visibilità diverso tra i due “accessor” (es. get; con visibilità public e set; con visibilità private)

Problemi di performance in Visual Studio 2008

Ero praticamente certo che sarebbe uscita la hotfix giusta per me riguardante Visual Studio 2008.

Negli ultimi tempi ho sperimentato in prima persona rallentamenti eccessivi e chiaramente molto fastidiosi nell’utilizzo di alcune funzionalità dell’IDE e precisamente:

  • Passando alla vista Design di una Web Form;
  • Passando alla vista Html Source di una Web Form;
  • Compilando un progetto web di grosse dimensioni;

Oggi ho scoperto che da pochissimo tempo è disponibile una hotfix che risolve tutti e tre i problemi sopradescritti.

Link per il download.

Oracle Data Provider for .NET

Negli ultimi tempi mi è capitato spesso di lavorare su applicazioni che utilizzano Oracle come database piuttosto che Sql Server e, naturalmente, ho dovuto utilizzare nello strato di accesso ai dati le classi specifiche di Oracle, meglio note come Oracle Data Provider for .NET. Utilizzare queste classi significa avere a che fare con oggetti tipici di Oracle, es. gli Oracle data type, o i cursori utilizzati per contenere i resultset derivanti da una chiamata ad una store procedure, ecc.

Non avendo una esperienza significativa in Oracle ho sempre pensato che il supporto per .NET fosse alquanto limitato e ridotto all’essenziale,  es.  aprire una connessione ed eseguire un comando SQL che ritorna un resultset.  Ma noto con piacere che mi sbagliavo. La versione 11.1.0.6.20 dell’ODP for .NET fornisce sia una integrazione con l’ambiente Visual Studio  in versione 2005/2008, es. Server Explorer, wizards e designer, sia una integrazione con la piattaforma ASP .NET. Quest’ultima per me è la più interessante in quanto è possibile utilizzare alcuni providers  (argomento di cui ho già parlato in un mio articolo apparso sul sito dello user group DotNetSide) ed utilizzare come repository un database Oracle. Nello specifico i providers sono i seguenti:

  • Memberhip (gestione degli utenti e validazione)
  • Role (ruoli)
  • SiteMap (mappa del sito)
  • SessionState (  la Sessione di una applicazione ASP .NET )
  • Profile (profili degli utenti)
  • Web Event (informazioni circa lo “stato di salute” delle applicazione ASP .NET)
  • Web Part personalization (chi lavora con le WebParts può ora memorizzare le informazioni di personalizzazione in un db Oracle)
  • Cache Dependency

Il supporto per il Cache Dependency Provider a mio avviso è il più interessante di tutti. Ho già avuto modo di utilizzare ed apprezzare questo meccanismo (invalidazione automatica di un oggetto in cache a fronte di modifiche apportate a resultset memorizzati in un database mediante il meccanismo di notifica) su applicazioni basate su database SqlServer. Sarà sicuramente interessante e produttivo poterlo utilizzare anche in quei contesti dove il database è Oracle.

Messaggio di errore Ambiguous match found e httpParseException

Scenario: web application che utilizza la versione 1.1 di ASP .NET migrata direttamente alla versione 3.5. Dopo la migrazione su una delle pagine ASPX viene sollevato una HttpParseException durante il caricamento della stessa. L’eccezione in questione, come si evince dal nome, viene generata dal runtime di ASP .NET quando il parsing di una pagina ASPX fallisce a runtime. Il messaggio di errore recita “Ambiguous match found”, e quindi non aiuta granchè. La cosa curiosa è che l’eccezione non si verifica in ambiente di sviluppo ma solo sulla versione di deploying dell’applicazione, quindi non è “debuggabile” in Visual Studio 2008 ( a meno di non effettuare un debug in remoto, cosa quasi mai possibile in ambiente di produzione) , e quindi non è di facile risoluzione.

In questi casi la prima cosa che penso è: sicuramente altri developers sparsi per il mondo hanno già sperimentato lo stesso problema, quindi  mi metto a perlustrare blogs e forum e normalmente alla fine il problema si risolve !

E così è stato anche stavolta, anche se le cause di questa eccezione possono essere diverse e quindi non esiste una soluzione universalmente applicabile.

Alcune delle cause che possono produrre una httpParseException sono, in ordine sparso:

  1. la pagina contiene un campo hidden che ha un ID con lo stesso nome di una variabile querystring usata dalla stessa pagina;
  2. la pagina ha un controllo (non ascx) inserito nel file ASPX (e quindi inserito nella partial class non visibile), e nel code-behind della stessa è dichiarato un altro controllo protected con lo stesso nome;
  3. la pagina contiene un controllo ASCX con lo stesso nome di un controllo nativo ASP .NET;

Tutte queste situazioni generano evidentemente una ambiguità dei tipi, che porta all’eccezione.

Inoltre,  effettuando un deploy del sito con l’opzione “non aggiornabile”, ovvero deselezionando l’opzione “Allow this precompiled site to be updateable”, l’eccezione dovrebbe scomparire, salvo poi approfondire le sue cause e riabilitare nel caso l’opzione.

Sottili differenze tra C# e VB .NET #Part 2#

Questa informazione me la annoto perchè sicuramente utile. Avevo già parlato precedentemente delle sottili e a volte subdole differenze esistenti tra il linguaggio VB .NET  e C#, differenze che possono anche riguardare il comportamento di Visual Studio, quindi non strettamente legate a costrutti di programmazione o alla semplice sintassi.

Questa differenza però mi sorprende parecchio e non riesco a comprenderne a fondo il motivo. Presto detto: se si utilizza l’incremento automatico nel numero di versione in un assembly (per intenderci quando impostiamo questa riga

[assembly: AssemblyVersion("1.0.*")]

nel file AssemblyInfo, otteniamo un risultato differente a seconda se l’assembly è scritto in VB .NET o in C#. Se è scritto in VB .NET l’incremento automatico è operato solo alla prima build, mentre alle successive build sulla stessa istanza di Visual Studio il numero di versione resta invariato (se l’assembly viene ricompilato in una differente istanza di Visual Studio il numero di versione è incrementato).

Se, viceversa, l’assembly è scritto in C#, ogni build produce un incremento automatico del numero di versione. Appena mi è possibile proverò questa funzionalità, anche se la documentazione MSDN è abbastanza chiara.

Questo comportamento differente in funzione del linguaggio avrà anche una sua logica, ma non è sicuramente immediatamente chiara.

Inoltre, non condivido la motivazione che la documentazione MSDN produce per spiegare il tutto: poichè il numero di versione è inserito solo a titolo informativo in un assembly non firmato con uno strong name, il problema non si pone. Viceversa, se l’assembly deve essere dotato di strong name, viene sconsigliato l’uso dell’incremento automatico, in VB .NET chiaramente, perchè in C# non c’è alcuna controindicazione.

Visual Studio 2008 non supporta .NET 1.0/1.1

Leggo con un certo disappunto dal blog di Irena Kennedy (uno dei miei preferiti, soprattutto per i suoi posts SYSK) che la prossima release di Visual Studio supporterà più versioni del .NET Framework, in modo da avere un unico ambiente di sviluppo installato (questo pensavo io). In realtà le versioni supportate del .NET Framework partono dalla 2.0, quindi 2.0, 3.0, 3.5. Quindi, in pratica, per gestire anche progetti scritti per .NET 1.0/1.1 (e sono veramente tanti in circolazione, soprattutto 1.1) occorrerà avere ancora installate più versioni di Visual Studio.

La cosa mi ha francamente deluso, e sono curioso di leggere (eventuali) feedback tecnici sul perchè di questa scelta apparentemente strana.