rails - ruby rubocop
¿Es un buen estilo volver explícitamente en Ruby? (8)
Viniendo de un fondo de Python, donde siempre hay una "forma correcta de hacerlo" (una forma "pitonica") cuando se trata de estilo, me pregunto si lo mismo existe para Ruby. He estado usando mis propias pautas de estilo, pero estoy pensando en liberar mi código fuente, y me gustaría adherirme a las reglas no escritas que puedan existir.
¿Es "The Ruby Way" para escribir explícitamente return
en métodos? Lo he visto hacerlo con y sin, pero ¿hay una forma correcta de hacerlo? ¿Hay quizás un buen momento para hacerlo? Por ejemplo:
def some_func(arg1, arg2, etc)
# Do some stuff...
return value # <-- Is the ''return'' needed here?
end
Como dijo Ben. El hecho de que "el valor de retorno de un método ruby es el valor de retorno de la última declaración en el cuerpo de la función" hace que la palabra clave return se use raramente en la mayoría de los métodos ruby.
def some_func_which_returns_a_list( x, y, z)
return nil if failed_some_early_check
# function code
@list # returns the list
end
En realidad, lo importante es distinguir entre:
- Funciones: métodos ejecutados por su valor de retorno
- Procedimientos: métodos ejecutados por sus efectos secundarios
Ruby no tiene una forma nativa de distinguirlos, lo que lo hace vulnerable a escribir un procedimiento side_effect()
y otro desarrollador decide abusar del valor de retorno implícito de su procedimiento (básicamente, lo trata como una función impura).
Para resolver esto, tome una hoja del libro de Scala y Haskell y haga que sus procedimientos devuelvan nil
explícitamente (aka Unit
o ()
en otros idiomas).
Si sigues esto, entonces usar la sintaxis de return
explícita o no solo se convierte en una cuestión de estilo personal.
Para distinguir mejor entre funciones y procedimientos:
- Copie la buena idea de Jörg W Mittag de escribir bloques funcionales con llaves, y bloques de procedimientos con
do/end
- Cuando invoque procedimientos, use
()
, mientras que cuando invoque funciones, no lo haga
Tenga en cuenta que Jörg W Mittag abogaba al revés - evitando ()
s los procedimientos - pero no es aconsejable porque quiere que las invocaciones de métodos de efecto secundario sean claramente distinguibles de las variables, particularmente cuando arity es 0. Consulte la guía de estilo de Scala invocación para detalles.
Es una cuestión de qué estilo prefiere en su mayor parte. Debe usar la palabra clave return si desea regresar desde algún lugar en medio de un método.
Estoy de acuerdo con Ben Hughes y no estoy de acuerdo con Tim Holt, porque la pregunta menciona la forma definitiva en que Python lo hace y pregunta si Ruby tiene un estándar similar.
Esta es una característica tan conocida del lenguaje que cualquiera puede esperar que solucione un problema en ruby, se espera que lo sepa.
No. El buen estilo de Ruby generalmente solo usaría un retorno explícito para un retorno anticipado . Ruby es grande en el minimalismo de código / magia implícita.
Dicho esto, si un retorno explícito hace las cosas más claras o más fáciles de leer, no dañará nada.
Pregunta anterior (y "respondida"), pero voy a dar mis dos centavos como respuesta.
TL; DR - No es necesario, pero puede hacer que su código sea mucho más claro en algunos casos.
Aunque no utilizar un retorno explícito puede ser "el modo Ruby", es confuso para los programadores que trabajan con código desconocido o que no están familiarizados con esta característica de Ruby.
Por ejemplo, uno podría tener una pequeña función como esta, que agrega una al número pasado y la asigna a una variable de instancia.
def plus_one_to_y(x)
@y = x + 1
end
¿Se suponía que era una función que devolvía un valor, o no? Es realmente difícil decir lo que el desarrollador quiso decir, ya que ambos asignan la variable de instancia Y devuelve el valor asignado también.
Supongamos que mucho más tarde, otro programador (tal vez no tan familiarizado con la forma en que Ruby devuelve basándose en la última línea de código ejecutado) viene y quiere poner en algunas declaraciones de impresión para el registro, y la función se convierte en esto ...
def plus_one_to_y(x)
@y = x + 1
puts "In plus_one_to_y"
end
Ahora la función se rompe si algo espera un valor devuelto . Si nada espera un valor devuelto, está bien. Claramente, si en algún lugar más abajo en la cadena de código, algo que llama esto está esperando un valor devuelto, va a fallar ya que no está recuperando lo que espera.
La verdadera pregunta ahora es esta: ¿algo realmente esperaba un valor devuelto? ¿Esto rompió algo o no? ¿Romperá algo en el futuro? ¡Quién sabe! Solo una revisión de código completo de todas las llamadas se lo hará saber.
Así que, al menos para mí, el enfoque de mejores prácticas es ser muy explícito de que estás devolviendo algo si es importante o no devuelves nada.
Entonces, en el caso de nuestra pequeña función de demostración, suponiendo que quisiéramos que devolviera un valor, se escribiría así ...
def plus_one_to_y(x)
@y = x + 1
puts "In plus_one_to_y"
return @y
end
Y sería muy claro para cualquier programador que devuelve un valor, y mucho más difícil para ellos romperlo sin darse cuenta.
Alternativamente, uno podría escribirlo así y dejar fuera la declaración de devolución ...
def plus_one_to_y(x)
@y = x + 1
puts "In plus_one_to_y"
@y
end
Pero, ¿por qué molestarse en dejar de leer la palabra? ¿Por qué no ponerlo allí y dejarlo al 100% claro de lo que está pasando? Literalmente no tendrá ningún impacto en la capacidad de rendimiento de su código.
Yo personalmente uso la palabra clave return
para distinguir entre lo que llamo métodos funcionales , es decir, los métodos que se ejecutan principalmente por su valor de retorno, y los métodos de procedimiento que se ejecutan principalmente para sus efectos secundarios. Por lo tanto, los métodos en los que el valor de retorno es importante, obtenga una palabra clave de return
adicional para llamar la atención sobre el valor de retorno.
Utilizo la misma distinción cuando llamo a métodos: los métodos funcionales obtienen paréntesis, los métodos de procedimiento no.
Y por último, pero no menos importante, también uso esa distinción con bloques: los bloques funcionales obtienen llaves, bloques de procedimientos (es decir, bloques que "hacen" algo) obtienen do
/ end
.
Sin embargo, trato de no ser religioso al respecto: con bloques, llaves y do
/ end
tienen precedencia diferente, y en lugar de agregar paréntesis explícitos para desambiguar una expresión, simplemente cambio al otro estilo. Lo mismo ocurre con las llamadas a métodos: si agregar paréntesis alrededor de la lista de parámetros hace que el código sea más legible, lo hago, incluso si el método en cuestión es de naturaleza de procedimiento.
La guía de estilo indica que no debe usar el return
en su última declaración. Aún puedes usarlo si no es el último . Esta es una de las convenciones que la comunidad sigue estrictamente, y usted también debería hacerlo si planea colaborar con cualquier persona que use Ruby.
Dicho esto, el argumento principal para usar return
explícitos es que es confuso para las personas que provienen de otros idiomas.
- En primer lugar, esto no es exclusivo de Ruby. Por ejemplo, Perl también tiene retornos implícitos.
- En segundo lugar, la mayoría de las personas a las que esto se aplica provienen de los idiomas de Algol. La mayoría de ellos son de un "nivel más bajo" que Ruby, por lo tanto, debes escribir más código para hacer algo.
Una heurística común para la longitud del método (excluyendo getters / setters) en java es una pantalla . En ese caso, es posible que no vea la definición del método y / o que ya haya olvidado de dónde regresaba.
Por otro lado, en Ruby, es mejor seguir métodos de menos de 10 líneas . Dado eso, uno se preguntaría por qué tiene que escribir ~ 10% más declaraciones, cuando están claramente implícitas.
Como Ruby no tiene métodos nulos y todo es mucho más conciso, solo está agregando sobrecarga para ninguno de los beneficios si va con return
explícitos.