¿Las declaraciones de "requerimiento" de Ruby van dentro o fuera de la definición de clase?

StackOverflow https://stackoverflow.com/questions/605261

  •  03-07-2019
  •  | 
  •  

Pregunta

Al usar archivos de clase en Ruby, ¿colocas las declaraciones de 'requisitos' en la parte superior del archivo, o dentro de la definición de la clase?

¿Fue útil?

Solución

Técnicamente, realmente no importa. require es solo una llamada de método normal, y el alcance al que se llama no afecta la forma en que funciona. La única diferencia que hace la ubicación es que se ejecutará cuando se evalúe el código en el que esté ubicado.

Hablando en términos prácticos, debe colocarlos en la parte superior para que las personas puedan ver las dependencias del archivo de un vistazo. Ese es el lugar tradicional para ello.

Otros consejos

en la parte superior.

require 'rubygems'
require 'fastercsv'

class MyClass
  # Do stuff with FasterCSV
end

Puedo ver una posible razón para no poner un require en la parte superior del archivo: donde es caro cargar y no siempre se ejecuta. Un caso que se me ocurre es que, por ejemplo, el código y sus pruebas están en el mismo archivo, que es algo que me gusta hacer de vez en cuando para el código de una biblioteca pequeña en particular. Luego puedo ejecutar el archivo desde mi editor y ejecutar las pruebas. En este caso, cuando el archivo es require d desde otra parte, no quiero que se cargue prueba / unidad .

Algo un poco como esto:

def some_useful_library_function()
  return 1
end

if __FILE__ == <*>
  require 'test/unit'
  class TestUsefulThing < Test::Unit::TestCase
    def test_it_returns_1
      assert_equal 1, some_useful_library_function()
    end
  end
end

Realmente no importa dónde los coloques, pero si los pones dentro de una expresión class o module , entonces se ve como si estuviera importando lo que sea que esté en el archivo require d en el espacio de nombres de la clase, lo cual no es cierto: todo termina en el espacio de nombres global (o cualquier espacio de nombres definido en la biblioteca ).

Por lo tanto, mejor colóquelos en la parte superior para evitar cualquier confusión.

En la parte superior del archivo, la mayoría de los idiomas (pero no todos) manejan las importaciones de esta manera. Me parece mucho más limpio y más fácil de manejar de esta manera.

Creo que solo tiene sentido de esta manera realmente ... como si estuvieras a mitad de camino en un archivo:

class Foo
  def initialize(init_value)
    @instance_var = init_value

# some 500 lines of code later....

  end
end

class Bar
# oh look i need an import now!
require 'breakpoint'

como puedes ver, sería muy difícil rastrearlos. Sin mencionar que si quería usar las funciones importadas anteriormente en su código , probablemente tendría que retroceder e incluirlo nuevamente porque la otra importación sería específica para esa clase. Importar los mismos archivos también generaría una gran sobrecarga durante el tiempo de ejecución.

Siento que la declaración require pertenece a la clase. El uso de clases significa que estamos aceptando un principio básico de la POO, es decir, los objetos deben estar acoplados lo más libremente posible. Para mí eso implica minimizar las dependencias externas. Si luego muevo una clase a su propio archivo, no quiero que se rompa porque no localicé todas las declaraciones requeridas que la clase consume.

No causa ningún problema tener declaraciones requeridas duplicadas en un archivo y simplifica la refactorización que inevitablemente tendrá lugar en el próximo programador que herede su código.

La mayoría de las respuestas recomiendan colocar las declaraciones require en la parte superior del archivo. Sin embargo, cuando se requieren clases / módulos anidados, quizás desee considerar colocarlos en la clase (en la parte superior). Echa un vistazo a este ejemplo:

# foo.rb
require './foo/bar'

class Foo < Struct.new(:name, :description)
  def bar
    Bar.new(self)
  end
end

# foo/bar.rb
class Foo
  class Bar < Struct.new(:foo)
  end
end

irb:

require './foo'
# ...
# TypeError (superclass mismatch for class Foo)

Esto sucede porque Bar está anidada dentro de Foo y deberá definirse como tal anidando la clase Bar dentro de Foo clase. Sin embargo, como Foo aún no está definido, ahora está siendo definido por la estructura anidada. Después de que se requiera con éxito Barra , ahora intentamos definir la clase Foo que se hereda de otra clase. Esto falla debido a que Foo ya está definido (por la estructura anidada) y la herencia solo puede ocurrir en la definición inicial de la clase. Subiendo así:

  

TypeError (discrepancia de superclase para la clase Foo)

Este problema se puede resolver simplemente moviendo la declaración requerida dentro de la clase Foo .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top