2010-08-06 15 views
17

Alcune persone considerano dichiarazioni di reso multiple come uno stile di programmazione errato. Mentre questo è vero per i metodi più grandi, non sono sicuro che sia accettabile per quelli brevi. Ma c'è un'altra domanda: dovrebbe essere scritto esplicitamente else, se c'è una dichiarazione di ritorno nel precedente if?Ritorno da un metodo con "altro" implicito o esplicito o con una singola istruzione "return"?

implicito else:

private String resolveViewName(Viewable viewable) { 
    if(viewable.isTemplateNameAbsolute()) 
     return viewable.getTemplateName(); 
    return uriInfo.getMatchedResources().get(0).getClass().toString(); 
} 

esplicita else:

private String resolveViewName(Viewable viewable) { 
    if(viewable.isTemplateNameAbsolute()) 
     return viewable.getTemplateName(); 
    else 
     return uriInfo.getMatchedResources().get(0).getClass().toString(); 
} 

Tecnicamente else non è necessario qui, ma rendere il senso più evidente.

E forse l'approccio più pulito con un solo ritorno:

private String resolveViewName(Viewable viewable) { 
    String templateName; 
    if(viewable.isTemplateNameAbsolute()) 
     templateName = viewable.getTemplateName(); 
    else 
     templateName = uriInfo.getMatchedResources().get(0).getClass().toString(); 
    return templateName; 
} 

Quale preferisce? Altri suggerimenti?

+3

Una dichiarazione singolo di ritorno non è di solito neccessary per un bel metodo breve come questo dato che avere due è leggibile e, di solito, a m e almeno, più logico nella maggior parte delle situazioni. – Nobody

+7

Mentre l'uso di altro è semplicemente un problema di materia, trovo questa catena mostruosa 'uriInfo.getMatchedResources(). Get (0) .getClass(). ToString()' più preoccupante. Questo semplicemente urla per Eccezioni a un certo punto che probabilmente dovrebbe essere meglio evitato con alcuni controlli extra. – x4u

+0

"Alcune persone considerano dichiarazioni di reso multiple come cattivo stile di programmazione." vedi http: // StackOverflow.it/questions/36707/should-a-function-have-only-one-return-statement – Raedwald

risposta

22

Altri suggerimenti ovvi: utilizzare l'operatore condizionale.

private String resolveViewName(Viewable viewable) { 
    return viewable.isTemplateNameAbsolute() 
     ? viewable.getTemplateName() 
     : uriInfo.getMatchedResources().get(0).getClass().toString(); 
} 

Per i casi in cui questo non è fattibile, sono quasi certamente incoerente. Non mi preoccuperei troppo di questo, ad essere onesti - non è il tipo di cosa in cui la leggibilità è come essere significativamente influenzata in entrambi i modi, ed è improbabile che introduca bug.

