[英]Play! framework uses a <lot> of statics
哇,玩! 框架有很多靜態方法。 在我上學的地方,我們被告知永遠不會使用任何靜力學,但玩! 使用它就像沒有明天一樣。 那是不是很好? 如果是這樣,為什么?
我們(7個人和我)正計划使用Play! 涉及Web應用程序的項目框架。 我們決定玩Play! 因為它看起來很有趣,我們所有人都已經知道Java並且任務很難,所以我們想要專注於實際的任務,而不是學習如何用不同的語言編程。
我們總是說,但是, 永遠不要用“靜在我們開發的任何Java程序,但是當我看着玩! ......好吧......大約一半的方法都是靜態的。 </誇張>
我想,至少,我們可以使用單例對象(通過使用Scala,例如^^)來編程我們的項目,但我非常擔心框架本身實際上有多少靜態。
那么,我應該關注這個嗎? 玩的方式! 開發人員編程使它成為所有這些靜態不會造成問題的?
(例如, 這個主題有一個關於為什么要不惜一切代價避免靜態成員的咆哮。)
Play只有在有意義時才使用靜態方法:
Play框架不是一個很好的演示,當使用靜態時是合適的,也不能證明你的老師是錯的。 Play是一種作弊行為,解決了Java語言之外的靜態問題。
關鍵問題是你必須並行處理多個HTTP請求,靜態字段是“全局的”。 因此,對於某些事情,每個線程需要一個實例(甚至更好,每個HTTP請求一個實例),但其中一些實例是由Play中的靜態方法返回的。 這很有效,因為玩! 大量使用ThreadLocal
,因此它解決了Java語言之外的靜態問題。 但那不是一切。 有人說控制器方法是正確的靜態。 當然,但是在普通的Java中它會很不方便,因為如果沒有某種前綴(例如req.
,你就無法訪問特定於請求的數據req.
在req.session
,然后你仍然必須從某個地方得到req
,比如作為靜態控制器方法的參數,這更加麻煩。 然而在Play中你可以直接寫session
等,它們只是靜態字段。 那是因為Play使用字節碼檢測將所有靜態字段引用更改為更智能的東西。 同樣,Java語言之外的解決方案。 那些不是最后的靜態字段。
所以,一般來說,避免非最終靜態。 Play雖然為你帶來了魔力,所以在這種情況下不要害怕它們。
從一個非常簡單的介紹一下,我會說這樣的有道理:web請求是無狀態的,所以沒有對象接收請求(=方法)。 因此,將諸如“/ articles / archive?date = 08/01/08&page = 2”之類的URI映射到名為archive()
的靜態方法,我想,你的應用程序類是有意義的。
編輯現在在Play 2.4中, 注射自動完成。 所以只需在文件routes
中的控制器路徑的開頭添加@就可以了:
GET / @controllers.Application.index()
對於舊版本(2.1到2.3),您必須覆蓋Global類中的getControllerInstance,如Documentantion中所述。
與編程中的任何內容一樣, 永遠不會是正確的答案。 就像往常一樣。 總有例外,正確的答案總是“它取決於”。
確實,在純粹的OO中(我都是這樣),靜力學的空間很小。 但有時它們才有意義也是如此。
經典的例子是實用方法。 當然,如果我們可以將abs()
方法附加到Integer會更好。 但我們不能; 所以我們堅持使用Math.abs(int i)
。
我傾向於認為,當一個方法與實例本身無關時,將方法設置為靜態是正確的。 例如,在Person
類中,您可以使用一個方法來獲取人員列表,並返回今天有生日的人數。 如果計算所需的數據是私有的(OO純粹主義者會理解的東西;)),也許你只能在類本身中執行此操作,但該方法顯然與單個Person實例無關。
另一件事是內部課程。 如果不需要與包含類型的關系,通常希望將它們設置為靜態。
我從未見過Play! 但如果你說它超過50%是靜態的,那么我猜它可能設計得很糟糕。 那也不例外; 很多框架都是。 不要讓它讓你失望。 絕對不要向它學習!
但如果它有效,你仍然可以使用它。
靜態控制器方法無疑是Play的關注領域! 框架,經過一些測試后,這是我不玩Play的主要原因! 在項目中。 你實際上可以在FOSS項目里看到這里玩的地方! 用來。 幾乎沒有控制器測試。 原因是,采用靜態方法,DI變得困難。 這是他們應該花費更多時間使用ASP.NET MVC的地方,從Play! 已經需要一些靈感。
通常你有一個像這樣的構造函數:
public HomeController( IService service ) {
_service = service;
}
public Index() {
var data = _service.getData();
return View( data );
}
然后使用DI將IService實現注入Controller。 關鍵是在測試中,您可以在運行Controller之前實例化IService,然后根據您剛剛生成的IService測試結果。
在Play中,這變得非常困難。 因此控制器單元測試變得困難。 對我來說,這是一個重大問題。 因此,我傾向於尋找除Play之外的其他框架! 在Java世界中。 哎呀,為什么不使用原版並只使用JRuby?
主要問題是靜態方法只能訪問其他靜態方法和字段,這導致“靜態粘附”,靜態方法必須通過公共靜態字段與應用程序的其余部分(包含其協作者)會合。 ,這導致不靈活。
免責聲明:我不太了解'玩!'
游戲中的靜態方法主要用於控制器動作方法。 這些方法只是從模型中獲取必要數據並將其公開給視圖。
它們以某種方式對應每個可能的http請求,就像那些http請求完全是無狀態的一樣。
在結構編程上,一方面是程序,另一方面是變量,但在OOP范例中,您將程序和變量視為一個整體。
也就是說,您具有實例方法(過程)和實例變量的對象。
但控制器操作是無狀態的,即它們從請求中獲取所有變量(也可能來自緩存,但在這種情況下,您需要某種最終來自請求的會話ID)。 因此控制器操作就像狀態過程一樣,這就是為什么它們不像模型那樣特別適合OOP范例。
我想,至少,我們可以使用單例對象
Java中的Singleton與使用所有靜態沒有多大區別。 作為國家也沒有多少存儲。 我想你不應該擔心它。
那么,我應該關注這個嗎? 玩的方式! 開發人員編程使它成為所有這些靜態不會造成問題的?
它不會。 事實上,沒關系。
Play采用了一種功能性方法,例如node.js ,並且可以說在Scala中比在Java中更“有意義”,例如Typesafe Stack正在推動。 正如其他海報所指出的那樣,Java正在使用字節碼檢測(一種方面J)進行擴充,以更無狀態/功能的方式運行; Scala默認執行此操作。
我也對游戲中靜態方法的數量感到驚訝,但為什么不工作呢?
其實我不同意你的老師。
如果一個對象沒有狀態(即全局變量)但只包含例子的方法,那么使用對象而不是靜態方法不會帶來任何好處。 除非您計划稍后添加狀態(不應共享的狀態),或者您正在使用接口並希望能夠輕松切換實現,否則使用靜態方法會更容易...
JDK本身,apache commons或許多框架都包含靜態方法:
其實我想你想知道像JPA.java這樣的類是什么: https : //github.com/playframework/play/blob/master/framework/src/play/db/jpa/JPA.java
它們僅使用靜態方法並保持靜態。 這可能很奇怪,但實際上對我來說這有點像使用單例,除了方法用於靜態上下文而不是對象。 主要區別在於您不必每次都調用getInstance()。
我認為這是為可用性而設計的,因為調用“getInstance”並不是用戶友好的,能夠輕松地在任何地方(鏈接到線程)輕松獲得會話而不是使用xml或自動裝配注入sessionFactory很酷。 ..
您的教授可能會告訴您避免使用靜態,因為如果您不正確使用它們,可能會對您的設計造成危險。 但請注意,在許多情況下,用單例替換靜態方法並不能使您的設計更好。 即使您現在在實例方法上調用方法,對象仍然會緊密耦合...
所以也許一個規則應該是避免使用靜力學,除非你真的不關心緊耦合。
在這種情況下,當您調用JPA.xxx()方法時,您的代碼與play框架的JPA類緊密耦合。 但我不認為游戲的設計是為了能夠輕松地從一個框架切換到另一個框架而不需要至少一些返工...
這與EJB3規范或類似的東西有很大不同:如果EJB3實體管理器的方法是靜態的,那么您將被迫通過調用HibernateEntityManager.xxx()或ToplinkEntityManager.xxx()將代碼緊密地耦合到實現。 在這種情況下,有一個通用接口(我們不能在接口上添加靜態方法)。
使用靜態方法的原因之一是靜態導入,它允許您縮短表示法並使代碼更具可讀性。 當使用像Guava或Apache Commons這樣的實用程序庫時,可能會有很多靜態調用。
Play 2.1中現在通過使用控制器注入支持非靜態控制器方法,因此不清楚為什么它們從一開始就不存在。
您現在可以在Play中使用Spring DI,請參閱https://stackoverflow.com/a/16552598/10433 。 我正在使用它,到目前為止工作正常。
如果你是面向對象編程的純粹主義者,你不應該使用static
方法/字段,但它們可以安全使用,並且不必引起關注IMHO。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.