2010-11-18 7 views
4

je trouve moi-même faire ce qui suit beaucoup pour définir les valeurs de retour des méthodes de rubis:les meilleures pratiques pour les valeurs de retour des méthodes de rubis

def foo 
    val = (some expression) 
    val 
end 

Cela semble toujours un peu artificiel. Quelle est la meilleure pratique ici?

+0

Ceci est trop subjectif. Ruby vous permet de placer la valeur de retour à la dernière ligne de la méthode - vous pouvez l'utiliser. Parfois, vous ne pouvez pas l'utiliser. Parfois, vous ne voulez pas l'utiliser. Vous pouvez faire ce que vous voulez ... Ce n'est pas une pratique BEST. – Nakilon

Répondre

11

Il n'est pas nécessaire de l'enregistrer dans une variable sauf si (une expression) est lourde et sera appelée plusieurs fois. Dans ce cas, vous pourriez vouloir le mettre en cache.

Je voudrais aller avec soit:

def foo 
    (some expression) 
end 

ou pour la mise en cache:

def foo 
    @val ||= (some expression) 
end 
+0

Merci pour cette réponse, c'est exactement correct. –

1

Tant que votre dernière expression évalue celle que vous voulez retourner, vous êtes en sécurité.

def foo 
    val = (some expression) 
end 

est identique à celui de la question qu'il évalue à (some expression), tout comme le ferait val.

+1

'def foo; (une expression) end' – Nakilon

+0

@Nakilon Dans sa forme la plus courte, oui. Seul Kevin sait ce qu'il veut faire dans ses fonctions. :) – pestaa

+0

Merci à vous deux. Je sais que c'est une question simple, mais j'apprécie que vous preniez le temps de clarifier. Merci! –

9

Notez que comme de Ruby 1.9, vous pouvez utiliser Object#tap pour enregistrer une valeur pour le retour à la fin si vous devez faire autre chose avec la valeur avant de le renvoyer:

def foo 
    (some expression).tap do |val| 
    # use val here 
    end 
    # The return value of the tap is _val_ 
    # and hence the return value of your method 
end 
+0

Intéressant. Merci pour la note. –

+0

Ouais en effet intéressant, mais je ne l'ai jamais vu comme une véritable implémentation –

1

Les variables temporaires sont mauvaises parce qu'elles augmentent la connectivité.

http://www.mgroves.com/what-is-connascence

ReplaceTempWithQuery est un refactoring J'utilise beaucoup:

def discount_price 
    base_price = quantity * item_price 
    if (base_price > 1000) 
    base_price * 0.95 
    else 
    base_price * 0.98 
    end 
end 
code

après refactoring:

def discount_price 
    if (base_price > 1000) 
    base_price * 0.98 
    else 
    base_price * 0.98 
    end 
end 

def base_price 
    quantity * item_price 
end 

http://www.refactoring.com/catalog/replaceTempWithQuery.html

+3

L'inconvénient de faire cela est que vous échangez une variable temporaire qui va tomber hors de la portée et être garbage-recueillis, avec deux appels pour recalculer la valeur: Le premier à faire test initial, et le second pour retourner la valeur ajustée. C'est une tentative de simplification, mais elle finit par augmenter la complexité et prend probablement plus de temps. –

+1

Et, BTW, vous pouvez essayer d'exécuter vos exemples. Le premier a une erreur de syntaxe parce qu'il manque une fermeture 'end' et la seconde ne retourne pas la bonne valeur pour le' if'. –

+0

Merci d'avoir signalé la fin manquante. –

1

Personnellement, je aime en utilisant retour pour appeler explicitement ce qui est retourné. C'est un code supplémentaire que Ruby ne vous oblige pas à utiliser, mais cela m'aide à la lisibilité. Cela vous permet également d'avoir plusieurs points de sortie dans votre méthode puisque l'exécution de votre méthode s'arrêtera dès que le retour est appelé.

Ce n'est vraiment pas très différent de l'exemple que vous avez donné dans votre question initiale.

def foo 
    val = (some expression) 
    val 
end 

pourrait ressembler à

def foo 
    return (some expression) 
end 
1

je fais parfois ce que vous avez dans votre question.

Quelques cas où je le fais sont:

  1. Quand je fais la programmation imperitive (foo = Foo.new; foo.modify_state; foo)
  2. Si je veux valider un objet avant de revenir, mais comme mentionné Phrogz, Object#tap peut aider ici (foo = new_foo; raise if foo.empty?; foo)
  3. Quand je veux préciser que je retourne une variable, plutôt que de faire plus de choses (do_this; do_that; do_other_thing; result #done!)

Il peut cependant indiquer des odeurs de code, comme dans le cas 1.

+0

Merci pour le commentaire. –

Questions connexes