インスタンスフィールドに依存しないメソッドを静的にしますか?


19

最近、統合テストフレームワーク用、Javaプロジェクト用にGroovyでプログラミングを開始しました。Intellij IDEAをGroovyプラグインで使用していますが、非静的でインスタンスフィールドに依存しないすべてのメソッドの警告として表示されて驚いています。ただし、Javaでは、これは問題ではありません(少なくともIDEの観点から)。

インスタンスフィールドに依存しないすべてのメソッドを静的関数に変換する必要がありますか?trueの場合、これはGroovy固有のものですか、それとも一般的なOOPで利用可能ですか?なぜ?


これらのメソッドは他のインスタンスメソッドを呼び出しますか?それとも、文字通りそのクラスのオブジェクトとはまったく関係ありませんか?例を挙げていただけますか?
レイトーアル

回答:


26

注IDEAは、この持っていることを検査だけでなく、呼ばれるJavaのための「静的」かもしれ方法を

この検査は、安全に静的にできるメソッドをレポートします。クラスの非静的メソッドと非静的フィールドのいずれも参照せず、サブクラスでオーバーライドされない場合、メソッドは静的である可能性があります...

ただし、Javaコードの場合、この検査はデフォルトでオフになっています(プログラマーの判断でオンにできます)。この理由は、いくつかの非常に信頼できる情報源に基づいて、そのような検査の有効性/有用性が問われる可能性が最も高いことです。

まず、公式のJavaチュートリアルでは、メソッドを静的にする必要がある場合にかなり制限があります。

静的メソッドの一般的な使用法は、静的フィールドにアクセスすることです。

上記で与えられたように、デフォルトで言及された検査をオンにすることは、Javaで推奨される静的修飾子の使用に準拠していないと主張できます。

その上、この検査の背後にあるアイデアを使用するか、それを落胆させる賢明なアプローチを示唆する限り、他のいくつかのソースがあります。

たとえば、Java Worldの記事をご覧ください-Mr. Happy Objectは静的メソッドを教えています

インスタンスの状態に依存しないメソッドは、静的として宣言される候補です。

「静的として宣言される候補」と言うことに注意してください。前の例でもinstances()、静的として宣言することを強制するものはありません。メソッドを呼び出すためにインスタンスを必要としないため、静的として宣言すると、呼び出しがより便利になります。インスタンスの状態に依存していないように見えるメソッドがある場合があります。これらのメソッドを静的にしたくない場合があります。実際、インスタンスなしでアクセスする必要がある場合にのみ、静的として宣言することをお勧めします。

さらに、このようなメソッドを静的として宣言することはできますが、設計に挿入される継承の問題のため、そうしたくない場合があります。見てみましょう「効果的なオブジェクト指向設計」あなたが直面する問題のいくつかを見るために...

Googleのテストブログの記事は、静的メソッドがテスト容易性の低下であると主張している限りです。

メンタルエクササイズをしましょう。アプリケーションに静的メソッドしかないと仮定します。(はい、そのようなコードは記述可能です。手続き型プログラミングと呼ばれます。)そのアプリケーションの呼び出しグラフを想像してください。リーフメソッドを実行しようとしても、その状態を設定し、すべてのコーナーケースをアサートしても問題はありません。理由は、リーフメソッドがそれ以上呼び出しを行わないためです。リーフから離れてルートmain()メソッドに近づくと、テストで状態を設定するのが難しくなり、物事を主張するのが難しくなります。多くのことを主張することは不可能になります。テストは徐々に大きくなります。に到達したらmain()ユニットテストがなくなったメソッド(ユニットはアプリケーション全体であるため)に、シナリオテストがあります。テストしようとしているアプリケーションがワードプロセッサであると想像してください。mainメソッドからアサートできるものはあまりありません...

静的メソッドは、他のオブジェクトのファクトリである場合があります。これにより、テストの問題がさらに広がります。テストでは、重要な依存関係をモックに置き換えてオブジェクトを異なる方法で配線できるという事実に依存しています。いったんnewオペレータが呼び出された私たちは、サブクラスでメソッドをオーバーライドすることはできません。そのような静的ファクトリの呼び出し元は、静的ファクトリメソッドが生成した具象クラスに永続的にバインドされます。言い換えれば、静的メソッドの損傷は静的メソッド自体をはるかに超えています。オブジェクトグラフの配線はテストのために物事を分離する方法なので、オブジェクトグラフの配線と構築コードを静的メソッドに突合せることは非常に悪いことです...


