静的メソッドの使用とメソッドを含むクラスのインスタンス化のパフォーマンス

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

質問

C#でプロジェクトに取り組んでいます。以前のプログラマーはオブジェクト指向プログラミングを知らなかったため、コードの大部分は数十から数百のメソッドにまたがる巨大なファイル(約4〜5000行)にありますが、クラスは1つだけです。そのようなプロジェクトをリファクタリングするのは大変な仕事なので、私は今のところそれで生きることを半学んでいます。

コードファイルの1つでメソッドが使用されるたびに、クラスがインスタンス化され、オブジェクトインスタンスでメソッドが呼び出されます。

この方法でパフォーマンスに顕著なペナルティがあるかどうか疑問に思っていますか?すべてのメソッドを「今のところ」静的にすべきですか?そして、最も重要なこととして、アプリケーションは何らかの方法でそれから利益を得るでしょうか?

役に立ちましたか?

解決

こちらから、静的呼び出しは4〜5倍高速になりましたインスタンスメソッドを呼び出すたびにインスタンスを構築するよりも。ただし、呼び出しごとに数十ナノ秒程度しか話していないため、メソッドを何百万回も呼び出す非常にタイトなループがない限り、利点を感じることはほとんどありません。単一のインスタンスを外部で構築することで同じ利点を得ることができますそのループとそれを再利用します。

新たに静的なメソッドを使用するためにすべての呼び出しサイトを変更する必要があるため、徐々にリファクタリングに時間を費やす方がよいでしょう。

他のヒント

私は職場で同様の問題に対処しました。私の前のプログラマーは、すべてのBLL関数がダンプされる1つのコントローラークラスを作成しました。

現在、システムを再設計しており、制御対象に応じて多くのControllerクラスを作成しています。例:

UserController、GeographyController、ShoppingController ...

各コントローラークラス内には、シングルトンパターンを使用してキャッシュまたはDALを呼び出す静的メソッドがあります。

これにより、2つの主な利点が得られました。それはわずかに高速です(約2〜3倍高速ですが、ここではナノ秒を話していました; P)。もう1つは、コードがはるかに簡潔であることです

i.e

ShoppingController.ListPaymentMethods()

の代わりに
new ShoppingController().ListPaymentMethods()

クラスが状態を維持しない場合、静的メソッドまたはクラスを使用するのが理にかなっていると思います。

オブジェクトが他に何を含んでいるかに依存します-" object"は単なる関数の束であり、おそらく世界の終わりではないでしょう。しかし、オブジェクトに他のオブジェクトの束が含まれている場合、インスタンス化すると、そのすべてのコンストラクター(および削除された場合はデストラクター)が呼び出され、メモリーの断片化などが発生する可能性があります。

とはいえ、現在のところパフォーマンスがあなたの最大の問題であるとは思えません。

書き換えの目標を決定する必要があります。テスト可能で拡張可能な&を使いたい場合オブジェクトとそのインスタンスメソッドを使用してみてください。これはすべて、オブジェクト指向プログラミングであり、クラス指向プログラミングではありません。

インターフェイスを実装するクラスを定義し、インスタンスメソッドを実行すると、オブジェクトの偽造やモック作成は非常に簡単です。これにより、徹底した単体テストが迅速かつ効果的になります。

