NDepend: un tool indispensabile per sviluppatori .NET
In questo articolo parleremo di NDepend, un tool indispensabile che non può assolutamente mancare nella cassetta degli attrezzi di qualsiasi sviluppatore .NET. Prima di addentrarci però nell’argomento, è necessario fare una premessa.
Premessa
Come probabilmente già saprà chi legge questo blog o mi conosce di persona, sono uno sviluppatore software e, come tale, la mia attività quotidiana consiste principalmente nello scrivere codice.
Oltre a scrivere “codice nuovo” per soluzioni software verticalizzate e richieste dai clienti della mia azienda (ABLS Team), mi occupo anche di formazione ma soprattutto di consulenza e sviluppo in outsourcing.
In breve, scrivo anche “codice conto terzi”, coadiuvando altri team di sviluppo e aiutandoli come posso nella realizzazione del proprio software, implementando nuove soluzioni o – nella maggior parte dei casi – modificando ed estendendo quelle già esistenti.
E’ opinione condivisa tra i programmatori, quasi una legge non scritta, che modificare il codice altrui sia una impresa ardua: di fronte alla richiesta di un cliente di modificare un programma disponendo del codice sorgente, molte software house propongono di riscriverlo da zero piuttosto che mettere mano al lavoro altrui, oppure accettano la proposta a fronte di costi elevati e scarse garanzie.
E’ vero che la riscrittura completa, pur rappresentando la scelta più lunga, complessa e rischiosa, a volte rappresenta una strada obbligata: le tecnologie, le metodologie e gli strumenti nell’ambito dello sviluppo software sono in costante evoluzione, e spesso conviene davvero iniziare da capo, magari perché vecchia di anni, viziata da numerosi interventi e “martellate”, apportate spesso da un numero elevato di persone, tutte differenti tra loro e con competenze ed esperienze variabili, che alla fine portano ad avere un groviglio indistinguibile di istruzioni tale che il software ha la consistenza di un castello di carte: nessuno lo tocchi, altrimenti crolla tutto e non funziona più nulla!

Esiste una alternativa al doversi rassegnare all’idea di rifare tutto? La risposta è sì, e si chiama Refactoring.
Refactoring: non è un gioco da ragazzi
Mi sono ritrovato spesso a ricorrere al Refactoring come unica via per poter manutenere un software esistente. E’ probabile che io sia contro corrente, ma credo si tratti di una pratica fondamentale, talvolta imprescindibile se si deve mettere mano a una porzione di codice composta da centinaia righe, scritte magari in modo poco ortodosso, ovvero senza applicare alcun principio fra quelli globalmente riconosciuti dagli sviluppatori (Design Patterns, principi SOLID, ecc.) o perché semplicemente non vi è alcuno schema concettuale identificabile nella struttura del codice, che come tale appare incomprensibile e quindi immodificabile.
Wikipedia definisce il Refactoring come “una tecnica per modificare la struttura interna di porzioni di codice senza modificare il comportamento esterno”. Spesso è più facile a dirsi che a farsi, perché la tecnica non è esente da rischi, ossia non è così facile apportare le modifiche assicurando che il comportamento del programma non venga alterato, soprattutto quando questo è completamente privo di Unit Test e altri espedienti che consentono di verificare questa condizione.
Come è possibile fare Refactoring al meglio e in modo affidabile? Oltre ad armarsi di tanta pazienza, è necessario anche dotarsi dei tool giusti per farlo. La maggior parte degli ambienti di sviluppo (Visual Studio, Delphi, Eclipse, …) possiede già funzionalità incorporate che consentono di eseguire le operazioni più semplici e immediate, come rinominare una classe o un metodo; nella manutenzione di progetti piuttosto grandi e complessi, questi strumenti risultano tuttavia spesso insufficienti ed è necessario ricorrere a prodotti di terze parti.
Per lo sviluppo su .NET Framework con Visual Studio e C#, ad esempio, ci sono due prodotti di cui non posso più fare a meno: NDepend e ReSharper.
Affronterò ReSharper eventualmente in un articolo separato: per chi non lo conosce, al momento basti sapere che si tratta di un “must have” in grado di offrire numerose funzioni per scrivere codice velocemente, unito a una gamma completa di comandi per rifattorizzare il codice in tutta sicurezza e in modo automatico, risparmiando tempo e ottimizzandone la struttura con la garanzia di non alterare il suo comportamento.
Ci sono però delle domande fondamentali da porsi quando si decide di iniziare col Refactoring di un software:
- Quali sono i punti in cui dobbiamo intervenire?
- Come facciamo a sapere che tipo di fix applicare?
- Come riconosciamo una parte di codice foriera di problemi?
- Come sappiamo se sono state usate al meglio le proprietà del linguaggio di programmazione e del framework?
Sebbene ReSharper fornisca alcune risposte a queste domande, l’esperienza con il tool NDepend è decisamente molto più completa.
NDepend: la soluzione!
Sono venuto a conoscenza di NDepend vedendolo spesso citato in forum online di programmazione e conferenze, così ho pensato di dare un’occhiata al tool e metterlo alla prova.
Dapprima ho visionato l’elenco delle feature sul sito ufficiale e ne sono rimasto sbalordito! Pensando al nome del tool, inizialmente credevo si trattasse di una semplice versione per .NET del noto Dependency Walker, una utility per mostrare le dipendenze di un eseguibile (.exe) o di una libreria (.dll) ma compatibile con il .NET Framework. NDepend è invece molto, molto di più! 😊
Installare il software è molto semplice: basta scaricare il pacchetto del programma in formato ZIP ed estrarlo in una directory del proprio disco locale.

