Modernizzazione applicativa: alcune importanti metriche di Architectural Design (Parte 2)
Dopo esserci occupati delle dipendenze cicliche e della duplicazione del codice nel precedente articolo, poniamo ora l’attenzione sulle best practice di complessità e accesso ai dati.
Metriche di Complessità
La piu nota metrica di complessità del software è la Complessità Ciclomatica di McCabe. La complessità ciclomatica di una sezione di codice è il numero di cammini linearmente indipendenti attraverso il codice sorgente: questi cammini dipendono sostanzialmente da numero di istruzioni condizionali (IF) e loop (cicli For, While, ecc.) presenti nella porzione di codice. La complessità ciclomatica può essere utilizzata come indice per misurare quanto può essere complessa l’implementazione di una funzionalità o di un algoritmo. Come best practice si suggerisce di tenerla bassa il più possibile su di una procedura, sfruttando la possibilità di suddividerla in moduli più piccoli e facili da mantenere.
I tool di CAST misurano la Complessità Ciclomatica e permettono di incrociare questa misura con altre informazioni come le LOC (Righe di Codice), gli AFP (Automated Function Points) e il Technical Debt (Debito Tecnico).
Esistono però altre misure di complessità, più legate al disegno architetturale che forniscono utili indicazioni sulla mautenibilità e sul contenimento dei costi di gestione delle applicazioni software:
- Avoid Artifacts with High Fan-In (CWE-1121): il Fan-In di un manufatto software è il numero di altri manufatti che lo referenziano. Più alto è questo numero, più difficile sarà gestire le modifiche in quanto andranno modificati e testati potenzialmente tutti gli oggetti che referenziano quello da modificare.
- Avoid Artifacts with High Fan-Out (CWE-1048): il Fan-Out di un manufatto software è il numero di altri manufatti che lui referenzia. Più alto è questo numero, più difficile sarà il costo di mantenimento: tutti gli aggiornamenti e le modifiche degli oggetti referenziati richiederanno di testare e/o modificare a sua volta il manufatto.
- Avoid Artifacts with High Integration Complexity (NIST M7-2016): la complessità dell'integrazione misura il numero di percorsi di integrazione indipendenti. I percorsi di integrazione sono percorsi del grafico del flusso di controllo in cui viene richiamato un altro oggetto esterno. La complessità di integrazione equivale al numero minimo di test per verificare il comportamento di integrazione dell'Artefatto. Un IC elevato significa più test e un maggiore rischio di errori.
- Avoid Namespaces (.NET) or Packages (J2EE) with High Efferent Coupling (CE): simile al Fan-Out ma a livello di package (gruppo di classi). Un accoppiamento eccessivo è dannoso per la progettazione modulare poiché le classi non sono indipendenti. Ciò impedisce il riutilizzo della componente poiché un accoppiamento elevato potrebbe indicare che uno spazio dei nomi è mal progettato e difficile da comprendere/mantenere. L'estrazione di classi dalla classe originale in modo che la classe sia scomposta in classi più piccole può ridurre l'accoppiamento efferente, questo migliora la modularità e promuove l'incapsulamento.
- Avoid Namespaces (.NET) or Packages (J2EE) with High Afferent Coupling (CA): simile al Fan-In ma a livello di package (gruppo di classi).. Il numero di package che dipendono da quello analizzato è un'indicazione del livello di responsabilità del package. Se il package è relativamente astratto, è accettabile un gran numero di dipendenze in entrata, ma maggiore è il numero riferimenti, maggiore è la sensibilità ai cambiamenti in altre parti del progetto e quindi la manutenzione è difficile.
Accesso ai dati
Un'altra problematica che può essere investigata e misurata con gli strumenti di CAST è quella della modalità di accesso ai dati e dell’utilizzo delle risorse database. Anche in questo caso esistono numerose metriche:
- Avoid having multiple artifacts inserting/updating/deleting data on the same SQL Table (CWE-1060) : una delle principali cause di corruzione dei dati nelle applicazioni, deriva dalla mancata conformità alle regole di modifica dei dati che sono state concordate. Queste policy spesso prevedono l’uso di procedure specifiche per l’aggiornamento/inserimento/ eliminazione di ogni tipologia di dati: spesso sono esposte API specifiche o Data Layer che sono completamente testati per mantenere l’integrità dei dati. La creazione di nuove e diverse procedure e funzioni di aggiornamento/inserimento/cancellazione che non utilizzano il codice testato esistente è all'origine di molti casi di danneggiamento dei dati.
Esempio di Data-call Graph prodotto con CAST Imaging che evidenzia più procedure che accedono alla stesa tabella
- Avoid direct access to Database Tables: l’accesso diretto alle tabelle del database da parte del codice presente nel frontend dell’applicazione, non rispetta i principi dell’architettura multi-layer. Le pagine web devono comunicare soltanto con il business-layer che a sua volta comunicherà con il data-layer attraverso un data-access-layer. L’accesso diretto alle tabelle, inoltre, impedisce il controllo a livello database degli accessi. Questa pratica favorisce anche l’utilizzo di query non ottimizzate sul database e l’utilizzo di query che non segue la data-logic corretta, creando incongruenze.
Oltre a queste esistono diverse metriche più specifiche per tecnologia e che riguardano l’utilizzo dei diversi framework disponibili per gestire l’accesso ai dati (Hibernate, iBatis, MS Entity Framework, ecc.)
Tutte queste problematiche, una volta individuate, possono essere meglio studiate e risolte sfruttando il motore grafico di CAST Imaging, che permette di navigare negli oggetti e nelle loro interazioni.
Comments: