2009-12-27 10 views
33

Per scrivere in modo più conciso, piuttosto che fare questo:L'assegnazione è in una clausola condizionale di stile rubino buono?

test_value = method_call_that_might_return_nil() 
if test_value 
    do_something_with test_value 
end 

Ho assegnando al condizionale:

if test_value = method_call_that_might_return_nil() 
    do_something_with test_value 
end 

È questo il cattivo stile? La sintassi ancora più concisa-:

do_something_with test_value if test_value = method_call_that_might_return_nil() 

non è consentita, come discusso in another SO question, e rimarrà così a 1,9, secondo Matz (http://redmine.ruby-lang.org/issues/show/1141).

Data la possibile confusione di assegnazione e confronto, questo rende troppo difficile leggere il codice?

+0

Penso che si debba tracciare una linea tra concisione e comprensibilità. Penso che al giorno d'oggi, dove dobbiamo conoscere diverse lingue, è una buona idea usare nuove fantastiche funzionalità di alcune lingue senza danneggiare la conoscenza del programmatore esistente. In qualità di programmatore esperto, perché dovrei aver bisogno di google tale adattabilità sintattica dalla lingua alla lingua? Preferirei passare il tempo a googling sul problema in questione. Ad esempio, come multithread in ruby. –

+1

Rubocop e questa guida in stile rubino consiglia di evitarlo: https://github.com/bbatsov/ruby-style-guide – Rimian

+0

Link alla parte specifica della guida di stile: https://github.com/bbatsov/ruby-style -guide # Assegnazione sicura -in-condizione –

risposta

14

Questa domanda è stata posta QUITE qualche tempo fa, e tutte le risposte non sono aggiornate.

È esplicitamente BUONA stile utilizzare i compiti in condizionali. In tal caso, racchiudi la condizione tra parentesi.

# Bad 

if value = Settings.get('test_setting') 
    perform_action(value) 
end 

# Okay, but uncommon and verbose 

value = Settings.get('test_setting') 
if value 
    perform_action(value) 
end 

# Good 

if (value = Settings.get('test_setting')) 
    perform_action(value) 
end 

See the community style guide for more information

La risposta precedentemente accettato detto di utilizzare la parola chiave and. Non utilizzare mai le parole chiave and o or in ruby. Questo è anche nella guida allo stile e ci sono ottimi motivi logici per non usarli.

1

Sì, direi che è cattivo stile a causa della possibile confusione tra assegnazione e confronto. È solo una riga in più da assegnare e poi testare, ed evita che qualcuno in futuro pensi che sia un bug e lo aggiusta per usare ==.

26

Uno po diffuso linguaggio è quello di utilizzare and, che sarebbe simile a questa:

tmp = method_call_that_might_return_nil and do_something_with tmp 

Un'altra possibilità sarebbe quella di chiamare #nil? esplicitamente, in questo modo l'intento diventa un po 'più chiara; in particolare è davvero evidente che in realtà dire per assegnare invece di confrontare:

unless (tmp = method_call_that_might_return_nil).nil? 
    do_something_with tmp 
end 
7

codice conciso è il codice non è necessariamente migliore. La concisione è utile quando migliora la comunicazione del comportamento previsto del codice dall'autore ai futuri manutentori. Penso che un numero sufficiente di noi provenga da background in cui abbiamo avuto incarichi accidentali nei blocchi if (quando intendevamo avere un confronto di uguaglianza) che preferiamo stili in cui è assolutamente chiaro che si intende l'assegnazione, piuttosto che il confronto. L'idioma .nil? già menzionato ha quella proprietà, e lo considererei più pulito rispetto all'assegnazione nuda all'interno della condizione if. Davvero, però, non vedo il danno nell'avere la linea di codice aggiuntiva per il compito.

2

I programmatori C fanno molto. Non vedo un problema con esso in Ruby, purché sia ​​chiaro cosa sta succedendo.

+3

Il problema è che ruby ​​emette un avviso ogni volta che lo assegni in modo condizionale. Se così non fosse, ho il sospetto che sarebbe così popolare nel rubino come lo è in C. –

1

Penso che vada bene. Avversione per l'assegnazione in una condizione deriva dal sapere che un tratto chiave persa durante la digitazione == trasforma un confronto in un incarico non intenzionale. Un divieto stilistica di utilizzare l'assegnazione in una condizione rende tali incidenti si distinguono come per gli occhi (e, talvolta, alla lingua, come in C, dove molti compilatori può essere fatto per emettere un avviso se incontrano un incarico in una condizione). D'altra parte, i test fanno anche risaltare tali incidenti. Se il tuo codice è ben coperto dai test, puoi considerare di scartare tali divieti.

5

Il modo funzionale programmazione per effettuare questa operazione è quello di utilizzare andand. È un modo leggibile di concatenazione chiamate di metodo in modo che un trascurabile della centrale si arresta la catena. Quindi il tuo esempio sarebbe qualcosa del tipo:

method_call_that_might_return_nil.andand.tap {|obj| do_something_with obj} 
## or, in the common case: ## 
method_call_that_might_return_nil.andand.do_something