5

StackOverflow で時期尚早の最適化に関する多くの質問を見ました (そして検索しました)。巷の言葉は、それがすべての悪の根源であるということです。:PI 私はしばしばこれについて有罪であることを告白します。コードの読みやすさを犠牲にして速度を最適化するわけではありませんが、タスクにより適していると思われるデータ型とメソッドを使用して論理的な方法でコードを書き直します (たとえば、Actionscript 3 では、型なし配列の代わりに型付きベクトルを使用します)。コードをよりエレガントにすることができれば、そうします。これは通常、自分のコードを理解するのに役立ち、これらの変更を行っている理由がよくわかります。

いずれにせよ、今日考えていたのは、OOP ではカプセル化を促進し、実装を隠してインターフェースを促進しようとして、クラスが疎結合になるようにすることです。アイデアは、内部で何が起こっているかを知らなくても機能するもの、つまりブラック ボックスのアイデアを作成することです。

そういうわけで、ここに私の質問があります.OOPはモジュール性を促進するので、クラスレベルでコードの深い最適化を試みるのは賢明ですか? それとも、これは時期尚早の最適化のカテゴリに分類されますか? ユニットテストを容易にサポートする言語を使用すると、クラス自体が入力を受け取り、出力を生成するモジュールであるため、クラスのテスト、ベンチマーク、および最適化を行うことができると考えています。しかし、コードを書いている一人の人間として、プロジェクトが完全に終了するまで待ってから最適化を開始する方が賢明かどうかはわかりません。

参考までに: 私はこれまでチームで働いたことがないので、このような経験を持つ開発者にとって明らかなことは、私にとってはなじみのないことかもしれません。

この質問が StackOverflow に適していることを願っています。クエリに直接答えた別の質問は見つかりませんでした。

ありがとう!

編集:質問について考えてみると、「プロファイリング」が「単体テスト」ではなく正しい用語だった可能性があることに気付きました。単体テストではモジュールが正常に動作することを確認し、プロファイリングではパフォーマンスを確認します。さらに、私が以前に尋ねるべきだった質問の一部 - 個々のモジュールを作成した後にプロファイリングしても、アプリケーションが完成した後のプロファイリングの時間は短縮されませんか?

私の質問は、私がやろうとしているゲーム開発から生じています - グラフィックエンジンなど、最適に動作するモジュールを作成する必要があります (それらが別の話になるかどうか:D)。パフォーマンスがそれほど重要でないアプリケーションでは、おそらくこれについて心配する必要はありません。

4

5 に答える 5

2

コードの読みやすさを犠牲にして速度を最適化することは実際にはありませんが、タスクにより適切と思われるデータ型とメソッドを使用して、論理的な方法でコードを書き直します [...] そして、コードをよりエレガントにすることができれば、そうします。これは通常、自分のコードを理解するのに役立ちます

これは実際には最適化ではなく、よりクリーンなコードとより良い設計のためのリファクタリングです*。そのため、それは良いことであり、少しずつ継続的に実践する必要があります. ボブ・マーティンおじさん (彼の著書Clean Codeの中で) は、ソフトウェア開発に適応したボーイスカウトのルールを普及させました

言い換えれば、タイトルの質問に答えるには、はい、コードをリファクタリングしてユニットテストを可能にすることは良い習慣です。これの 1 つの "極端な" は、テスト駆動開発です。最初にテストを記述し、次にテストに合格するコードを追加します。このようにして、コードは最初から単体テスト可能に作成されます。

*細かいことを言うのではなく、一般的な用語を明確にし、同じ用語を同じ意味で使用することを確認するのに役立ちます.

于 2011-03-31T21:27:59.053 に答える
1

確かに、最適化は最後のタスクとして残すべきだと思います (ただし、最初のドラフトを書いているときに、どこに戻って最適化する必要があるかを認識しておくことは良いことです)。コードの秩序と清潔さを維持するために、物事を繰り返しリファクタリングするべきではないと言っているわけではありません。何かが現在目的を果たしており、アプリケーションの要件を台無しにしていない場合は、要件に最初に対処する必要があります.それらの線に沿った何か)。Korin の方法論にも同意します。時間が許せば、最初に機能を構築して、心のコンテンツ (または理論上の限界のいずれか早い方) に合わせて最適化します。