上記のように、Javaのデフォルトで前述の検査がオフになっているのはごく自然なことです。

IDE開発者は、広く認知されている推奨事項やベストプラクティスに反して、デフォルトで設定することが非常に重要だと考える理由を説明するのに非常に苦労するでしょう。

Groovyの場合、状況はまったく異なります。Javalobbyの記事Groovyの静的メソッドのモックなど説明されているように、上記の引数、特にテスト容易性に関する引数は適用されません。

テストしているGroovyクラスが別のGroovyクラスの静的メソッドを呼び出す場合、ExpandoMetaClassを使用して、メソッド、コンストラクター、プロパティ、および静的メソッドを動的に追加できます...

この違いが、言及された検査のデフォルト設定がGroovyで反対である理由です。Javaのデフォルトでは「オン」がユーザーの混乱の原因になりますが、Groovyでは反対の設定がIDEユーザーを混乱させる可能性があります。

「メソッドはインスタンスフィールドを使用しないのに、なぜそれについて警告しないのですか?」この質問は、Java(上記で説明したように)に答えるのは簡単ですが、Groovyには、説得力のある説明はありません。


ところで、ReSharperの(C#/ Visual Studio用ジェットブレーンズ社製)同じことを示唆している
コンラッドMorawski

6
副作用のある静的メソッドと副作用のない静的メソッドには重要な違いがあります。Googleの抜粋は実際に前者に対応しています。
assylias

@assyliasありますが、ファクトリメソッドがテストを難しくする方法についても説明します(アプリケーションの依存関係を緊密に結合するため)。依存性注入フレームワークを使用することは、このための最善の回避策の1つであり、他の多くの問題も解決します。
Per Lundberg

5

これがパフォーマンスに何らかの認識可能な影響を与えることを想像するのは困難です。それらを作成することでわかる唯一の利点staticは、インスタンスの状態に影響がないことを視覚的に示すことです。言い換えれば、ソースコードを読んでいる人に、そのメソッドが存在するという理由だけで、そのメソッドについて「興味深い」ことを伝えます。本当の質問は、明確にするのか混乱させるのか? 「なぜこのメソッドは静的なのですか?それはファクトリメソッドなのですか?オブジェクトインスタンスなしでメソッドを呼び出す機能が必要なのですか?」

さらに、一部の人々は静的メソッドが好きではありません。なぜなら、あなたはそれらをモックできないと主張しているため、テスト可能ではない、またはそれらに沿った何かだからです。確かに、たとえばファクトリーメソッドを提供するなど、通常の理由のいずれかで静的にする場合は、それだけです。メソッドがインスタンスの状態に触れないという理由だけでメソッドを静的にすることが義務付けられているかどうかはよくわかりません。


5
(Java内で)静的メソッドはオーバーライドできないと考えてください。多くの場合問題ではありませんが、サブクラスによっては後でその実装を変更できないことを意味します。これは、静的メソッドが正しい答えではなく、設計上の考慮事項の一部であると言うことではありません。

2
@ user40980、それは考慮する価値があります、本当ですが、継承はしばしば誤用される不器用なツールになる可能性があることを考慮する価値があります。いくつかの著名な人物は、すべてのクラスはfinal継承を念頭に置いて、または特に設計する必要があると主張しています。
サラ

3

リファクタリングの可能性を発見できるようにすることだと思います。

メソッドを静的にすると、クラスからユニティクラスに移動できることは明らかです。

また、パラメータの1つのインスタンスメソッドに変換するのも簡単です。多くの場合、これはコードがあるべき場所です。


-1

インターフェースを実装するステートレスクラスがある場合があることに注意してください(たとえばjava.lang.Runnable、メソッドを静的にすることはできません。パターン(Strategyなど)は、いくつかのメソッドを持つステートレスオブジェクトを生成することもできます。

静力学は、シングルトンの最初のいとこです。後で静的から非静的に移行するのは非常に困難です。そのため、状態を追加する必要がある場合は、静的変数の導入を開始することになります。


これは質問にどう答えますか?
gnat

1
なぜ無状態からある状態に移行するのが難しいのですか?私はそれが逆であると言うでしょう。汚染されたものを浄化するよりも、純粋なものを汚染する方が簡単です。
サラ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.