EMBEDDED
52 • MAGGIO • 2014
67
SOFTWARE
QUALITY
di apportare una serie di cambiamenti in tutti i vari pacchetti
dipendenti – può diventare pesante da gestire in termini di
evoluzione e manutenzione del software, al punto da bloccare
i processi di autorizzazione alle modifiche dei pacchetti stessi.
A quel punto il progetto software diventa rigido, fragile, e
difficile da modificare. O anche da riutilizzare, se le compo-
nenti del progetto che si desidera riusare si rivelano altamente
dipendenti da altri aspetti tecnici su cui risulta troppo oneroso
e complesso intervenire.
Una via di soluzione del problema è adottare tecniche di
sviluppo in grado di portare verso la creazione di dipendenze
definite ‘buone’. Un codice robusto, manutenibile e riutilizza-
bile si caratterizza per la scarsità di interdipendenze. E, dove
presenta dipendenze, queste sono buone, nel senso che non
condizionano il raggiungimento dei requisiti richiesti per il
progetto, perché si rifanno a classi stabili. Una classe è tanto
più stabile quanti meno legami ha con altre classi, e in tale
accezione si definisce classe indipendente. In questo campo,
un sentiero di guida della progettazione object-oriented può
essere rappresentato dallo Stable Dependencies Principle
(SDP), secondo il quale le dipendenze fra i pacchetti, in un
progetto software, dovrebbero andare nella direzione della
stabilità dei pacchetti stessi. Quindi un pacchetto software
dovrebbe dipendere solo da altri moduli più stabili. Allo stesso
tempo, però, visto che un progetto non può essere comple-
tamente statico, è necessario conformarsi anche a un altro
principio, il cosiddetto Common Closure Principle (CCP),
che disciplina la creazione di pacchetti software progettati
per essere più ‘volatili’ e adatti a subire modifiche, in modo
da ridurre l’impatto dei cambiamenti sulla manutenibilità del
sistema, specie quando il progetto è grande e si compone di
molti pacchetti.
Ottimizzazione: non sempre
va d’accordo con portabilità
Un software di qualità si contraddistingue per la flessibilità,
solidità e stabilità, la facilità di riutilizzo dei componenti e la
trasparenza di comprensione. Nella pratica, però, l’esigenza di
rispettare determinati requisiti del sistema embedded entra in
collisione con questi princìpi virtuosi: come detto precedente-
mente, qualità del software significa anche portabilità, ma in
vari casi questo non accade. Come quando si ha a che fare con
il software di sistemi embedded con architettura a 16, 32 o 64
bit, scritto in un linguaggio di programmazione ad alto livello
come il linguaggio C. Se è vero che quest’ultimo consente la
portabilità del codice su diverse piattaforme utilizzando vari
compilatori, è vero anche che molto del software sviluppato
in C per applicazioni embedded non viene scritto con questo
obiettivo primario. Piuttosto, il punto diventa ottimizzare
caratteristiche specifiche del sistema, come l’uso della memo-
ria o le prestazioni. Quindi il codice viene creato ‘su misura’,
usando un compilatore con opzioni modificate per soddisfare
tali requisiti, e non risulta portabile. Così, successivamente,
quando tale codice si fa migrare su un nuovo ambiente opera-
tivo, magari usando un compilatore C differente, tipicamente
va in crash e si blocca.
C e C++, attenzione alle ‘insidie’
L’utilizzo del linguaggio ad alto livello C++ è ampiamente dif-
fuso nelle attività di sviluppo software per i sistemi embedded,
anche quando si tratta di realizzare applicazioni safety-critical
o sistemi che devono mantenere un funzionamento hard-real-
time. Tuttavia occorre anche aggiungere che C++ (come anche C),
proprio per la sua ricchezza semantica, in un certo senso non si
posiziona esattamente come un linguaggio adatto allo sviluppo di
software di categoria safety-critical. Infatti, offrendo al programma-
tore un’elevata gamma di sfumature e libertà espressive in fase di
sviluppo, impone maggior attenzione, preparazione e responsabilità
per non incorrere in errori. Se il linguaggio C, per le sue caratteristi-
che, si può paragonare, dal punto di vista della programmazione, a
una spada con una lama tagliente, qualche sviluppatore parla di C++
come di un spada a due lame, ancora più tagliente e bisognosa di
responsabilità e controllo. Le difficoltà e i ‘pericoli’ derivanti dall’uti-
lizzo del linguaggio C++ risiedono nel fatto che esso è uno strumen-
to davvero molto potente, capace di portare in errore gli sviluppatori
non sufficientemente formati e disciplinati sull’applicazione delle
sue regole. In altri termini, con C++ in molti casi risulta troppo facile
raggiungere elevati livelli di astrazione e creare codice ‘offuscato’,
difficile da leggere e incomprensibile nel lungo termine.
Nella prossima parte di questa guida allo sviluppo di codice di
qualità si analizzeranno alcuni aspetti positivi e negativi dell’uso del
linguaggio C++ per lo sviluppo di sistemi embedded safety-critical,
indicando alcune regole e linee guida per la creazione di codi-
ce di qualità.
Fig. 3 – Uno strumento di analisi ed evidenziazione della
sintassi del codice