NDepend può essere lanciato nel proprio IDE indipendente (eseguendo il file VisualNDepend.exe) oppure eseguito come estensione direttamente integrata in Visual Studio (previa installazione tramite l’apposito programma che si occupa di tutto).

Dopo aver disbrigato le questioni burocratiche della procedura di registrazione e attivato correttamente la licenza, ho iniziato a sperimentare le funzionalità di NDepend, usando come “cavia da laboratorio” il progetto già esistente di un cliente.
Una volta avviato Visual Studio e caricato la Solution desiderata, l’estensione di NDepend mostra un indicatore nella parte inferiore a destra della barra di stato principale dell’IDE. Questa consente di tenere sotto controllo lo stato di salute del vostro lavoro, condizionato dall’adesione del codice ai canoni fissati dall’analisi effettuata da NDepend, completamente personalizzabile in tutti i suoi parametri.
Primi passi con NDepend
Spostando il mouse sull’indicatore, appare una finestrella popup che consente di creare un nuovo progetto NDepend (o caricare un progetto esistente) da agganciare alla Solution corrente.
Se l’associazione è già stata eseguita in precedenza, il progetto NDepend viene caricato in automatico dall’estensione contestualmente all’apertura della Solution a cui fa riferimento.

Ciascun progetto NDepend contiene tutti i valori delle impostazioni per il tool relativi a una specifica Solution, e consente di salvarli in un file separato da quello della Solution o del Project di Visual Studio.
Tutte le funzionalità di NDepend sono accessibili dal comodo menu integrato dall’estensione di Visual Studio e suddiviso in base all’ambito di ciascuna di esse.

Trattandosi del primo utilizzo, io ho scelto di creare un nuovo progetto NDepend da zero: il tool ha avviato un processo di “Build” della Solution aperta e analizzato il codice compilato, visualizzando un report in formato HTML al termine della procedura. All’interno del report troviamo una sintesi dei risultati delle analisi che il software è in grado di eseguire, mostrando una finestra di dialogo per la scelta del passo successivo da compiere.

Nel mio caso, ho scelto di proseguire mostrando la Dashboard del progetto: si tratta di uno strumento molto comodo per tenere sotto controllo tutte le informazioni che il tool è in grado di estrarre, mantenere e storicizzare in merito alla Solution associata.

