Nei sistemi safety-critical esistono coding standards e regole di engineering resi obbligatori dalle varie
normative internazionali. La più blanda e probabilmente più nota anche i non addetti tra tali raccomandazioni normative è la
MISRA/C 2012, la quale al proposito si esprime come segue:
Dir 4.7 (Required) "If a function returns error information, then that error information shall be tested."
Exception: If it can be shown, for example by checking arguments, that a function cannot return an error indication, then there is no need to perform a check.
Dir 4.11 (Required) "The validity of values passed to library functions shall be checked."
Da tali direttive di codifica scaturisce poi la regola:
Rule 17.7 (Required, Decidable, STU) "The value returned by a function having a non-void type shall always be used."
Tali regole sono inoltre ampiamente rafforzate dalla pratica del Design by Contract ideato da Bertrand Meyer (nativamente supportato da linguaggi per applicazioni ad altissima affidabilità, come Eiffel e Ada, come pure da appositi framework o preprocessori C), che richiede di stabilire formalmente un
contratto tra funzione chiamata e chiamante, con obblighi da rispettare per ambo le parti nel passaggio di parametri e nella eventuale restituzione di valori.
Da notare, a margine, il fatto che in molti standard di codifica C proprietari adottati dalle più grandi multinazionali che gestiscono il mercato dei sistemi altamente critici esiste una direttiva del tipo "
Functions type must exclusively be either void or boolean, where the boolean type will feed back the caller with the information about the absence or presence of any error.".
Colgo l'occasione da ricordare che i coding standards di cui si parla (soprattutto quelli a livello entry come MISRA/C) non sono assolutamente appannaggio esclusivo delle torri d'avorio dove opera la ristretta elite dei professionisti dei sistemi safety-critical, che hanno completato un ciclo di studi non inferiore a 12-15 anni tra accademia e corsi interni prima di metter mano al più banale dei progetti nel nostro ambito. Con opportune variazioni e compromessi, si tratta di regole la cui adozione (e verifica automatica tramite appositi parser e checker) apporta un netto beneficio alla qualità di codifica di un qualsiasi programmatore quadratico medio.
Non a caso le norme MISRA/C e gli standard di codifica
NASA (che in gran parte si basano su dette norme, ricorsivamente) sono strettamente alla base anche dei pochi coding standards mirati esclusivamente al mass market e ai sistemi mainstream, come quello elaborato dal
(ad ulteriore conferma di quanto si va ripetendo da almeno vent'anni, da quando sono esplose talune mode, ossia che un software ingegneristicamente robusto è anche automaticamente un software sicuro, nelle accezioni comunemente diffuse in letteratura).
I tempi in cui il footprint di un'applicazione era soggetto a limitazioni talmente drastiche da sconsigliare l'adozione generalizzata delle regole sopra esposte sono tramontati da decenni, perfino nel mondo dei sistemi embedded entry level. Oramai gli unici a sostenere la tendenza suicida di trascurare sistematicamente i controlli "per aumentare la leggibilità" in nome di principi empirici assolutamente esilaranti (come la "regola" che una funzione debba rientrare in una singola schermata), con l'ovvio effetto di lasciare andare in crash l'applicazione al minimo errore di allocazione o di I/O per aver "risparmiato" un paio di if() e un early exit, sono i cialtroni dell'agile. Ciò si pone, come si vede, apertamente in rotta di collisione con i pirincipi più saldi del software engineering, dei quali ho appena dato un breve ma significativo assaggio.