于 2011-03-31T21:24:36.960 に答える
1

時期尚早の最適化が悪いことである理由は次のとおりです。それには多くの時間がかかる可能性があり、どこで時間を最大限に活用できるかが前もってわからないからです。

たとえば、クラスの最適化に多くの時間を費やした後、アプリケーションのボトルネックが、実行時間の点ではるかにコストのかかるネットワーク遅延または同様の要因であることが判明する場合があります。最初は全体像を把握していないため、時期尚早の最適化は時間の無駄遣いにつながります。この場合、クラス コードを最適化するよりも、レイテンシの問題を修正することをお勧めします。

于 2011-03-31T21:24:38.687 に答える
1

パフォーマンスの最適化のために、コードの可読性と優れた設計を決して低下させてはならないと強く信じています。

パフォーマンスが重要なコードを書いている場合は、コードのスタイルと明瞭さを落としても問題ないかもしれませんが、これは平均的なエ​​ンタープライズ アプリケーションには当てはまりません。ハードウェアは急速に進化し、日々安価になっています。最終的には、他の開発者に読まれるコードを書くことになるので、それをうまくやった方がよいでしょう。

慎重に作成されたコードを読むのはいつでも美しいものです。すべてのパスには、使用方法を理解するのに役立つテストがあります。多くのクレイジーなことを行うスパゲッティの代替手段よりも50ミリ秒遅いかどうかはあまり気にしません。

于 2011-03-31T21:29:20.613 に答える
1

はい、単体テストの最適化をスキップする必要があります。通常、必要に応じて最適化すると、コードがより複雑になります。シンプルさを目指します。単体テスト用に最適化すると、実際には本番用に最適化を解除できます。

単体テストでパフォーマンスが非常に悪い場合は、設計を確認する必要がある場合があります。最適化する前に、アプリケーションでテストして、パフォーマンスが同等に悪いかどうかを確認します。

編集: 処理されるデータのサイズが異なる場合、最適化解除が発生する可能性があります。これは、データのセットを操作するクラスで発生する可能性が最も高くなります。応答は線形かもしれませんが、幾何学的で元々速いのに比べて、もともと遅いです。単体テストで小さなデータ セットを使用する場合は、幾何学的解を単体テスト用に選択できます。データ パフォーマンス タンクの大規模なセットで生産がクラスに到達したとき。

並べ替えアルゴリズムは、この種の動作とその結果の非最適化の典型的なケースです。他の多くのアルゴリズムにも同様の特徴があります。

EDIT2: 私の最も成功した最適化は、データがディスク上のメモリ マップ ファイルに格納されたレポートの並べ替えルーチンでした。ディスク アクセスを必要としない適度なデータ サイズで、ソート時間は妥当でした。サイズの大きいデータ セットでは、データの処理に数日かかる場合があります。レポートの最初のタイミングが示されました。データの選択に 3 分、データの並べ替えに 3 日、レポートに 3 分。ソートの調査により、それは完全に最適化されていないバブル ソート (サイズ n のデータ セットに対して n-1 フル パス) であり、big O 表記でおよそ n 平方であることが示されました。並べ替えアルゴリズムを変更すると、このレポートの並べ替え時間が 3 分に短縮されました。単体テストでこのケースをカバーできるとは思っていませんでした。元のコードは、小さなセットで得られるのと同じくらい単純 (高速) でした。非常に小さなセットの場合、置換ははるかに複雑で遅くなりました。しかし、大きな O 表記の n log n というより直線的な曲線を使用すると、大きなセットをより高速に処理できます。(注: メトリクスが得られるまで、最適化は試みられませんでした。)

実際には、モジュール実行時間の少なくとも 50% を占めるルーチンの 10 倍の改善を目指しています。実行時間の 55% を使用するルーチンでこのレベルの最適化を達成すると、合計実行時間の 50% を節約できます。

于 2011-03-31T21:32:06.940 に答える