Quando si dovrebbero usare i parametri "out"?

1

In Objective-C, ci sono diversi metodi come initWithContentsOfFile:encoding:error: dove si passa in un riferimento a un oggetto NSError per il parametro error: . In questo esempio, il valore dell'oggetto NSError passato può cambiare in base a ciò che accade al runtime quando viene chiamato il metodo e se il corpo del metodo è stato eseguito in un certo modo. In un certo senso, penso a questo oggetto NSError come una sorta di come un secondo valore di ritorno dal metodo e differisce solo da un oggetto anObject nell'istruzione return anObject; in quanto quando viene chiamata questa istruzione, l'esecuzione lascia il metodo .

Quindi la mia domanda è, non solo nel contesto della gestione degli errori in Objective-C, ma in generale, quando si dovrebbe usare un parametro "out" al posto di restituire detto valore in una dichiarazione di ritorno?

    
posta pasawaya 05.12.2012 - 02:25
fonte

3 risposte

1

Nel caso del metodo NSString initWithContentsOfFile:encoding:error: che citi, un errore viene gestito restituendo nil dall'inizializzatore. Se ciò accade, puoi interrogare l'oggetto error (se ne hai fornito uno) per ottenere dettagli sull'errore.

NSError *error = nil;
NSString *someString = [[NSString alloc] initWithContentsOfFile:somePath encoding:someEncoding error:&error];
if (!someString) {
    // oops - check out the error
} else {
    // continue using the string
}

Fondamentalmente, questo modello di progettazione del metodo deve essere presente perché il valore restituito non può essere utilizzato per fornire informazioni sugli errori. Il tipo restituito deve essere l'oggetto inizializzato (o nil ). Pertanto, l'unica opzione per ottenere informazioni più dettagliate sull'errore è fornire il parametro "out" per l'errore.

Per rispondere alla tua domanda più generale, l'unica volta in cui ho mai utilizzato un parametro "out" è quando il metodo deve restituire un valore primario ma è necessario anche un valore di ritorno secondario.

Non riesco a pensare a nessun metodo void con parametri "out" (nell'SDK di iOS).

NSString ci fornisce un esempio di non errore con l'inizializzatore initWithContentsOfFile:usedEncoding:error: . Il parametro usedEncoding è un parametro "out". Il valore di ritorno primario è la stringa. Il valore di ritorno secondario è la codifica utilizzata per convertire il file in una stringa.

    
risposta data 05.12.2012 - 03:14
fonte
0

IMO (enfasi su O), dovresti evitare i parametri ogni volta che puoi. Non so nulla di Objective-C, ma se fosse Java avresti lanciato un'eccezione invece di usare un parametro out.

Sono state create eccezioni per mantenere la tua logica eccezionale fuori dal normale controllo del flusso. In teoria, questo rende il codice più facile da leggere perché non deve apparire come questo:

Object something = doSomething();
if (something == isValid())
    Object somethingElse = doSomethingElse();
    if (somethingElse == isValid())
        ...
    else
        //handle what happens when "something else" goes wrong
else
    //handle what happens when "something" goes wrong

Invece, può assomigliare a questo:

try {
   Object something = doSomething();
   Object somethingElse = doSomethingElse();
   ...
} catch (SomethingException e) {
    //handle what happens when "something" goes wrong
} catch (SomethingElseException e) {
    //handle what happens when "something else" goes wrong
}

Quello che mi piace di quest'ultimo è che il flusso tipico può essere letto in sequenza.

You do something, then you do something else, then you ...

Con il primo esempio, la gestione degli errori è tutta confusa con quella logica invece che fuori mano nella remota possibilità che ciò accada.

Se Objective-C ha delle eccezioni, penso che l'API sarebbe stata scritta meglio se le avesse usate in questo caso. Se non li ha, presumo che abbia almeno Oggetti. Potrebbe aver restituito un tipo di oggetto risposta che è possibile interrogare per scoprire se la risposta ha avuto errori.

    
risposta data 04.01.2013 - 02:16
fonte
-1

Questo, per me, assomiglia a una scarsa scelta iniziale di progettazione dell'API che non avrebbe potuto essere corretta senza rompere un sacco di binari esistenti.

È abbastanza normale che se una funzione fa qualcosa che potrebbe fallire, allora il successo / fallimento è contrassegnato dal valore di ritorno, e se qualcos'altro deve essere restituito è fatto attraverso un parametro che è passato per riferimento.

Il modo in cui viene definito il tuo esempio non fa nulla (che io possa vedere) per rendere la vita dello sviluppatore più facile, a meno che non sia il tipo di sviluppatore che si assume che nulla possa andare storto. Neanche io sono sicuro di come gli strumenti di analisi statica possano far fronte a questa convenzione.

    
risposta data 05.12.2012 - 02:49
fonte