Anche il software è ingegneria
Dalla rivista:
Elettronica Oggi
Non importa come lo si misuri, il software sta sempre più arrivando a dominare sistemi elettronici. Le applicazioni automotive da sole hanno attualmente molti milioni di righe di codice, come li avranno i dispositivi consumer. Eppure gran parte di questo software è stato sviluppato in un modo precario e indisciplinato. Gli utenti dei prodotti consumer sono rassegnati a doverli spegnere e riaccendere – riavviando il computer interno – in modo sistematico. Anche se ci sono alcuni segnali di miglioramento, le cose si stanno muovendo ancora troppo lentamente.
Ci sono molti strumenti disponibili, che spaziano dalla specifica dei requisiti iniziali e del system modelling ai test e al debug, e che possono aiutare a trasformare lo sviluppo software in una disciplina razionale di progettazione.
Questo articolo darà uno sguardo ai requisiti essenziali per dei progetti di successo e ai tool che assicurino la qualità del software. Ci sono quasi altrettante definizioni di buon codice quante le persone che commentano lo sviluppo del software, ma ciò che si sta cercando è un codice che sia privo di bug, facile e comprensibile, il che implica semplicità, e che sia facile da mantenere.
Per semplicità, gli esempi saranno riferiti a C e C++, non perché questi linguaggi siano migliori o peggiori di altri, ma perché sono quelli più ampiamente utilizzati. Gli argomenti potrebbero, nel complesso, fare riferimento a Java, Ada o anche altri linguaggi.
Alla base di questo approccio c’è il presupposto che innanzitutto è meglio non scrivere un codice che abbia dei bug. Anche con questo obbiettivo, si possono avere dei bug, quindi il passo successivo è quello di rimuoverli prima che il codice sia compilato. Infine c’è la necessità di valutare quanto bene si stia svolgendo il compito.
Un altro presupposto è che sia meglio risolvere i problemi di bug il prima possibile nel ciclo di sviluppo. È ampiamente evidente che i costi per fissare un bug crescono quasi esponenzialmente quanto più tardi vengono identificati nel ciclo di sviluppo (i costi di un bug trovato quando il prodotto è già sul campo possono, nei casi più estremi, essere causa del fallimento di un’azienda).
Standard di codifica
Un punto di partenza è quello di utilizzare standard di codifica. Non si è interessati alle “Style Guides” – set di regole che prevedono le convenzioni per i nomi e l’indentazione del codice – ma agli standard che aiutano a prevenire che il software faccia cose non desiderate. Questo è in particolare il caso del C e C++ dove la vastità degli standard e la flessibilità che offrono, portano con sé la possibilità che qualcosa che appare essere lecita possa avere conseguenze inaspettate o imprevedibili. Cosi come per ogni linguaggio, come per lo stesso inglese, una frase grammaticalmente lecita può essere ambigua o addirittura senza senso.
Esempi di comportamento indefinito in C includono: dereferenziare un puntatore nullo, divisioni per zero in una espressione, e una funzione che restituisca un collegamento a dati locali non statici. Una linea guida per la programmazione può essere tanto facile quanto una regola omnicomprensiva per evitare tutti i comportamenti indefiniti. Più utili sono le linee guida che richiedono che la proprietà del puntatore sia verificata prima che sia dereferenziato, o che il programma si accerti che il divisore non sia zero.
L’altra causa di bug sono semplici errori di codifica, oppure la formulazione di assunzioni che non sono poi valide riguardo il comportamento del codice oppure non prevedere tutte le conseguenze di una operazione. C e C++ offrono molte possibilità che ciò avvenga, ma dei buoni standard di codifica possono ridurre tutto ciò drasticamente.
I tool di analisi statica del codice che analizzano il software cercando errori di codifica sono utilizzati ormai da diversi anni come sistema per rimuovere i bug. Oggigiorno sono disponibili tool che contengono potenti motori per analizzare il comportamento del programma nel suo insieme. Possono identificare anche utilizzi pericolosi del linguaggio, codici eccessivamente complessi ed evidenziare problematiche che produrranno un codice poco migrabile o difficile da mantenere.
C’è ampia evidenza che i tool di analisi statica del codice sono nettamente migliori nello scovare bug di quanto non lo siano i compilatori. Uno studio condotto da PRQA ha mostrato come “…è dimostrato empiricamente che l’analisi statica è in grado di evidenziare una quantità di warning 25 volte superiore rispetto a tutti e quattro i compilatori [testati].”
http://www.programmingresearch.com/resources/white-papers/
Ambiguità dei compilatori
In effetti, gli stessi compilatori possono essere la causa di ciò che appare come un bug nel codice compilato, come le ambiguità nei linguaggi standard, oppure le opzioni per differenti implementazioni nello standard possono implicare che differenti compilatori possono compilare lo stesso codice ottenendo comportamenti differenti.
In C e C++ l’ordine di valutazione degli operatori tra i punti della sequenza non viene specificato, quindi possono essere valutati in qualsiasi ordine. Se la corretta operazione poggia su un particolare ordine di valutazione, allora si possono insinuare dei bug subdoli.
Per esempio:
x = f1() * f2() + f3();
Lo sviluppatore sta facendo affidamento sulle tre funzioni chiamate nell’ordine, f1, f2 e f3. Infatti l’ordine non è specificato – le funzioni possono essere chiamate in qualsiasi ordine. Si sa dalle regole di precedenza che la moltiplicazione verrà effettuata prima della somma – ma questa è effettuata su valori restituiti dalle funzioni.
Lo sviluppatore decide di correggere il codice:
x = (f1() * f2()) + f3();
Tuttavia, le parentesi non incidono sull’ordine di valutazione degli operatori, ma solo sulla precedenza. Il solo modo per raggiungere questo scopo è quello di chiamare le funzioni separatamente.
Un punto di sequenza è un posto in un programma in cui tutti gli effetti collaterali precedenti hanno avuto luogo. Un punto e virgola è un punto di sequenza e ce ne sono altri. Per esempio gli operatori logici AND e OR (| | e &&). Si consideri il seguente codice:
if ( (x == f1()) || (x == f2()) )
Diversamente dal precedente esempio si sa esattamente in che ordine le funzioni saranno chiamate: f1 sarà assolutamente chiamata per prima. Tuttavia, f2 potrebbe essere chiamata, oppure no. C e C++ hanno una particolare caratteristica chiamata ‘short circuit’ con gli operatori logici. Con un OR se la prima espressione è true, qualsiasi sia il secondo valore, il risultato generale è true – quindi lo standard C dice che non deve essere valutato. Perciò se il programma dipende dal fatto che entrambe f1 e f2 siano chiamate allora il programma potrebbe non funzionare correttamente – dipende dal valore di x e da quello restituito da f1.
Alcuni programmi possono essere scritti per trarre vantaggio da questo, per esempio:
if ( OpenDatabase() && WriteRecord(record) )
WriteRecord sarà chiamata solo se la funzione OpenDatabase ritorna true. Tuttavia si possono avere problemi facendo un semplice errore di battuta:
if ( OpenDatabase() & WriteRecord(record) )
In questo caso entrambe le funzioni saranno chiamate – ma non si sa in che ordine.
Gli strumenti di analisi del codice dovrebbero identificare queste aree di ambiguità, se gli standard di codifica non hanno ancora imposto che, per esempio, le funzioni debbano essere chiamate separatamente.
Nuove categorie di strumenti
Se aggiungete alle cap
acità di rilevamento dei bug di un analizzatore statico del codice anche la capacità di verificare la rispondenza agli standard di codifica, questo crea una nuova categoria di tool – quella dei Coding Standard Enforcement (CSE) tool. Lo stesso studio ha mostrato che un CSE potrebbe identificare molte più violazioni agli standard di codifica rispetto ai compilatori, in alcuni casi con un ordine di grandezza di due o tre volte.
L’analisi del codice è stato uno strumento per garantire un buon codice quasi fin dagli albori dell’informatica. Mentre l’analisi formale del codice, spesso obbligatoria per uno sviluppo safety-critical e con elevata affidabilità, può dimostrarsi un gran dispendio di tempo, persino un’analisi informale “run an eye over this” (“dagli solo un’occhiata”) può essere preziosa nel rilevare problemi con complicazioni più in profondità, come la struttura del programma. Lanciare un’analisi statica del codice e gli strumenti CSE prima della revisione del codice può far risparmiare tempo e permettere all’analisi di concentrarsi sugli obbiettivi generali, senza preoccuparsi delle problematiche minori.
Fig. 1 – QA•Verify, un nuovo strumento di PRQA, lavora con i tool code analysis/CSE e le principali versioni dei prodotti control/code repository per fornire l’accesso a dati di analisi storica, trend, statistiche, e valutazioni quantitative che riflettano la costante qualità del codice base
Finora ci si è occupati del codice nuovo, ma è raro che tutto il codice di un progetto sia nuovo; è sensato riutilizzare del codice legacy, codice di cui è stato verificato il funzionamento. In questo caso è quasi certo che il codice non sarà conforme agli standard di codifica e che facendolo esaminare da un tool CSE emergeranno molti possibili errori. Poiché “sistemarli” comporterebbe sia a un dispendio di tempo che la potenziale aggiunta di bug a un codice che sta funzionando adeguatamente, spesso è meglio lasciare le cose come stanno. Ma potrebbe essere necessario aggiungere codice, effettuare cambiamenti per manutenzione, o aggiungere funzionalità. Una possibilità è quella di confrontare le problematiche di programmazione prima e dopo i cambiamenti e le aggiunte, evidenziando solo le nuove problematiche. PRQA ha sviluppato degli strumenti di analisi che fanno esattamente questo.
Per una buona prassi di progettazione è importante conoscere i trend alla base. Il codice sta migliorando nel tempo? Ci sono particolari problematiche ricorrenti? Queste sono valutazioni quantitative difficili da raccogliere e analizzare, ma molte informazioni sono disponibili nei prodotti version control/code repository. Gli strumenti code repository e version control memorizzano diverse versioni del codice, permettendo cosi agli sviluppatori il roll back alle versioni precedenti, se necessario, oppure di utilizzare una versione precedente del codice come punto di partenza per una differente implementazione. Normalmente uno sviluppatore rileverà il codice dallo store, ci lavorerà e in seguito lo riconsegnerà. È buona prassi subordinare la riaccettazione del codice al superamento di una analisi statica del codice stesso.
QA•Verify, un nuovo strumento di PRQA, lavora con i tool code analysis/CSE e le principali versioni dei prodotti control/code repository per fornire l’accesso a dati di analisi storica, trend, statistiche, e valutazioni quantitative che riflettano la costante qualità del codice base.
Le tecniche e i tool qui analizzati da sole non garantiscono progetti di successo. Tuttavia, specialmente quando sono messe in campo come parte di un ben definito processo di sviluppo, con tool appropriati, a partire dalle specifiche iniziali fino ai test finali e persino al life cycle management del prodotto, possono offrire la sicurezza che il codice sia di elevata qualità.
Contenuti correlati
-
Superare il terahertz gap con un software di simulazione
La simulazione numerica consente di studiare a fondo le nuove tecnologie per laser, rivelatori e assorbitori nel “gap” tra infrarossi e microonde Leggi l’articolo completo su EO 512
-
Ottimizzare elaborazione, rilevamento e controllo general purpose con le MCU Arm Cortex-MO+
Le MCU MSPM0 Arm Cortex-M0+ proposte da Texas Instruments offrono ai progettisti maggiori opzioni, più flessibilità di progettazione e una gamma più ampia di software e strumenti intuivi Leggi l’articolo completo su EO 512
-
Sicurezza: un problema volutamente ignorato
Nel momento in cui le normative e i regolamenti che disciplinano la sicurezza entrano in vigore non solo in Europa, ma in tutto il mondo, le aziende devono necessariamente aggiungere funzioni atte a garantire la sicurezza dei...
-
Come rendere sicuro e semplice l’aggiornamento OTA con TUF
L’ambiente dei dispositivi embedded è ancora il bersaglio di continue minacce. Più un dispositivo è connesso e più funzioni intelligenti offre all’utente, maggiore sarà la “superficie di attacco” per eventuali minacce informatiche Leggi l’articolo completo su Embedded...
-
Come proteggere le soluzioni OT dagli attacchi cyber
I cyberattacchi che hanno inizio nell’ambiente IT possono ora facilmente migrare in un sistema OT non protetto, causando interruzioni di operazioni vitali e rischi eccessivi per la salute e la sicurezza pubblica Leggi l’articolo completo su Embedded...
-
Renesas presenta Quick-Connect Studio per accelerare il ciclo di progettazione
Renesas Electronics ha annunciato la disponibilità di una nuova piattaforma di progettazione di sistemi IoT, online e basata su cloud, che consente agli utenti di progettare, in un ambiente grafico, hardware e software per convalidare rapidamente i...
-
I benefici del “real-time” nelle applicazioni IoT
Nello sviluppo di sistemi embedded, i sistemi operativi real-time, o RTOS, possiedono qualità che stanno giocando un ruolo sempre più importante nell’implementazione di un crescente numero di applicazioni Internet of Things “time-critical” Leggi l’articolo completo su Embedded...
-
Architetture orientate ai servizi per l’industria automotive
Con l’obiettivo di gestire i costi e la complessità dello sviluppo del software automotive, NXP ha introdotto il software Real-Time Drivers (RTD) che supporta tutti i processori automotive S32 con core Arm Cortex-M o Cortex-R52 Leggi l’articolo...
-
Come rendere (e mantenere) sicuri gli apparecchi medicali
Il tradizionale approccio costituito da progettazione e sviluppo, seguiti dal testing prima del lancio del prodotto non è infatti più sufficiente per la gestione di una sicurezza che mantenga la propria efficacia per tutta la vita del...
-
Uno sguardo all’evoluzione del debug
I progressi tecnici che hanno caratterizzato l’industria dei semiconduttori hanno contribuito a modificare il processo di sviluppo del software e di conseguenza anche il debugger, divenuto un vero e proprio tool di processo Leggi l’articolo completo su...