web-dev-qa-db-fra.com

Est-ce un bon style de revenir explicitement en Ruby?

Venant d'un fond Python, où il y a toujours une "bonne façon de le faire" (une façon "Pythonic") en matière de style, je me demande s'il en va de même pour Ruby J'ai utilisé mes propres règles de style mais je songe à publier mon code source et j'aimerais qu'il respecte toutes les règles non écrites qui pourraient exister.

Est-il "La Ruby Way") "de taper explicitement return dans les méthodes? Je l'ai vu faire avec et sans, mais existe-t-il une bonne façon de le faire? il y a peut-être un droit temps de le faire? Par exemple:

def some_func(arg1, arg2, etc)
  # Do some stuff...
  return value # <-- Is the 'return' needed here?
end
147
Sasha Chedygov

Ancienne question (et "répondue"), mais je vais ajouter mes deux sous comme réponse.

TL; DR - Ce n'est pas obligatoire, mais cela peut rendre votre code beaucoup plus clair dans certains cas.

Bien que ne pas utiliser un retour explicite puisse être "la méthode Ruby") ", cela peut dérouter les programmeurs travaillant avec du code inconnu ou peu familier avec cette fonctionnalité de Ruby.

C'est un exemple quelque peu artificiel, mais l'imagerie a une petite fonction comme celle-ci, qui ajoute un au nombre passé et l'assigne à une variable d'instance.

def plus_one_to_y(x)
    @y = x + 1
end

S'agissait-il d'une fonction renvoyant une valeur ou non? Il est très difficile de dire ce que le développeur voulait dire, car il attribue la variable d'instance ET renvoie également la valeur attribuée.

Supposons beaucoup plus tard, un autre programmeur (peut-être pas si familier avec comment Ruby retourne en fonction de la dernière ligne de code exécutée) se présente et veut insérer des instructions d'impression pour la journalisation, et la fonction devient cette...

def plus_one_to_y(x)
    @y = x + 1
    puts "In plus_one_to_y"
end

Maintenant, la fonction est cassée si quelque chose attend une valeur retournée. Si rien n'attend une valeur renvoyée, c'est bon. Il est clair que si quelque part plus loin dans la chaîne de code, quelque chose qui appelle cela attend une valeur renvoyée, cela échouera car il ne récupérera pas ce qu'il attend.

La vraie question maintenant est la suivante: est-ce que quelque chose attendait vraiment une valeur renvoyée? Est-ce que cela a cassé quelque chose ou pas? Est-ce que ça va casser quelque chose dans le futur? Qui sait! Seule une vérification complète du code de tous les appels vous le fera savoir.

Donc, pour moi au moins, la meilleure approche consiste à indiquer très clairement que vous retournez quelque chose si cela compte, ou à ne rien renvoyer si ce n’est pas le cas.

Donc, dans le cas de notre petite fonction de démonstration, en supposant que nous voulions lui renvoyer une valeur, ce serait écrit comme ceci ...

def plus_one_to_y(x)
    @y = x + 1
    puts "In plus_one_to_y"
    return @y
end

Et il serait très clair pour tout programmeur que cela retourne une valeur, et beaucoup plus difficile pour eux de la casser sans s'en rendre compte.

Alternativement, on pourrait l'écrire comme ceci et laisser de côté la déclaration de retour ...

def plus_one_to_y(x)
    @y = x + 1
    puts "In plus_one_to_y"
    @y
end

Mais pourquoi se donner la peine d'omettre le retour de Word? Pourquoi ne pas simplement le préciser et expliquer à 100% ce qui se passe? Cela n'aura littéralement aucun impact sur la capacité de votre code à fonctionner.

216
Tim Holt

No. Bon Ruby n'utilise généralement que des retours explicites pour un retour anticipé. Ruby concerne le minimalisme du code/implicite la magie.

Cela dit, si un retour explicite rendait les choses plus claires ou plus faciles à lire, cela ne nuirait à rien.

66
Ben Hughes

J'utilise personnellement le mot clé return pour distinguer ce que j'appelle méthodes fonctionnelles, c'est-à-dire les méthodes exécutées principalement pour leur valeur de retour, et méthodes procédurales qui sont exécuté principalement pour leurs effets secondaires. Ainsi, pour les méthodes dans lesquelles la valeur de retour est importante, obtenez un mot clé supplémentaire return pour attirer l’attention sur la valeur de retour.

J'utilise la même distinction lorsque appelant méthodes: les méthodes fonctionnelles ont des parenthèses, pas les méthodes procédurales.

