わあ、遊び!フレームワークには非常に多くの静的メソッドがあります。私が学校に行くところ、私たちはこれまでにない静力学を使うように言われましたが、まだプレイしてください!明日がないようにそれを使用します。それはどういうわけか大丈夫ですか?もしそうなら、なぜですか?
私たち(7人と私)はPlayを使用する予定です。 Webアプリを含むプロジェクトのフレームワーク。 Playを使用することにしました。とても楽しいように見えるので、私たち全員がすでにJavaを知っており、割り当てはかなり難しいので、別の言語でプログラミングする方法を学ぶのではなく、実際の割り当てに集中したかったのです。
しかし、私たちは常にNEVER EVERで、任意のJavaプログラムで 'static'sを使用するように言われましたが、 Playを見てください!...ええと...メソッドの約半分は静的です。</ exaggeration>
少なくとも、プロジェクトをプログラムするために(Scalaを使用して^^などの)シングルトンオブジェクトを使用できると思いますが、実際にはフレームワーク自体に静的がいくつあるのか非常に心配です。
それで、私はこれについて心配する必要がありますか?遊び方をしました!開発者は、これらすべての静力学が問題を引き起こさないようにプログラムを作成しましたか?
(たとえば、 this thread には、静的メンバーをすべてのコストで避けなければならない理由についての怒りがあります。)
Playは、意味のある場合にのみ静的メソッドを使用します。
Playフレームワークは、静力学を使用することが適切である場合の良いデモンストレーションではなく、先生が間違っていることを証明するものでもありません。遊びは一種の不正行為であり、Java言語外の静力学の問題を解決します。
重要な問題は、複数のHTTPリクエストを並行して処理する必要があり、静的フィールドが「グローバル」であることです。したがって、スレッドごとに1つのインスタンス(または、HTTP要求ごとに1つのインスタンス)が必要になりますが、それらの一部はPlayの静的メソッドによって返されます。 Play!はThreadLocal
- sを頻繁に使用するため、Java言語以外の静的問題を解決します。しかし、それだけではありません。コントローラーメソッドは当然静的であると言う人もいます。確かに、単純なJavaそれは不便です。その場合、req.
のreq.session
のような接頭辞がなければリクエスト固有のデータにアクセスできず、静的コントローラメソッドのパラメータのように、どこかからreq
を取得する必要がありますが、これはさらに面倒です。しかし、Playでは、session
を直接記述するだけで、静的フィールドです。これは、Playがバイトコードインスツルメンテーションを使用して、すべての静的フィールド参照をよりスマートなものに変更するためです。ここでも、Java言語外のソリューションです。これらは最後の静的フィールドではありません。
したがって、一般的には、最終ではない統計を避けてください。 Playはあなたのために魔法をかけるので、この場合それらを恐れないでください。
非常に簡単に見ると、それは一種の理にかなっていると思います。Webリクエストはステートレスであるため、isリクエストを受け取るオブジェクト(=メソッド)はありません。したがって、 "/ articles/archive?date = 08/01/08&page = 2"などのURIをarchive()
onと呼ばれる静的メソッドにマッピングすると、アプリケーションクラスに意味があると思います。
[〜#〜] edit [〜#〜]Play 2.4では、 注入 が自動的に行われます。したがって、ファイルのコントローラパスの先頭に@を追加するだけでroutes
がトリックになります。
GET / @controllers.Application.index()
古いバージョン(2.1から2.3)では、 Documentantion で説明されているように、グローバルクラスのgetControllerInstanceをオーバーライドする必要があります。
プログラミングの他のことと同様に、-never everは決して正しい答えではありません。 alwaysと同じです。常に例外があり、正しい答えは常に「依存する」ことです。
純粋なOO(私はそれがすべてです))では、静力学の余地はほとんどありません。
典型的な例はユーティリティメソッドです。もちろん、abs()
メソッドをIntegerに追加するだけでよいでしょう。しかし、それはできません。そのため、Math.abs(int i)
で行き詰まっています。
インスタンス自体とは何の関係もない場合は、メソッドを静的にする方が正しいと思う傾向があります。たとえば、クラスPerson
では、人のリストを取得し、今日誕生日のある人の数を返すメソッドを作成できます。たぶん、計算を実行するために必要なデータがプライベートである場合(OO純粋主義者が理解するものです;))、クラス自体でのみこれを行うことができますが、それでもメソッドは明らかにシングルと関係がありません個人インスタンス。
もう1つは内部クラスです。包含型との関係が必要ない場合は、静的にしたいことがよくあります。
私は見たことがないPlay!しかし、その50%以上が静的であると言えば、おそらく設計が間違っていると思います。それも例外ではありません。多くのフレームワークがあります。落胆させないでください。間違いなくそれから学ばないでください!
しかし、それが機能する場合は、引き続き使用できます。
主な問題は、静的メソッドは他の静的メソッドとフィールドにしかアクセスできないため、静的メソッドが共通の静的フィールドを介してアプリケーション(コラボレーターを含む)の残りの部分とランデブーしなければならない「静的リンク」が発生することです。 、柔軟性につながります。
免責事項:私は「遊び」についてはあまり知りません!
静的コントローラーメソッドは確かにPlayの関心領域です。フレームワーク、そしていくつかのテストを行った後、それは私がプレイをしない主な理由です!プロジェクトで。実際に、FOSSプロジェクトのPlay!使用されている。コントローラーのテストはほとんどまたはまったくありません。静的メソッドでは、DIが難しくなる理由です。ここから、Play!すでに少しインスピレーションを得ています。
通常、次のようなコンストラクタがあります。
public HomeController( IService service ) {
_service = service;
}
public Index() {
var data = _service.getData();
return View( data );
}
次に、DIを使用してIService実装をコントローラーに注入します。ポイントは、テストでは、コントローラーを実行する直前にIServiceをインスタンス化し、作成したIServiceに基づいて結果をテストできることです。
Playでは、これは非常に難しくなります。したがって、コントローラのユニットテストは困難になります。それは、私にとって重要な問題です。したがって、Play以外のフレームワークを探す傾向があります。 Java世界の中で。まあ、なぜオリジナルと一緒にJRubyを使用しないのですか?
静的メソッドは、主にコントローラーのアクションメソッドで使用されます。これらのメソッドは、モデルから必要なデータをフェッチしてビューに公開することを目的としています。
それらは可能なHTTPリクエストそれぞれに何らかの形で対応し、それらのHTTPリクエストが完全にステートレスであるように。
構造的プログラミングでは、一方ではプロシージャがあり、もう一方では変数がありますが、OOPパラダイムでは、プロシージャと変数を全体として扱います。
つまり、インスタンスメソッド(プロシージャ)とインスタンス変数を持つオブジェクトがあります。
ただし、コントローラーアクションはステートレスです。つまり、リクエストからすべての変数を取得します(おそらくキャッシュからも取得できますが、その場合、最終的にリクエストから取得されるある種のセッションIDが必要です)。したがって、コントローラのアクションは、statelesプロシージャとまったく同じであり、モデルとは異なり、OOPパラダイム)には特に適合しません。
少なくとも、シングルトンオブジェクトを使用できると思います。
Javaのシングルトンは、すべてのstaticを使用するよりも大きな違いはありません。状態として保存することもあまりありません。心配する必要はありません。
それで、私はこれについて心配する必要がありますか?遊び方をしました!開発者は、これらすべての静力学が問題を引き起こさないようにプログラムを作成しましたか?
そうではありません。実際、それは大丈夫です。
Playは、たとえば node.js などの機能的なアプローチを採用しており、JavaではなくScalaのほうが Typesafe Stack のように間違いなく「理にかなっています」。たとえば押しています。他のポスターが指摘しているように、Javaはバイトコードインストルメンテーション(アスペクトJの1つ)を使用して拡張され、よりステートレス/機能的な方法で動作します。 Scalaはデフォルトでこれを行います。
私はまた、プレイ中の静的メソッドの数にも驚いていますが、それがうまく機能しない場合はどうして...
実は私は先生に同意しません。
オブジェクトに状態(グローバル変数など)がなく、例のメソッドのみが含まれている場合、静的メソッドではなくオブジェクトを使用するメリットはありません。後で状態を追加することを計画している場合(共有してはならない状態)、またはインターフェイスを使用していて実装を簡単に切り替えられるようにする場合を除いて、静的メソッドを使用する方が簡単です...
JDK自体、Apacheコモンズ、または多くのフレームワークには、静的メソッドが含まれています。
実際、JPA.Javaのようなクラスについてはどうでしょうか https://github.com/playframework/play/blob/master/framework/src/play/db/jpa/JPA.Java
静的メソッドのみを使用し、静的状態を維持します。これは奇妙なことかもしれませんが、実際には、メソッドがオブジェクトではなく静的コンテキストで使用されることを除いて、シングルトンを使用するのと少し似ています。主な違いは、毎回getInstance()を呼び出す必要がないことです。
「getInstance」を呼び出すのはユーザーフレンドリーではなく、xmlまたは自動配線ですべての場所にsessionFactoryを注入するのではなく、どこでも(スレッドにリンクされた)セッションを簡単に取得できるのはクールなので、これは使いやすさのためにそのように設計されたと思います。 ..
正しく使用しないと設計に危険を及ぼす可能性があるため、教授はおそらく静的変数の使用を避けるように指示しています。ただし、多くの場合、静的メソッドをシングルトンに置き換えてもデザインは改善されません。インスタンスメソッドでメソッドを呼び出しても、オブジェクトは引き続き密結合されます...
したがって、おそらく密結合を本当に気にしない場合を除いて、静力学の使用を避けることがルールになるはずです。
この場合、JPA.xxx()メソッドを呼び出すと、コードはフレームワークのJPAクラスを再生するために密結合されます。しかし、私はあなたが少なくともいくつかのやり直しなしにあるフレームワークから別のフレームワークに簡単に切り替えることができるようにplayが設計されているとは思いません...
これは、EJB3仕様などとの大きな違いです。EJB3エンティティマネージャーのメソッドが静的である場合、HibernateEntityManager.xxx()またはToplinkEntityManager.xxx()を呼び出して、コードを実装に密結合する必要があります。この場合、共通のインターフェースがあります(インターフェースに静的メソッドを追加することはできません)。
Play内でSpring DIを使用できるようになりました https://stackoverflow.com/a/16552598/104 を参照してください。私はそれを使用しており、これまでのところ問題なく動作します。
静的メソッドを使用する理由の1つは、静的インポートであり、これにより表記を短くしてコードを読みやすくすることができます。これは、GuavaやApache Commonsなどの静的な呼び出しが多数ある可能性のあるユーティリティライブラリを使用する場合に特に当てはまります。
非静的コントローラーメソッドが supported になりました。Play2.1ではコントローラーインジェクションを使用しているため、最初からそれらがなかった理由はあまり明確ではありません。
オブジェクト指向プログラミングの純粋主義者であれば、static
メソッド/フィールドを使用するべきではありませんが、それらは安全に使用でき、心配する必要はありませんIMHO。