我在Rails中有一個更概念性的問題......或者Ruby的那個問題:什麼時候在Rails中調用「require」?
最好是在需要它的方法之前調用require權限,在類的開始處或者在某處Rails啓動時的初始化程序?
從性能的角度來看它有什麼關係?從可讀性的角度來看?如果我使用Rails 3,它會有所作爲嗎?
謝謝!
我在Rails中有一個更概念性的問題......或者Ruby的那個問題:什麼時候在Rails中調用「require」?
最好是在需要它的方法之前調用require權限,在類的開始處或者在某處Rails啓動時的初始化程序?
從性能的角度來看它有什麼關係?從可讀性的角度來看?如果我使用Rails 3,它會有所作爲嗎?
謝謝!
如果你關心性能,那麼你應該在需要它的地方需要一些東西,這樣如果你的代碼部分沒有被執行,庫就不會被加載。由於該文件已被加載,因此對require
的任何後續調用都不起作用。這最終看起來像沿着線的東西:
if (user.using_openid?)
require 'openid'
# ... Do OpenID stuff
end
雖然這是在資源方面更有效,它可以使人們很難確定應用程序的依賴關係。聲明這些預先向其他維護軟件的人員說明。請記住,當你忘記了應用程序的某些細節時,「其他人」總是包含你的未來自我。
您在技術上允許在任何時間,遲到或早期需要任何東西,但從設計的角度來看,預先聲明您的需求是更好的。如果您發現有一個元素只是間歇性使用,並且需要花費不尋常的時間或內存來加載,那麼您應該在需求文件中預先記錄該元素。例如:
require 'library1'
require 'library2'
require 'library3'
require 'library4'
require 'library5'
# Other libraries loaded as required:
# * slowimagelibrary
# * slowencryptionlibrary
# * openid
可以說這是不太有bundler的問題,因爲你可以有你的寶石宣佈了前面更正式和實際require
調用可以晚一點。
如果你考慮vanilla Ruby,'require'主要用在第一行,因爲你確定你有權訪問你需要的東西,並且它更容易找到並閱讀你需要的依賴關係。
有幾種情況只需要在一個方法中加載一個gem,因爲腳本不是真的需要工作(例如:可選的可視化)。
隨着Rails,我相信這取決於你想要做什麼。
如果你使用Bundler,你可以假設你的gem是'required'(你當然可以用require選項覆蓋它)。
如果它是一些你想在服務器啓動時自動加載的東西(如驗證器或表單構建器),那麼你應該看看如何處理配置(autoload_paths和eager_load_paths)。
require還可以用來加載一個寶石的一部分,就像它的一個擴展。那麼它當然需要配置的位置。
如果您在多線程環境中工作,您可能會擔心,因爲它們存在一些問題。在線程運行之前,您必須確保一切都已加載。 (像類常量被加載,但方法尚未,有一篇很好的文章,但我找不到它了)。
您可能還想嘗試{Module,Kernel}。自動加載,Rails廣泛使用它來加載訪問時只需要的東西(但它看起來相當醜陋)。你也可以用const_missing自己破解它(如果你接受一個結構,這可以做簡單的延遲加載)。 這是一個簡單的例子(不適用於嵌套類)。
def Object.const_missing c
if (file = Dir["#{c.downcase}.rb"]).size == 1
require_relative(file)
end
if const_defined? c
const_get c
else
super # Object < Module
end
end
關於性能,需要調用相對昂貴,所以如果你知道你要使用它,做它只有一次,如果可能的。但是,要管理項目中的複雜依賴關係,可能需要相關文件。然後require_relative
是1.9的方式。
最後,對於一個項目,我建議在lib /中的主文件中需要所有的文件,並且有一些Dir["**/*.rb"]
表達式。你很少需要require_relative
,因爲只有當你在類的主體中引用另一個常量時才需要它(方法的所有內容都沒有解決,所以沒有問題)。
另一種解決方案是在主文件中定義這些常量,它也會給你一個結構的概念。
謝謝tadman,這符合我的想法。結論:除了使用重要要求時,可讀性比性能更重要。 – Cimm 2010-08-27 20:06:35