web-dev-qa-db-ja.com

シンプルなソリューションと複雑なソリューション(ただし、パフォーマンスは効率的)のどちらを選択するか。

私は数年前からプログラミングをしていて、ジレンマに陥ることがよくあります。

2つの解決策があります-

  • 1つはシンプルなもの、つまりシンプルなアプローチで、理解と保守が容易です。これには、冗長性、追加の作業(追加のIO、追加の処理)が含まれるため、最適なソリューションではありません。
  • しかし、他のものは、多くのモジュール間の相互作用を伴うことが多く、実装が難しい複雑なアプローチを使用しており、パフォーマンス効率の高いソリューションです。

ハードパフォーマンスがない場合にどのソリューションを試すべきですかSLAを満たす必要があり、シンプルなソリューションでもパフォーマンスSLAを満たすことができますか?)簡単なソリューションに対する同僚の開発者の軽蔑を感じました。

単純なソリューションでパフォーマンスSLAを満たすことができる場合、最も最適な複雑なソリューションを考え出すことは良い習慣ですか?

28
MoveFast

ハードパフォーマンスSLAを満たす必要がなく、単純なソリューションでもパフォーマンスSLAを満たすことができる場合、どのソリューションを試す必要がありますか?

シンプルなもの。仕様を満たし、理解しやすく、保守が容易で、バグが大幅に減ります。

パフォーマンス効率の高いソリューションを提唱するためにあなたがしていることは、投機的な一般性と時期尚早な最適化をコードに導入することです。やめろ!パフォーマンスは、他のほぼすべてのソフトウェアエンジニアリングの「柔軟性」(信頼性、保守性、可読性、テスト容易性、理解可能性など)の粒度に反します。テスト時のパフォーマンスの追跡は、パフォーマンスの後に追跡する必要があることを本当に示しています。

パフォーマンスが重要でない場合は、パフォーマンスを追跡しないでください。問題があったとしても、パフォーマンスのボトルネックが存在することがテストで示されている領域でのみパフォーマンスを追跡する必要があります。単純なバージョンがボトルネックとして表示されない場合は、パフォーマンスの問題をsimple_but_slow_method_to_do_X()をより高速なバージョンに置き換える言い訳にしないでください。

強化されたパフォーマンスは、ほとんどの場合、ホストのコードのにおいの問題によって妨げられます。あなたは質問でいくつか言及しました:複雑なアプローチ、実装するのが難しい、より高い結合。それらは本当に引き込む価値がありますか?

58
David Hammen

短い回答:複雑なものよりも単純なソリューションを優先し、 KISSとYAGNI 原則

プロジェクトの初期要件とソフトウェアは完璧ではないため、アプリケーションの開発/使用に応じて変更が必要です。開発段階での反復アプローチは、物事を単純に開始し、必要に応じて拡張するのに非常に適しています。最も単純なソリューションは、柔軟性があり、保守がより簡単です。

さらに、アプリケーションを構築しながら、スマートになり、アドホックな最適化を行うことはお勧めできません。ソリューションが複雑になる可能性があります。知られているように、"premature optimization is the root of all evil"-Knuthの本から

12
Yusubov

ここでKnuthから教訓を学びましょう:「私たちは小さな効率を忘れるべきです。つまり、時間の約97%を言います。時期尚早な最適化がすべての悪の根源です」。

ソリューションについて次の順序で考えてください。最初に、常に、正確さ。第二に、明快さとシンプルさを向上させます。 3つ目は、必要性と効率性を実証できる場合のみです。

効率を追加すると、ほとんどの場合、何か重要なコストが発生します。したがって、必要なことがわかっている場合にのみ追求する必要があります。

8
simon

単純なソリューションでパフォーマンスSLAを満たすことができる場合、最も最適な複雑なソリューションを考え出すことは良い習慣ですか?

最適は曖昧な言葉です!

結局のところ、複雑なものを維持する必要がある場合にリスクが大きく、単純なもので十分な場合は、常に単純なものの方を誤ると思います。

複雑なものでは不十分であるというリスクを追加してください。KISSがおそらく正しい答えです。

3
Andrew

2つのアプローチを評価する場合、1つは単純ですが効率が低く、もう1つはより複雑で効率的です。問題とプロジェクトドメインを考慮する必要があります。

15年以上のメンテナンスと20年以上の使用の寿命を計画しているヘルスケア業界向けの数十億のソフトウェアプロジェクトを考えてみましょう。このようなプロジェクトでは、パフォーマンスは明らかに問題になりませんが、プロジェクトの複雑さと構造は、プロジェクトのメンテナンスに大きな問題を引き起こす可能性があり、少なくとも15年間は続きます。保守性とシンプルさが何よりも優先されます。

次に、別の例を考えます。今後5年以上、会社の今後のゲームを強化することになっているコンソールゲームエンジン。ゲームは極端にリソースに制約のあるプログラムであるため、多くの場合、効率は保守性よりも優先されます。ソフトウェア開発の「ベストプラクティス」に反する場合でも、独自の非常に具体的なデータ構造といくつかのタスクのアルゴリズムを作成することは非常に重要です。これの良い例は Data Oriented Design であり、実際のオブジェクトではなく、類似のデータ配列にデータを格納します。これは、局所性の参照を増やすためであり、CPUキャッシュの効率を向上させます。実用的ではありませんが、特定のドメインではvery非常に重要です。

2
zxcdw

シンプルな方がいいです。私の意見では、時期尚早の最適化はそれらが解決するのと同じくらい多くの問題を引き起こします。多くの場合、優れた設計により、特定の実装がボトルネックになった場合に将来変更することができます。

したがって、最終的には、可能な限り柔軟に設計しますが、柔軟性のために単純さをあまり犠牲にしません。