(D'altra parte, ho sarebbe suggerirei di usare le parentesi per tutti if blocchi, anche quelli singola istruzione.)

+0

Devo essere d'accordo con usare sempre le parentesi graffe (ho cambiato la mia risposta per riflettere), anche se di solito lasciavo che Eclipse lo gestisse per me con autoformat + salva azioni. –

+0

+1 - anche se penso che tu abbia un paren molto vicino. – Carl

+0

@Carl: corretto, grazie. –

4

solito preferisco la prima opzione dal momento che è la più breve.

E penso che ogni programmatore decente dovrebbe rendersi conto di come funziona senza che io debba scrivere il resto o utilizzare un singolo ritorno alla fine.

Inoltre ci sono casi nei metodi lunghi in cui si potrebbe aver bisogno di fare qualcosa di simile

if(!isValid(input)) { return null; }// or 0, or false, or whatever 
// a lot of code here working with input 

trovo che sia ancora più chiaro come questo fatto per questi tipi di metodi.

3

Dipende dall'intenzione. Se il primo ritorno è un salvataggio rapido, allora andrei senza lo else; se OTOH è più come uno scenario "return this or that", allora userei else. Inoltre, preferisco una dichiarazione di ritorno anticipato su dichiarazioni o variabili infinitamente annidate if che esistono al solo scopo di ricordare un valore di ritorno. Se la tua logica fosse leggermente complessa, o anche come è ora, prenderei in considerazione l'idea di mettere i due modi di generare il valore di ritorno in funzioni dedicate, e usare un if/else per chiamare entrambi.

0

Certo, le persone hanno molto da dire sullo stile di programmazione, ma non essere così preoccupato di qualcosa di relativamente banale per lo scopo del programma.

Personalmente, mi piace andare senza il resto. Se qualcuno sta esaminando il tuo codice, è molto probabile che non sarà troppo confuso senza il resto.

1

Preferisco il primo.

Oppure ... è possibile utilizzare if return else return per biforcazioni altrettanto importanti e if return return per casi speciali.

Quando si hanno asserzioni (if p==null return null), il primo è il più chiaro di gran lunga. Se hai opzioni ugualmente ponderate ... trovo bene usare l'altro esplicito.

0

Preferisco la seconda opzione perché per me è la più veloce da leggere.

Eviterei la terza opzione perché non aggiunge chiarezza o efficienza.

La prima opzione va bene, ma almeno metterei una riga vuota tra il primo bit (il se e il suo ritorno rientrato) e la seconda dichiarazione di ritorno.

Alla fine, si tratta di preferenze personali (come molte cose nello stile di programmazione).

6

preferisco l'approccio più pulito con ritorno singolo. Per me il codice è leggibile, manutenibile e non confuso. Domani se è necessario aggiungere alcune linee al blocco if o else è facile.

1.) il codice non dovrebbe mai essere intelligente.

1

È completamente una questione di preferenze personali - ho letteralmente attraversato fasi di fare tutte e 4 le opzioni (inclusa quella pubblicata da Jon Skeet) - nessuna di esse è sbagliata, e non ho mai avuto alcun svantaggio come un risultato dell'utilizzo di uno di essi.

3

Preferisco rendimenti multipli in una struttura if-else quando la dimensione di entrambe le istruzioni è circa uguale, il codice sembra più bilanciato in questo modo. Per le espressioni corte uso l'operatore ternario. Se il codice per un test è molto più breve o è un caso eccezionale, potrei usare un singolo se il resto del codice rimane nel corpo del metodo.

Cerco di evitare di modificare le variabili il più possibile, perché penso che rende il codice molto più difficile da seguire rispetto a più uscite da un metodo.

+0

+1 per la differenza tra percorsi di codice ugualmente validi e condizioni di protezione eccezionali. – ILMTitan

0

Considerare dichiarazioni di reso multiple "cattivo stile" è un errore lungo, lungo e screditato. Possono rendere il codice molto più chiaro e più gestibile rispetto alle variabili del valore di ritorno esplicito. Soprattutto in metodi più grandi.

Nel tuo esempio, considererei la seconda opzione più pulita perché la struttura simmetrica del codice riflette la sua semantica, ed è più breve ed evita la variabile non necessaria.

1

Le informazioni su una sola dichiarazione di ritorno risalgono agli anni '70, quando Dijkstra e Wirth selezionavano la programmazione strutturata. Lo hanno applicato con grande successo per controllare le strutture, che ora si sono stabilizzate secondo la loro prescrizione di una entrata e una uscita. Fortran aveva più voci in una subroutine (o forse una funzione, mi dispiace, circa 35 anni da quando ne ho scritte), e questa è una caratteristica che non ho mai perso, anzi, non credo di averlo mai usato.