Enfin, j’utilise également cette distinction avec les blocs: les blocs fonctionnels ont des accolades, les blocs procéduraux (c’est-à-dire les blocs qui "font" quelque chose) ont pour do/end.

Cependant, j'essaie de ne pas être religieux: avec des blocs, des accolades et do/end, la priorité est différente, et plutôt que d'ajouter des parenthèses explicites pour lever une ambiguïté, je passe simplement à la autre style. Il en va de même pour l'appel de méthode: si l'ajout de parenthèses autour de la liste de paramètres rend le code plus lisible, je le fais, même si la méthode en question est de nature procédurale.

31
Jörg W Mittag

En réalité, l’important est de distinguer entre:

  1. Fonctions - méthodes exécutées pour leur valeur de retour
  2. Procédures - méthodes exécutées pour leurs effets secondaires

Ruby n'a pas de méthode native pour les distinguer - ce qui vous laisse vulnérable à l'écriture d'une procédure side_effect() et à un autre développeur qui décide d'abuser de la valeur de retour implicite de votre procédure (la traitant essentiellement comme une fonction impure).

Pour résoudre ce problème, jetez un œil à Scala et au livre de Haskell) et demandez à vos procédures de retourner explicitement nil (alias Unit ou () dans d'autres langues).

Si vous suivez ceci, alors utiliser explicitement la syntaxe return devient une question de style personnel.

Pour mieux distinguer les fonctions et les procédures:

  1. Copiez la belle idée de Jörg W Mittag d’écrire des blocs fonctionnels avec des accolades et des blocs procéduraux avec do/end
  2. Lorsque vous appelez des procédures, utilisez (), alors que lorsque vous appelez des fonctions, ne le faites pas

Notez que Jörg W Mittag a en fait préconisé le contraire - éviter ()s pour les procédures - mais cela n'est pas conseillé car vous voulez que les appels de méthode à effet secondaire soient clairement différenciés des variables, en particulier lorsque l'arité est 0. Voir le Guide de style Scala sur l'invocation de méthode pour plus de détails.

13
Alex Dean

Le guide de style indique que vous ne devriez pas utiliser return sur votre dernière déclaration. Vous pouvez toujours l'utiliser si ce n'est pas le dernier . C’est l’une des conventions que la communauté suit strictement, et vous devriez en faire autant si vous envisagez de collaborer avec toute personne utilisant Ruby.


Cela étant dit, le principal argument en faveur de l'utilisation explicite de returns est que cela crée de la confusion pour les personnes provenant d'autres langues.

  • Tout d'abord, ce n'est pas entièrement exclusif à Ruby. Par exemple, Perl a aussi des retours implicites.
  • Deuxièmement, la majorité des personnes concernées sont issues des langues ALGOL. La plupart d'entre elles sont bien "plus basses" que Ruby, vous devez donc écrire plus de code pour faire quelque chose.

Une heuristique commune pour la longueur de la méthode (à l’exclusion des getters/setters) dans Java est un écran . Dans ce cas, vous pourrait ne pas voir la définition de la méthode et/ou avoir déjà oublié d'où vous reveniez.

Par contre, dans Ruby, il vaut mieux s'en tenir aux méthodes moins de 10 lignes . Cela étant, on se demanderait pourquoi il doit écrire ~ 10% plus de déclarations, quand elles sont clairement impliquées.


Depuis Ruby n'a pas de méthodes et void ) et tout est tellement plus concis, vous ajoutez simplement une surcharge pour aucun des avantages si vous utilisez explicitement returns.

7
ndnenkov

Je suis d'accord avec Ben Hughes et en désaccord avec Tim Holt, car la question mentionne la manière définitive Python le fait et demande si Ruby a une norme similaire.

c'est le cas.

C’est une caractéristique du langage si connue que quiconque s’attend à déboguer un problème dans Ruby devrait en être raisonnablement informé.

4
Devon Parsons

C'est une question de style que vous préférez pour la plupart. Vous devez utiliser le mot-clé return si vous voulez retourner quelque part au milieu d'une méthode.

1
Praveen Angyan

Comme dit Ben. Le fait que 'la valeur de retour d'une méthode Ruby= soit la valeur de retour de la dernière instruction du corps de la fonction') 'rend le mot clé de retour rarement utilisé Ruby méthodes.

def some_func_which_returns_a_list( x, y, z)
  return nil if failed_some_early_check


  # function code 

  @list     # returns the list
end
0
Gishu