Ad esempio, vengono indicati il numero di assembly generati dalla soluzione, il conteggio dei namespace, dei tipi, delle classi e dei metodi al loro interno, il numero complessivo di file sorgente, delle righe di codice sorgente ivi comprese quelle che contengono commenti, con una indicazione del loro rapporto percentuale rispetto alle istruzioni vere e proprie.
Personalmente trovo utili in modo particolare gli indici che mostrano la complessità massima dei metodi (a tal proposito, leggi il mio articolo sulla Cyclomatic Complexity) e la stima del cosiddetto “debito tecnico”, ossia la valutazione del costo implicito (espresso in termini di tempo) derivante dalla necessità di rimaneggiare il codice scritto a causa dell’adozione di una soluzione più semplice e sbrigativa, quindi limitata, rispetto a quella che invece rappresenta un approccio migliore e con maggiore manutenibilità.
La Dashboard mostra infine un prospetto delle regole violate e warning che inficiano la qualità del codice sorgente, aggregate e riepilogate in base a diversi criteri, per tipologia e per gravità.
Molto interessanti sono i grafici che mostrano il trend di variazione delle misurazioni effettuate. NDepend è in grado di fornire questa informazione in quanto a ogni build, in modo manuale o automatico, tutti i valori vengono ricalcolati eseguendo una nuova analisi, ma conservando una fotografia delle situazioni precedenti: in questo modo è possibile tenere sotto controllo l’andamento complessivo del progetto, i benefici prodotti dalle modifiche eventualmente apportate e l’evoluzione generale nel corso del tempo.
La Dashboard può essere personalizzata a proprio piacimento, togliendo i riquadri che non interessano o aggiungendone di nuovi: tutte le scelte operate vengono salvate in modo persistente all’interno del file di progetto di NDepend.
Riguardo l’identificazione delle regole violate all’interno del codice sorgente, NDepend fornisce un motore di analisi sofisticato e completamente personalizzabile. Da tempo cercavo uno strumento che fosse simile al famigerato FxCop di Microsoft, ma in grado di offrire maggiori possibilità di customizzazione, ad esempio “chiudere un occhio” su determinate violazioni del tutto trascurabili, concentrandosi invece su quelle più importanti e con maggiore impatto sul debito tecnico dal punto di vista pratico.

Per ciascuna regola violata, il tool consente di individuare i punti esatti nel codice laddove si verifica il misfatto, in modo da procedere in modo mirato alla risoluzione del problema, rilanciando poi l’analisi del codice e comparando i nuovi risultati con i precedenti.

Nelle schermate riportate, io ho preso come riferimento la violazione della regola “Avoid methods with too many parameters“. Facendo clic sulla regola, si ottiene l’elenco dei metodi che sono affetti dal problema. Facendo nuovamente clic sul singolo elemento, si viene portati nel punto del codice interessato per poter apportare le dovute modifiche. Nel mio caso, ho corretto la firma problematica del metodo sostituendo tutti i parametri – evidentemente troppi – e lasciandone solo uno al loro posto, appartenente a un nuovo tipo di struttura che raggruppa tutti i valori dei parametri al proprio interno, espressi come campi.

Questo è ovviamente solo un esempio dei problemi diagnosticati da NDepend, ma le casistiche supportate sono davvero infinite: da quelle più banali, come l’uso di tipi e membri dichiarati come obsoleti, a quelli più subdoli, come la presenza di un numero troppo elevato di metodi all’interno di una interfaccia (che è un indizio della probabile violazione del principio di Interface Segregation Principle).
Conclusioni
Questo post non ha come obiettivo descrivere tutte le caratteristiche complete di NDepend: non sarebbe solo un compito improbo, ma è praticamente impossibile, perché le potenzialità offerte da questo tool sono pressoché infinite, soprattutto nella gestione di progetti software particolarmente grandi e complessi, laddove è necessario imporre un livello elevato di qualità del codice sorgente e continuare a garantirlo nel tempo, con una adesione il più possibile ferrea agli standard di utilizzo sia del Framework sia della piattaforma .NET, sfruttando possibilmente i “coding pattern” riconosciuti che risolvono egregiamente determinati scenari.
Se volete comunque farvi un’idea più approfondita delle capacità di NDepend, c’è una intera playlist di filmati di YouTube che vi mostra nel dettaglio ogni singola feature, con tanto di demo.
Se qualcuno di voi deciderà di mettere alla prova NDepend, sono felice di ricevere i vostri feedback su quali sono le feature che ritenete più interessanti e quali modalità d’impiego innovative avete messo in opera.
Buon Refactoring! 😉
articolo interessantissimo,c’è qualche programma simile freeeware od opensource 🙂 ?
Purtroppo credo che la risposta sia “no”. 🙂 O almeno, io non sono a conoscenza di estensioni e/o programmi così completi che forniscano tutte le feature di NDepend, e includo anche prodotti commerciali.
Vi sono diverse estensioni, anche gratuite, che ne riproducono in parte le funzionalità, o che danno una mano nelle operazioni di pulizia e Refactoring del codice.
Se può essere utile, magari scriverò qualcosa sulle estensioni che preferisco appena avrò un pochino di tempo… non si sa mai che da questo scaturisca qualcosa di utile e di nuovo. 😉
Grazie mille per il feedback!
Marco.