La risposta di DW è ottima , ma vorrei espandermi su un punto. Una specifica non è solo un riferimento rispetto al quale viene verificato il codice. Uno dei motivi per avere una specifica formale è convalidarlo dimostrando alcune proprietà fondamentali. Naturalmente, la specifica non può essere completamente convalidata: la convalida sarebbe complessa come la specifica stessa, quindi sarebbe un processo senza fine. Ma la convalida ci consente di ottenere una garanzia più forte su alcune proprietà critiche.
Ad esempio, supponiamo che stai progettando un pilota automatico per auto. Questa è una cosa piuttosto complessa che coinvolge molti parametri. Le proprietà di correttezza dell'autopilota includono cose come "l'auto non si schianterà contro un muro" e "l'auto guiderà dove gli viene detto di andare". Una proprietà come "l'auto non si schianterà contro un muro" è davvero molto importante, quindi vorremmo dimostrarlo. Poiché il sistema funziona nel mondo fisico, dovrai aggiungere alcuni vincoli fisici; la proprietà effettiva del sistema computazionale sarà qualcosa del tipo "in base a questi presupposti riguardanti la scienza dei materiali e questi presupposti riguardanti la percezione degli ostacoli da parte dei sensori dell'auto, l'auto non si schianterà contro un muro". Ma anche così, il risultato è una proprietà relativamente semplice che è chiaramente desiderabile.
Potresti provare questa proprietà dal codice? In definitiva, è quello che sta succedendo, se stai seguendo un approccio completamente formale¹. Ma il codice ha molte parti diverse; i freni, le telecamere, il motore, ecc. sono tutti controllati autonomamente. Una proprietà di correttezza dei freni sarebbe qualcosa del tipo "se il segnale" applica freni "è attivo, allora i freni vengono applicati". Una proprietà di correttezza del motore sarebbe "se il segnale della frizione è spento, allora il motore non sta guidando le ruote". Ci vuole una visione di altissimo livello per metterli tutti insieme. Una specifica crea uno strato intermedio in cui i diversi componenti del sistema possono essere articolati insieme.
In effetti, un sistema così complesso come un pilota automatico per auto avrebbe diversi livelli di specifiche con quantità variabili di perfezionamenti. Nel progetto viene spesso utilizzato un approccio di perfezionamento: iniziare con alcune proprietà di alto livello come "l'auto non si schianterà contro un muro", quindi capire che ciò richiede sensori e freni e elaborare alcuni requisiti di base per i sensori, i freni e il software pilota, quindi perfezionare nuovamente quei requisiti di base in un progetto del componente (per il sensore, avrò bisogno di un radar, un DSP, una libreria di elaborazione delle immagini, ...), ecc. In un processo di sviluppo formale, ogni livello di specifica ha dimostrato di soddisfare i requisiti stabiliti dal livello sopra di esso, dalle proprietà di livello più alto fino al codice.
È impossibile essere sicuri che le specifiche siano corrette. Ad esempio, se hai sbagliato la fisica, i freni potrebbero non essere efficaci anche se la matematica che collega il codice freno ai requisiti formali è corretta. Non serve dimostrare che le rotture sono efficaci con 500 kg di carico se si hanno effettivamente 5000 kg. Ma è più facile vedere che 500 kg sono sbagliati che vedere all'interno del codice dei freni che non saranno abbastanza buoni per i parametri fisici della macchina.
¹ Il contrario di un approccio completamente formale è "Immagino che funzioni, ma non posso esserne sicuro". Quando ci scommetti la vita, non sembra così bello.