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?

39
demandé sur Community 2009-12-27 21:03:15

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.

24
répondu Devon Parsons 2017-10-06 12:29:30

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
26
répondu Jörg W Mittag 2009-12-27 19:15:04

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.

8
répondu Aidan Cully 2009-12-27 19:43:30

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
5
répondu Chuck 2009-12-27 23:39:19

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.

2
répondu horseyguy 2009-12-27 20:53:21

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.

1
répondu Brian Campbell 2009-12-27 18:06:58

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.

1
répondu Wayne Conrad 2009-12-27 23:17:39