2

どちらが安いですか?

ほとんどの場合、少し遅いシンプルなソリューションはパフォーマンスの点で完全に許容可能であり、シンプルなため、開発、保守、および最終的な交換のコストが低くなります。

一方、速度が非常に重要な場合もあります。速度を少しでも改善することで得られる経済的利益は、より複雑なソリューションのコストの増加よりもはるかに大きくなる可能性があります。たとえば、トランザクションを完了するまでの時間を0.01秒短縮すると、証券取引システムの収益性が大幅に向上します。数百万人のユーザーをサポートするシステムの効率が10%向上すると、サーバーのコストを大幅に削減できます。

それで、あなたがあなた自身に尋ねなければならない質問は次のとおりです:複雑なソリューションを使用することはその追加費用を支払うために収益に十分な影響を与えますか?実際には、クライアントが請求書を支払い、潜在的なメリットを享受しているため、クライアントに決定を依頼する必要があります。 1つの適切なオプションは、最初に単純なソリューションを使用して、考えられる改善としてより複雑なソリューションを提供することです。これにより、システムを起動して実行し、クライアントにテストを開始するための何かを与えることができます。その経験により、より複雑なソリューションを実装する(または実装しない)かどうかを決定することができます。

2
Caleb

これは常に難しい質問であり、私は答えが一方向に変動しているのを見るので、私は反対側のゲームをプレイします。どちらの答えも正しいとは言いませんが、非常に柔らかく、ケースバイケースのトピックです。

複雑でありながら高性能なソリューションについての1つのことは、常にそこから常に生きている問題を文書化できることです。私は一般的に自己文書化コードのファンですが、私が遅くならないように感じさせる時間で応答するソフトウェアのファンでもあります。複雑だが高性能のソリューションを採用する場合は、それほど悪くないようにするために何ができるかを検討してください。

それをインターフェイスにラップし、それ自体のアセンブリに配置します。おそらくそれ自体がすべてのプロセスです。 leaks を避けるために、可能な限り疎結合にして、その周囲にできるだけ厚い抽象化壁を配置します。将来の回帰を保存するために、たくさんの単体テストを書いてください。

コードでそれを文書化し、実際の文書を書くことも検討してください。複雑なデータ構造とそれらがどのように文書化されているかを考え、それを説明するデータ構造の本/ウィキペディアの記事がないコードからそれらの1つの実装を理解しようとすることを想像してみてください。それでも、これらの複雑なデータ構造は実際には良いものであり、誰かが私たちの言語でそれらを実装したことは有益です。

私たち全員がTCP/IPスタックでメッセージを送信していることを忘れないでください。メッセージを見るとコードが取得するのと同じくらいハリーである可能性が高く、明示的にそうすることで、私たち全員が必要とする方法も実行します。おそらくあなたの問題はこのレベルの最適化を必要としないかもしれませんが、おそらくそれは必要ですが、私たち全員が時々しなければならないので、この質問に取り組むときは注意してください:そこにはドラゴンがいます。

1
Jimmy Hoffa

私は、パフォーマンスSLAがない領域でこの作業に参加しています。コンピューターグラフィックスのオフラインレンダラーに関しては、ユーザーに「満足のいくパフォーマンス」はありません。なぜなら、ユーザーはすでに膨大な金額を使い、クラウド全体にコンピューティングを分散させ、最先端のレンダラーでもファームをレンダリングしているからです。フィルム用の制作品質の画像とフレームを出力するには、例えば.

しかし、私が長年この領域で働いている人として、効率を優先して保守性を大幅に低下させるソリューションは、実際には常に変化するパフォーマンス要件に逆らって機能していると言わざるを得ません。なぜなら、物事が足元でシフトしているため、今後数年間ソリューションを効果的に維持できない場合(周囲のコードの点でも、競合他社がお互いに優れたパフォーマンスを発揮し続けるためにユーザーが期待する点でも)、ソリューションはすでに陳腐化に向かっており、卸売り交換の必要性。

コードをより高速に実行する方法として、VTuneのようなプロファイラーの究極の目的はわかりません。彼らの究極の価値は、私が生産性を低下させず、絶えず増大するパフォーマンスの要求を満たすことを確実にすることです。全体的に見えるミクロ最適化を適用する必要がある場合は、プロファイラーを実際のユーザーケースに対して実行することと組み合わせて(そしてmightが重要だと思うテストケースではなく)、確認しますそのような必然的に見栄えのする最適化を、表示される上位のホットスポットのみに非常に慎重に適用し、非常に慎重に文書化します。なぜなら、そのソリューションの場合、今後数年間は再訪して維持し、微調整して変更する必要があるためです。実行可能なままです。

そして特に、最適化されたソリューションがより多くのカップリングを含む場合、私は本当にそれを使用するのをためらいます。コードベースの最もパフォーマンスが重要な領域で私が高く評価するようになった最も価値のあるメトリックには、デカップリングがあります(何かが機能するために必要な情報の量を最小限に抑えることで、直接変更が必要でない限り、変更が必要になる可能性を最小限に抑えます) )、これらの重要な領域は、物事が変化する理由を大幅に増加させるためです。つまり、何かが機能するために必要な情報が少ないほど、変更の理由が少なくなり、変更の理由を最小限に抑えることは、とにかく常に変化しなければならないため、私の特定の領域の生産性を向上させる上で非常に重要です。それ以外の場合は1年で廃止されます)。これを最小限に抑えるだけでなく、そのような変更のコストを削減するのに役立ちます。

私が見つけた最大かつ最も効果的なソリューションは、効率性、保守性、および生産性が互いに正反対であるものではありません。私の探求は、これらの概念を、おそらくそれを実現できる限り調和させることを試みることです。

0
Dragon Energy