web-dev-qa-db-fra.com

L'affectation dans une clause conditionnelle est-elle bonne Ruby style?

Afin d'écrire de manière plus concise, plutôt que de faire ceci:

test_value = method_call_that_might_return_nil()
if test_value
  do_something_with test_value
end

J'ai assigné au conditionnel:

if test_value = method_call_that_might_return_nil()
  do_something_with test_value
end

Est-ce un mauvais style? La syntaxe encore plus concise:

do_something_with test_value if test_value = method_call_that_might_return_nil()

n'est pas autorisé, comme discuté dans une autre SO question , et le restera en 1.9, selon Matz ( http: //redmine.Ruby -lang.org/issues/show/1141 ).

Compte tenu de la confusion possible entre l'attribution et la comparaison, cela rend-il trop difficile la lecture du code?

47
TimH

Il est explicitement bon d'utiliser des affectations dans des conditions. Si vous le faites, mettez la condition entre parenthèses.

# 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

Voir le guide de style de la communauté pour plus d'informations

32
Devon Parsons

Un quelque pe idiome répandu est d'utiliser and, qui ressemblerait à ceci:

tmp = method_call_that_might_return_nil and do_something_with tmp

Une autre possibilité serait d'appeler #nil? explicitement, de cette façon l'intention devient un peu plus claire; en particulier, il est vraiment évident que vous signifiait assigner au lieu de comparer:

unless (tmp = method_call_that_might_return_nil).nil?
  do_something_with tmp
end
28
Jörg W Mittag

Un code concis n'est pas nécessairement un meilleur code. La concision est utile lorsqu'elle améliore la communication du comportement de code prévu de l'auteur aux futurs responsables. Je pense que nous sommes suffisamment issus de milieux dans lesquels nous avons eu des affectations accidentelles dans des blocs if (alors que nous voulions avoir une comparaison d'égalité) pour que nous préférions des styles dans lesquels il est absolument clair que l'affectation est destinée, plutôt que Comparaison. Le .nil? idiom déjà mentionné a cette propriété, et je la considérerais plus propre que d'avoir l'affectation nue dans la condition if. Vraiment, cependant, je ne vois pas le mal d'avoir la ligne de code supplémentaire pour l'affectation.

8
Aidan Cully

La méthode de programmation fonctionnelle pour ce faire est d'utiliser andand . C'est une manière lisible de chaîner les appels de méthode afin qu'un nul au milieu arrête la chaîne. Donc, votre exemple serait quelque chose comme:

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
5
Chuck

Ouais, je dirais que c'est un mauvais style en raison de la confusion possible entre l'affectation et la comparaison. Il ne s'agit que d'une ligne de plus à attribuer, puis à tester, et cela évite que quelqu'un dans le futur pense que c'était un bogue et le corrige pour utiliser == au lieu.

3
Brian Campbell

Les programmeurs C font beaucoup cela. Je ne vois pas de problème avec ça dans Ruby non plus tant que ce qui se passe est clair.

2
horseyguy

Je pense que ça va. L'aversion pour l'affectation dans une condition vient du fait de savoir qu'un coup de touche manqué lors de la saisie == transforme une comparaison en affectation involontaire. Une interdiction stylistique d'utiliser l'affectation dans une condition fait ressortir de tels accidents comme aux yeux (et parfois au langage, comme en C, où de nombreux compilateurs peuvent être amenés à émettre un avertissement s'ils rencontrent une affectation dans une condition). D'un autre côté, les tests font également ressortir ces accidents. Si votre code est bien couvert par les tests, vous pouvez envisager de supprimer ces interdictions.

1
Wayne Conrad