Question

J'ai été mordu plusieurs fois en oubliant ça x = y dans Ruby fait que x se réfère au même objet que y; Je suis trop habitué aux langues où cela signifie, en termes de rubis, x = y.dup. Oubliant cela, je change par inadvertance y Quand je pense qu'il est sûr du côté droit de la mission.

Je peux voir qu'il serait logique d'éviter simple x = y affectations sans raison particulière, mais la même chose peut se cacher dans d'autres endroits tels que

name = (person.last_name.blank? ? 'unknown' : person.last_name)

Où un plus tard name << title Changerait en fait personne.last_name et pas seulement le nom.

Si cela vous est arrivé aussi, comment avez-vous appris à l'éviter? Y a-t-il certains drapeaux rouges ou motifs à rechercher? Regardez-vous avec suspicion à chaque mission que vous faites? Utilises tu .dup beaucoup? Je ne sais pas si l'utilisation de Ruby deviendra jamais la seconde nature pour moi, donc tous les conseils utiles seraient les bienvenus.

Était-ce utile?

La solution

Cela peut sembler peu orthodoxe dans une langue (essentiellement impérative) comme Ruby, mais mon conseil est: éviter dommages collatéraux en ne mettant pas à jour les objets du tout (sauf lorsque vous êtes strictement nécessaire); en créer de nouveaux à la place. Vous payez un peu de performances, mais vous obtiendrez du code qui est plus clair, plus compact, plus modulaire et plus facile à déboguer.

http://en.wikipedia.org/wiki/Fonctional_Programming

Donc, dans votre exemple, créez simplement une nouvelle chaîne avec un nouveau nom:

complete_name = name + title

Autres conseils

Juste un ajout à la réponse de Tokland:

L'approche fonctionnelle insiste sur immutabilité - IE ne modifiant pas les objets existants, mais en créant un autre chaque fois que vous voulez changer celui d'origine. C'est quelque peu contre le paradigme orienté objet que Ruby apporte également (les objets gardent leur état en interne, ce qui peut être modifié en appelant des méthodes), vous devez donc équilibrer un peu entre les deux approches (en revanche, nous bénéficions En ayant plusieurs paradigmes facilement accessibles dans une seule langue).

Donc, trois choses à retenir pour l'instant:

  1. Apprenez quelle affectation dans Ruby est: rien que de nommer un objet. Alors, quand tu dis y=x, tu dis seulement "nous donnons un autre nom y à tout ce qui a été nommé x".
  2. name << title mute objet appelé name.
  3. name += title prend des objets nommés name et title, les concaténe en une autre objet, et attribue ce nouveau nom d'objet name. Cela ne mute rien.

Je suis également tombé sur une telle situation et cela a entraîné un bug, que j'ai pris une demi-journée pour comprendre. J'ai essentiellement fait quelque chose comme ça

hash = {....}
filename = object.file_name
hash.each |k, v| {file_name.gsub!(k, v) if file_name.include? k}

Ce code était à l'intérieur d'une boucle et dans la boucle, je m'attendais à la variable file_name Pour être à nouveau réglé sur la valeur d'origine. Mais le nom d'objet.file_name a été changé, car je jouais file_name.gsub!. Il existe 2 façons de résoudre ce problème. Soit remplacer le .gsub! appeler avec file_name = file_name.gsub ou faire file_name = object.file_name.dup. J'ai opté pour la deuxième option.

Je pense que nous devons être prudents avec les méthodes ayant ! et <<, car ils changent l'objet d'origine sur lequel ils agissent, surtout après des affectations comme celle-ci.

Une méthode ne doit pas modifier une variable (par exemple en utilisant l'opérateur de décalage) à moins que sa définition indique qu'elle le modifiera.

SO: ne modifiez jamais un objet dans une méthode qui n'a pas (a) le créer ou (b) le document qu'il le modifie.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top