Non ho mai effettivamente riscontrato questa "regola" applicata ai metodi al di fuori del mondo accademico, e davvero non riesco a capire il punto. Fondamentalmente devi offuscare considerevolmente il tuo codice per obbedire alla regola, con variabili extra e così via, e non c'è modo in cui puoi convincermi che è una buona idea. Curiosamente, se lo scrivi in ​​modo naturale come per la tua prima opzione, il compilatore di solito genera il codice in base alla regola comunque ...quindi puoi obiettare che la regola viene rispettata: non solo da te ;-)

2

Mantieni il gergo coerente e leggibile per il programmatore comune più basso che potrebbe dover rivisitare il codice in futuro.

Solo poche lettere in più per digitare il resto e non fa alcuna differenza se non la leggibilità.

6

Il dogma "single point of exit" deriva dai giorni di programmazione strutturata.

Ai suoi tempi, la programmazione strutturata era una BUONA COSE, specialmente come alternativa al codice spaghetti GOTO, che era prevalente nel codice Fortran e Cobol vintage degli anni '60 e '70. Ma con la popolarità di linguaggi come Pascal, C e così via con la loro gamma più ricca di strutture di controllo, la Programmazione Strutturata è stata assimilata alla programmazione mainstream e alcuni aspetti dogmatici sono caduti in disgrazia. In particolare, la maggior parte degli sviluppatori è felice di avere più uscite da un ciclo o un metodo ... a condizione che questo faciliti la comprensione del codice.

La mia sensazione personale è che in questo caso particolare, la simmetria della seconda alternativa lo rende più facile da capire, ma la prima alternativa è quasi leggibile. L'ultima alternativa mi sembra inutilmente prolissa e meno leggibile.

Ma @Jon Skeet ha sottolineato che esiste un problema stilistico molto più significativo con il codice; cioè l'assenza di {} blocchi attorno alle affermazioni "allora" e "altro". Per me il codice in realtà dovrebbe essere scritto in questo modo:

private String resolveViewName(Viewable viewable) { 
    if (viewable.isTemplateNameAbsolute()) { 
     return viewable.getTemplateName(); 
    } else { 
     return uriInfo.getMatchedResources().get(0).getClass().toString(); 
    } 
} 

Questo non solo è una questione di codice di grazia. C'è in realtà un punto serio per usare sempre i blocchi. Considerate questo:

String result = "Hello" 
if (i < 10) 
    result = "Goodbye"; 
    if (j > 10) 
     result = "Hello again"; 

A prima vista, sembra che risultato sarà "Ciao di nuovo", se i è inferiore a 10 e j è maggiore di 10. In realtà, questo è un travisamento - siamo stati ingannati da indentazione errata. Ma se il codice fosse stato scritto con { } attorno alle parti allora, sarebbe chiaro che il rientro era sbagliato; per esempio.

String result = "Hello" 
if (i < 10) { 
    result = "Goodbye"; 
    } 
    if (j > 10) { 
     result = "Hello again"; 
    } 

Come si vede, il primo } spicca come un pollice irritato e ci dice di non fidarsi del rientro come un segnale visivo a quello che significa il codice.

1

Poiché hai chiesto altri suggerimenti, come su

Usa asserisce o RuntimeExceptions

private String resolveViewName(Viewable viewable) { 
    if(viewable.isTemplateNameAbsolute()) 
     return viewable.getTemplateName(); 
    else 
     return uriInfo.getMatchedResources().get(0).getClass().toString(); 
    throw new RuntimeException ("Unreachable Code") ; 
    } 

Usa la parola finale

private String resolveViewName(Viewable viewable) { 
final String templateName; 
if(viewable.isTemplateNameAbsolute()) 
    templateName = viewable.getTemplateName(); 
else 
    templateName = uriInfo.getMatchedResources().get(0).getClass().toString(); 
return templateName; 
} 
+0

'finale' è una buona aggiunta. – deamon

+0

Perché hai aggiunto questo RuntimeException? – DerMike

+0

@DerMike Credo che, a causa dei precedenti resi, RuntimeException non sia raggiungibile. Se viene lanciato, saprò che mi sono sbagliato. – emory

Problemi correlati