また、適切なオブジェクト指向の原則に従う場合( http: //en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29 )および/またはデザインパターンを使用します。多くのインスタンスベース、インターフェイスベースの開発を行い、多くの静的メソッドは使用しません。

この提案に関して:

  
    

オブジェクトを作成するだけで、メソッドを呼び出すことができます。     どうやらオブジェクトに副作用はありません(説明から私はこれを仮定しています)。

  

これはドットネットショップでよく見られますが、これはオブジェクト指向の重要な概念であるカプセル化に違反しています。メソッドが静的であるかどうかで、メソッドに副作用があるかどうかを見分けることはできません。カプセル化を破るだけでなく、これは、副作用が発生するようにメソッドを変更する場合、メソッドを静的からインスタンスに変更する必要があることを意味します。この1つのオープン/クローズの原則を読んで、上記の推奨アプローチがどのようにそれを念頭に置いて機能するかを確認することをお勧めします。

古い栗、「時期尚早な最適化がすべての悪の根源」であることを思い出してください。この場合、これは、パフォーマンスの問題があることがわかるまで、不適切な手法(クラス指向プログラミング)を使用してフープを飛び越えないことを意味すると思います。それでも問題をデバッグし、最も適切なものを探します。

静的メソッドは非常に高速で、使用するメモリも大幅に少なくなります。少し速いという誤解があります。ループに配置しない限り、少し高速です。ところで、一部のループは小さく見えますが、実際には、ループを含むメソッド呼び出しも別のループであるためです。レンダリング機能を実行するコードの違いを知ることができます。残念ながら、多くの場合、メモリがはるかに少ないことは事実です。インスタンスにより、姉妹メソッドと情報を簡単に共有できます。静的メソッドは、必要なときに情報を要求します。

しかし、車の運転のように、速度は責任をもたらします。通常、静的メソッドには、対応するインスタンスよりも多くのパラメーターがあります。インスタンスは共有変数のキャッシュを処理するため、インスタンスメソッドはよりきれいに見えます。

ShapeUtils.DrawCircle(stroke, pen, origin, radius);

ShapeUtils.DrawSquare(stroke, pen, x, y, width, length);

VS

ShapeUtils utils = new ShapeUtils(stroke,pen);

util.DrawCircle(origin,radius);

util.DrawSquare(x,y,width,length);

この場合、ほとんどの場合、インスタンス変数がすべてのメソッドで使用されるたびに、インスタンスメソッドはそれだけの価値があります。インスタンスは状態についてではなく、共有についてです。共通状態は共有の自然な形ですが、それらは同じではありません。一般的な経験則は次のとおりです:メソッドが他のメソッドと密接に結合している場合--- 1つが呼び出されたときに互いに愛し合っている場合、他のメソッドも呼び出す必要があり、おそらく同じカップの水を共有します- -、インスタンス化する必要があります。静的メソッドをインスタンスメソッドに変換するのはそれほど難しくありません。共有パラメータを取得して、インスタンス変数として配置するだけです。他の方法は難しいです。

または、静的メソッドをブリッジするプロキシクラスを作成できます。理論的には非効率的と思われるかもしれませんが、実践は別の話をします。これは、DrawSquareを1回(またはループで)呼び出す必要があるときは常に、静的メソッドに直接進むためです。ただし、DrawCircleとともに何度も使用する場合は、常にインスタンスプロキシを使用します。たとえば、System.IOクラスのFileInfo(インスタンス)とFile(静的)です。

静的メソッドはテスト可能です。実際、インスタンス1回よりもさらにテスト可能です。メソッドGetSum(x、y)は、単体テストだけでなく、負荷テスト、統合テスト、使用テストに対して非常にテスト可能です。インスタンスメソッドは単体テストには適していますが、他のすべてのテスト(単体テストよりも重要)にとっては恐ろしいため、最近では多くのバグが発生します。すべてのメソッドをテスト不能にするのは、(Sender s、EventArgs e)のような意味のないパラメーター、またはDateTime.Nowのようなグローバルな状態です。実際、静的メソッドはテスト容易性が非常に優れているため、新しいLinuxディストリビューションのCコードのバグは、平均的なOOプログラマーよりも少なくなっています(彼は私が知っている***)。

この質問には、あなたが尋ねた方法で部分的に答えていると思います。あなたが持っているコードには、パフォーマンスに顕著な ペナルティがありますか?

罰則が目立たない場合、必ずしも何もする必要はありません。 (言うまでもなく、コードベースは、立派なオブジェクト指向モデルへの漸進的なリファクタリングから劇的に利益を得るでしょう)。

私が言っていることは、パフォーマンスの問題は、問題だと気付いたときだけの問題だと思います。

オブジェクトに対して副作用を持たないように見えるメソッドを呼び出すことができるように、オブジェクトを作成するのは馬鹿げているようです(説明から、これを想定しています)。私にとっては、より良い妥協点はいくつかのグローバルオブジェクトを持ち、それらを使用することだと思われます。そうすることで、通常グローバルな変数を適切なクラスに入れて、スコープをわずかに小さくすることができます。

そこから、これらのオブジェクトのスコープを徐々に移動して、適切なOOPデザインができるようにします。

次に、 I がおそらく使用するアプローチは異なります;)。

個人的には、構造とそれらに作用する機能に焦点を当て、それらを少しずつメンバーを持つクラスに変換しようとするでしょう。

質問のパフォーマンスの面に関しては、静的メソッドはオブジェクトの構築、受け渡し、分解を伴わないため、わずかに高速になります(ただし、それほどではありません)。

PHPでは無効です。
オブジェクトメソッドは高速です:
http://www.vanylla.it/tests/static-method-vs -object.php

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top