L'affectation dans une clause conditionnelle est-elle un bon style ruby?
Pour é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é dans le 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 question SO, et le restera dans 1.9, selon Matz ( http://redmine.ruby-lang.org/issues/show/1141).
Compte tenu de la confusion possible de l'affectation et de la comparaison, cela rend-il trop difficile de lire le code?
7 réponses
Cette question a été posée il y a un certain temps, et toutes les réponses sont obsolètes.
Il est explicitement bon style d'utiliser des affectations dans des conditions. Si vous le faites, enveloppez 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 communautaire pour plus d'Informations
La réponse précédemment acceptée dit utiliser le mot clé and
. N'utilisez jamais les mots-clés and
ou or
dans ruby. C'est aussi dans le guide de style, et il y a de très bonnes raisons logiques de ne pas utiliser ils.
Unun peu idiome répandu est d'utiliser and
, qui ressemblerait à quelque chose comme 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 avez réellement signifiait pour assigner au lieu de comparer:
unless (tmp = method_call_that_might_return_nil).nil?
do_something_with tmp
end
Le 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 mainteneurs. Je pense que nous venons assez de milieux dans lesquels nous avons eu des affectations accidentelles dans des blocs if
(quand nous voulions avoir une comparaison d'Égalité) que nous préférons les styles dans lesquels il est absolument clair que l'affectation est destinée, plutôt que la comparaison. L'idiome .nil?
déjà mentionné a cette propriété, et je le considérerais plus propre que d'avoir l'affectation nue dans la condition if
. Vraiment, cependant, je ne vois pas le mal à avoir la ligne de code supplémentaire pour la mission.
La fonctionnelle de la programmation façon de le faire est d'utiliser andand
. C'est un moyen lisible de chaîner les appels de méthode afin qu'un nil 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
Les programmeurs C le font beaucoup. Je ne vois pas non plus de problème avec Ruby tant qu'il est clair ce qui se passe.
Ouais, je dirais que c'est un mauvais style en raison de la confusion possible entre l'affectation et la comparaison. Ce n'est qu'une ligne de plus à assigner puis à tester, et cela évite que quelqu'un à l'avenir pense que c'était un bug et le corrige pour utiliser ==
à la place.
Je pense que c'est bon. L'Aversion pour l'affectation dans une condition vient de savoir qu'un coup de touche manqué lors de la frappe = = transforme une comparaison en une affectation involontaire. Une interdiction stylistique d'utiliser l'affectation dans une condition fait que de tels accidents se distinguent comme à l'œil (et parfois au langage, comme en C, où de nombreux compilateurs peuvent émettre un avertissement s'ils rencontrent une affectation dans une condition). D'autre part, les tests font également ressortir de tels accidents. Si votre code est bien couvert par des tests, vous pouvez envisager de jeter de telles interdictions.