Идут ли инструкции Ruby 'require' внутрь или за пределы определения класса?

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

  •  03-07-2019
  •  | 
  •  

Вопрос

При использовании файлов классов в Ruby вы помещаете инструкции 'requireds' в начало файла или внутри определения класса?

Это было полезно?

Решение

Технически, это действительно не имеет значения. require это просто обычный вызов метода, и область, в которой он вызывается, не влияет на то, как он работает.Единственное отличие размещения заключается в том, что оно будет выполнено, когда будет вычислен любой код, в который оно помещено.

С практической точки зрения, вы должны поместить их сверху, чтобы люди могли сразу увидеть зависимости файла.Это традиционное место для этого.

Другие советы

на самом верху.

require 'rubygems'
require 'fastercsv'

class MyClass
  # Do stuff with FasterCSV
end

Я вижу возможную причину для того, чтобы не ставить require в верхней части файла:где загрузка обходится дорого и не всегда выполняется.Один случай, который приходит мне на ум, - это когда, например, код и его тесты находятся в одном файле, что я люблю делать время от времени, в частности, для кода небольшой библиотеки.Затем я могу запустить файл из своего редактора, и тесты будут запущены.В этом случае, когда файл находится requireбуду приходить откуда-то еще, я не хочу test/unit чтобы быть загруженным.

Что-то немного похожее на это:

def some_useful_library_function()
  return 1
end

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

На самом деле не имеет значения, куда вы их положите, но если вы их положите внутри a class или module выражение, тогда это выглядит так, как будто вы импортируете все, что есть в requireобщий файл в пространство имен класса, что неверно:все заканчивается в глобальном пространстве имен (или любых других определенных пространствах имен в библиотеке).

Поэтому лучше разместите их вверху, чтобы избежать какой-либо путаницы.

В верхней части файла большинство (но не все) языков обрабатывают импорт таким образом.Я нахожу, что таким образом с ними гораздо чище и проще обращаться.

Я думаю, что на самом деле это имеет смысл только так...как будто ты добираешься до середины файла, тогда:

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'

как вы можете видеть, отследить их было бы очень трудно.Не говоря уже о том, хотели ли вы использовать импортированные функции ранее в вашем коде, вам, вероятно, придется вернуться назад и включить его снова, потому что другой импорт будет специфичен для этого класса.Импорт одних и тех же файлов также привел бы к большим накладным расходам во время выполнения.

Я чувствую, что требовать оператор принадлежит классу.Использование классов означает, что мы принимаем базовый принцип ООП, а именно: объекты должны быть как можно более слабо связаны.Для меня это подразумевает минимизацию внешних зависимостей.Если я позже перемещу класс в его собственный файл, я не хочу, чтобы он прерывался, потому что я не отследил все необходимые требовать операторы, которые использует класс.

Наличие дубликатов не вызывает никаких проблем требовать инструкции в файле, и это упрощает рефакторинг, который неизбежно будет выполнен следующим программистом, наследующим ваш код.

В большинстве ответов рекомендуется ставить требовать инструкции в верхней части файла.Однако, когда требуются вложенные классы / модули, вы можете рассмотреть возможность размещения их вместо этого в классе (вверху).Взгляните на этот пример:

# 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)

Это происходит потому, что Бар вложен внутрь Фу и его нужно будет определить как таковой путем вложения Бар класс внутри Фу класс.Однако с тех пор , как Фу еще не определено, сейчас оно определяется вложенной структурой.После Бар успешно требуется, теперь мы попытаемся определить Фу класс, который наследуется от другого класса.Это не удается из-за того, что Фу уже определен (вложенной структурой), и наследование может происходить только при начальном определении класса.Таким образом, повышая:

TypeError (несоответствие суперкласса классу Foo)

Эта проблема может быть решена простым перемещением инструкции require внутри Фу класс.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top