¿Cuál es la mejor práctica en Ruby para evitar el uso indebido de asignación "="?
-
12-11-2019 - |
Pregunta
He sido mordido un par de veces por olvidar que x = y
en Ruby hace que x se refieren al mismo objeto como y;Estoy demasiado acostumbrado a idiomas donde significa, en Ruby términos, x = y.dup
.Olvidar esto, me cambie accidentalmente y
cuando yo creo que es seguro en el lado derecho de la asignación.
Puedo ver que tendría sentido para evitar simple x = y
tareas sin una razón especial, pero lo mismo puede estar al acecho en otros lugares, tales como
name = (person.last_name.blank? ? 'unknown' : person.last_name)
donde más tarde name << title
en realidad sería el cambio de persona.apellido y no sólo de nombre.
Si esto ha ocurrido a usted, también, cómo han aprendido a evitar?Hay ciertas banderas rojas o patrones a buscar?¿Mirar con recelo a cada tarea que hacer?¿Utiliza .dup
un montón?No sé si la de Ruby uso se conviertan en una segunda naturaleza para mí, así que algunos consejos útiles sería bienvenido.
Solución
Esto puede parecer poco ortodoxo en un (esencialmente imprescindible) de la lengua como Ruby, pero mi consejo es:evitar daños colaterales por no actualizar todos los objetos (excepto cuando sea estrictamente necesario);crear otros nuevos en su lugar.Usted paga un poco de rendimiento pero tendrás un código que es más claro, más compacto, más modular y fácil de depurar.
http://en.wikipedia.org/wiki/Functional_programming
Así, en el ejemplo, acaba de crear una nueva cadena con un nombre nuevo:
complete_name = name + title
Otros consejos
Sólo una adición a tokland la respuesta:
Enfoque funcional insiste en la inmutabilidad de - es decir,no alteración de los objetos existentes, sino en la creación de otro siempre que desee cambiar el original.Esto es algo en contra de la orientación a objetos es un paradigma que Ruby también trae (objetos de mantener su estado interno, que puede ser alterada por llamar a métodos en él), así que usted tiene que equilibrar un poco entre los dos enfoques (por otro lado, se benefician de múltiples paradigmas fácilmente accesibles en un solo idioma).
Por lo tanto, tres cosas para recordar por ahora:
- Aprender lo que la asignación en Ruby es:nada pero el nombramiento de un objeto.Así que, cuando usted dice
y=x
, sólo está diciendo: "le damos otro nombrey
a lo que se ha denominadox
". name << title
muta objeto de llamadoname
.name += title
toma objetos con nombrename
ytitle
, concatena en otro objeto, y se asigna a ese nuevo nombre de objetoname
.No mutar nada.
También me he topado con una situación y que resultó en un error, que me tomó la mitad de un día de averiguar.Esencialmente me hizo algo como esto
hash = {....}
filename = object.file_name
hash.each |k, v| {file_name.gsub!(k, v) if file_name.include? k}
Este código fue dentro de un bucle y en el bucle, se esperaba que la variable file_name
se establecen de nuevo valor original.Pero el objeto.file_name fue cambiado, como yo estaba realizando file_name.gsub!
.Hay 2 maneras de resolver esto.Reemplazar la .gsub!
llamada con file_name = file_name.gsub
o hacer file_name = object.file_name.dup
.Yo he optado por la segunda opción.
Creo que debemos tener cuidado con los métodos de haber !
y <<
, como cambiar el objeto original en el que están actuando, especialmente después de las tareas como esta.
Un método no debe modificar una variable (por ejemplo,utilizando el operador de desplazamiento a) a menos que su definición dice que se va a modificar.
Así:nunca modificar un objeto en un método que no sea: (a) crear o (b) documento que modifica.