Separa il valore della variabile dal codice di errore usando struct

2

Diciamo che ho una funzione che calcola un output del sensore, tutti i valori sono > = 0, ma devo anche rilevare alcune situazioni di errore come "NO_POWER" che ho codificato con il valore "-65500". Sulla mia applicazione ci sono classi che si preoccupano solo del valore di output reale (indipendentemente dal fatto che sia presente un errore) e di altre classi che richiedono il valore reale e il codice di errore corretto. Quindi, in termini di design, mi è venuta l'idea di dover separare il concetto di "valore" e "codice di errore", ho trovato 2 opzioni:

Valore restituito e codice di errore nello stesso output (le classi client dovranno sapere come interpretare il valore di output):

double Sensor::compute() {
   double output = compute();
   return output;
}

o usare una struttura per recuperare l'output:

struct SensorOutput {
   double value;
   int error_code;
}

quindi il mio metodo potrebbe essere simile a:

SensorOutput Sensor::compute() {
   double output = compute();
   int errorCode = get_error_code();
   SensorOutput out;
   out.value = output;
   out.error_code = errorCode;
}

Quale è meglio in termini di design?

    
posta EzeEst 25.09.2018 - 14:48
fonte

2 risposte

3

Prima di tutto, presumo che l'uso di eccezioni per segnalare quegli errori sia fuori questione (o perché non si desidera utilizzare eccezioni, o quegli errori sono considerati parte del flusso "normale" del programma per una ragione o un altro).

Suggerirei caldamente il secondo approccio. Se dovessi usare un risultato -65500 come codice per indicare "c'è stato errore XYZ", stai effettivamente mescolando due contesti separati: il risultato normale di Sensor::compute() e gli errori di segnalazione. Immagina che - a causa di una modifica dei requisiti - Sensor::compute() dovrebbe essere in grado di restituire valori negativi ... ma quelli sono ora già riservati per i tuoi "codici di errore" - e inaspettatamente hai un problema.

Inoltre è necessario cospargere il codice con le chiamate lungo la linea di

if (sensorValue == ERROR_CODE_ABC)
    //Error handling
else if (sensorValue == ERROR_CODE_DEF)
    //More Error handling
else
    doStuffWithValue(sensorValue);

E rischi sempre la possibilità di lavorare con un valore errorCode invece di un valore reale, perché hai perso un posto per un controllo (la nuova tensione target per il PSU è -65500V ... ummm, non va bene). Ahimè, anche il secondo approccio non può liberarti completamente da questo carico: potresti essere in grado di usare valori più sani / sicuri (il sensore ha NO_POWER, quindi la tensione misurata è 0V), ma devi comunque controllare sensorValue.errorCode ogni volta - solo eccezioni sarebbero in grado di aiutarti (se dimentichi di gestirli da qualche parte, per terminare il programma, invece di lasciarti lavorare con valori fasulli, causando errori difficili da tracciare)

    
risposta data 25.09.2018 - 17:02
fonte
1

L'altro approccio sarebbe boost :: facoltativo o (se il compilatore lo supporta) std :: facoltativo. Un opzionale può o non può avere un valore. Non so se questo funzionerebbe bene per te come struct, ma è meno sbagliato.

    
risposta data 25.09.2018 - 17:15
fonte

Leggi altre domande sui tag