web-dev-qa-db-ja.com

コードの記述方法の段階的な変化は、システムのパフォーマンスに影響を与えましたか?そして、私は気にする必要がありますか?

TD; DR:

私が尋ねていることに関していくつかの混乱があったので、これが質問の背後にある推進力のアイデアです:

私はいつもその質問が何であるかを意図していました。元々うまく表現できていなかったのかもしれません。しかし、意図は常に「モジュラー、分離、疎結合、分離、リファクタリングされたコード」であり、「モノリシックな単一ユニット、すべてを1か所で実行する」よりも、その性質上著しく遅い、 1つのファイル、密結合 "コード。残りは、私がそのとき、または今、あるいは後で遭遇した、詳細とこれのさまざまな症状です。確かにある程度の速度は遅いです。デフラグされていないディスクのように、どこからでも断片を取得する必要があります。遅いです。確かに。しかし、気にする必要がありますか?

そして問題は...

マイクロ最適化、時期尚早の最適化などについてではありません。「これまたはその部分を最適化して死ぬ」ことについてではありません。

それは何ですか?

それは、overallの方法論と手法、および時間の経過とともに出現したコードの記述に関する考え方についてです。

  • 「このコードを依存関係としてクラスに挿入する」
  • 「クラスごとに1つのファイルを書き込む」
  • 「データベース、コントローラー、ドメインからビューを分離する」。
  • スパゲッティ同種の単一のコードブロックを作成するのではなく、一緒に機能する多くの個別のモジュール式コンポーネントを作成する

それは、現在-この10年以内に-ほとんどのフレームワークで見られ、支持され、規約で支持され、コミュニティ経由で受け継がれているコードの方法とスタイルに関するものです。これは、「モノリシックブロック」から「マイクロサービス」への考え方の転換です。それに伴い、マシンレベルのパフォーマンスとオーバーヘッド、および一部のプログラマレベルのオーバーヘッドという点で代償が生じます。

元の質問は次のとおりです:

コンピュータサイエンスの分野では、プログラミングに関して、考え方が著しく変化していることに気づきました。私はよくこのようなアドバイスに出くわします:

  • 小さな関数単位のコードを記述します(この方法でテストおよび保守がより容易になります)
  • ほとんどのメソッド/関数の長さが数行になり、その目的が明確になるまで、既存のコードをますます小さなコードのチャンクにリファクタリングします(その目的が明確になります(これにより、大きなモノリシックブロックと比較して、より多くの関数が作成されます)。
  • 1つのことだけを行う関数を記述します-関心事の分離など(通常、スタック上により多くの関数とより多くのフレームを作成します)
  • より多くのファイルを作成します(ファイルごとに1つのクラス、分解目的、MVC、ドメインアーキテクチャ、デザインパターン、OOなどのレイヤー目的で、より多くのファイルシステムコールを作成するためのより多くのクラス)。

これは、2500行にわたるメソッドがあり、大きなクラスと神のオブジェクトがすべてを実行する「古い」または「古い」または「スパゲッティ」コーディングプラクティスと比較した変更です。

私の質問はこれです:

呼び出しがマシンコード、1sと0s、アセンブリー命令、HDDプラッターになると、完全にクラスで区切られたOOさまざまなリファクタリングされた小さいコード-to-tiny関数とメソッドは、余計なオーバーヘッドを生成しすぎますか?

詳細

OOコードとそのメソッド呼び出しが最終的にASMでどのように処理されるか、およびDB呼び出しとコンパイラー呼び出しがHDDプラッターのアクチュエータアームの移動にどのように変換されるかについては、あまり詳しくありませんが、いくつかのアイデアがあります。追加の関数呼び出し、オブジェクト呼び出し、または「#include」呼び出し(一部の言語)は、追加の命令セットを生成し、それによってコードのボリュームを増やし、さまざまな「コード配線」オーバーヘッドを追加すると思います実際の「有用な」コードを追加せずに。また、ASMを実際にハードウェアで実行する前に、ASMに対して適切な最適化を行うこともできると思いますが、その最適化でできることはそれだけです。

したがって、私の質問-十分に分離されたコード(数百のファイル、クラス、デザインパターンなどに分割されたコード)が実際に導入するオーバーヘッド(スペースと速度)が「1つの大きなメソッドこのオーバーヘッドにより、すべてが1つのモノリシックファイルに含まれています。

明確にするために更新:

同じコードを使用して分割、リファクタリング、デカップリングより多くの関数、オブジェクト、メソッドおよびクラスに分解すると、ますますパラメータの受け渡しになると想定しています。 =小さなコード片の間。確かに、リファクタリングコードはスレッドを実行し続ける必要があり、パラメーターを渡す必要があります。より多くのメソッド、またはより多くのクラス、またはより多くのファクトリメソッドのデザインパターンは、単一のモノリシッククラスまたはメソッドの場合よりも、さまざまな情報のビットを渡すことによるオーバーヘッドmoreが多くなります。

全コードの最大70%がASMのMOV命令で構成されていると(TBDを引用して)どこかで言われました-実際の計算ではなく、適切な変数でCPUレジスタをロードします。私の場合、Push/POP命令を使用してCPUの時間をロードし、さまざまなコード間でのリンケージとパラメーターの受け渡しを提供します。コードを小さくするほど、より多くのオーバーヘッド「リンケージ」が必要になります。このリンケージがソフトウェアの肥大化とスローダウンを助長するのではないかと心配しています。これについて心配する必要があるかどうか、また、もしあればどれだけ心配する必要があるのでしょうか。は、これらのプラクティスを使用して構築されたソフトウェアと共存し、使用する必要があります。

更新:複数のファイル

古いコードを徐々に置き換えている新しいコードを書いています。特に、以前のクラスの1つが(前述のように)〜3000行のファイルであることに気付きました。今では、テストファイルを含み、PHPフレームワークを含まない)を含まない、さまざまなディレクトリに配置された15〜20個のファイルのセットになっています。ディスクI/Oに関しては、1つの大きなファイルをロードするよりも複数のファイルをロードする方が遅くなります。もちろん、すべてのファイルがロードされるわけではなく、必要に応じてロードされ、ディスクキャッシュとメモリキャッシュのオプションが存在しますが、それでも_loading multiple files_は、メモリに_loading a single file_よりも多くの処理を必要とします。

PDATE:Dependency Inject everything

しばらくして、これに戻ってきます。私の質問は誤解されていたと思います。あるいは、私はいくつかの答えを誤解することにしました。いくつかの回答が特定されているため、私はマイクロ最適化について話していません(少なくとも、マイクロ最適化について話していることを誤解していると思います)全体として、「リファクタリングコードを使用して密結合を緩める」という動きについてです。 、コードのすべてのレベルで。私はZend Conの出身ですが、このスタイルのコードは、コンベンションの中心となる要素の1つとなっています。ビューからロジック、モデルからビュー、データベースからモデルを切り離し、可能であればデータベースからデータを切り離します。依存性-すべてを注入します。これは、nothingを実行する配線コード(関数、クラス、ボイラープレート)を追加するだけで、シーム/フックポイントとして機能し、ほとんどの場合、コードサイズを簡単に2倍にすることを意味します。

更新2:「コードをより多くのファイルに分離する」ことはパフォーマンスに大きな影響を及ぼしますか(コンピューティングのすべてのレベルで)

_compartmentalize your code into multiple files_の哲学は、今日のコンピューティング(パフォーマンス、ディスク使用率、メモリ管理、CPU処理タスク)にどのように影響しますか?

私は話している

前...

それほど遠くない過去の架空の仮説では、モデルとビューおよびコントローラーのスパゲッティまたは非スパゲッティコードが含まれているファイルの1つのモノブロックを簡単に書き込むことができますが、これはeverythingを1回実行しますすでにロードされています。過去にCコードを使用していくつかのベンチマークを行うと、単一の900Mbファイルをメモリにロードして大きなチャンクで処理する方が、小さなファイルの束をロードして小さなピースミールで処理するよりもはるかに高速であることがわかりました最後に同じ作業を行うチャンク。

..そして今*

今日私は、元帳を表示するコードを見ていて、それが..アイテムが「注文」の場合、注文のHTMLブロックを表示するなどの機能を備えています。広告申込情報をコピーできる場合は、アイコンとその背後にあるHTMLパラメータを表示するHTMLブロックを印刷して、コピーを作成できるようにします。アイテムを上下に移動できる場合は、適切なHTML矢印を表示します。等私は、Zend Frameworkを介してpartial()呼び出しを作成できます。これは、本質的には「パラメーターを取り、それも呼び出す別のHTMLファイルにそれらを挿入する関数を呼び出す」ことを意味します。取得したい詳細に応じて、元帳の最も小さな部分に個別のHTML関数を作成できます。上向き矢印、下向き矢印、「このアイテムをコピーできます」などの1つ。Webページの小さな部分を表示するためだけに複数のファイルを簡単に作成できます。私のコードと舞台裏のZend Frameworkコードを使用すると、システム/スタックはおそらく20から30近くの異なるファイルを呼び出します。

何?

私はアスペクトに興味があります。コードは多くの小さな個別のファイルに区分化することによって作成されたマシンでwear and tearです。

たとえば、より多くのファイルをロードすることは、ファイルシステムのさまざまな場所、および物理HDDのさまざまな場所にそれらを配置することを意味します。つまり、より多くのHDDシークおよび読み取り時間を意味します。

CPUの場合は、コンテキストの切り替えとさまざまなレジスタのロードが増えることを意味します。

このサブブロック(更新#2)では、複数のファイルを使用して、単一のファイルで実行できる同じタスクをシステムのパフォーマンスにどのように影響させるかについて、より厳密に興味を持っています。

Zend Form APIと単純なHTMLの使用

Zend Form APIを最新かつ最新のOOプラクティスと共に使用して、検証付きのHTMLフォームを構築し、POSTをドメインオブジェクトに変換しました。

作成に35ファイルが必要でした。

_35 files = 
    = 10 fieldsets x {programmatic fieldset + fieldset manager + view template} 
    + a few supporting files
_

これらはすべて、いくつかの単純なHTML + PHP + JS + CSSファイル、おそらく合計4つの軽量ファイルで置き換えることができます。

いいですか?それは価値がありますか? ... 35個のファイルと、それらを機能させる多数のZend Zrameworkライブラリファイルをロードすることを想像してください。

37
Dennis

私の質問はこれです:呼び出しがマシンコード、1と0、アセンブリ命令に到達したとき、さまざまな小さな関数から小さな関数までのクラスで区切られたコードが余分なオーバーヘッドを生成することを心配する必要がありますか?

私の答えは「はい」です。小さな関数がたくさんあるからではありません(一度に関数を呼び出すオーバーヘッドがかなり重要であり、ループで100万回の小さな呼び出しを行うことによってプログラムの速度が低下する可能性がありましたが、今日のコンパイラーはそれらをインライン化し、残っているものを取得しますCPUファンシー予測アルゴリズムによって処理されるため、心配する必要はありません)。ただし、機能が小さすぎて頭を使いこなせない場合は、プログラムにレイヤー化しすぎるという概念を導入します。より大きなコンポーネントがある場合、それらが同じ作業を繰り返し実行していないことは合理的に確認できますが、プログラムを非常に細かくして、呼び出しパスを実際に理解できず、結果的に何かが発生する可能性がありますそれはほとんど機能しません(そしてほとんど維持できません)。

たとえば、1つの方法でWebサービスの参照プロジェクトが表示される場所で働いていました。プロジェクトは32個の.csファイルで構成されました-単一のWebサービス用です!これは複雑すぎると思いましたが、各部分は小さくて簡単に理解できましたが、システム全体を説明するとなると、すぐに、何が起こっているのかを確認するために、呼び出しをたどる必要がありました。予想通り、あまりにも多くの抽象化が含まれていました)。私の代わりのWebサービスは4つの.csファイルでした。

全体的にほぼ同じだろうと思ったので、パフォーマンスは測定しませんでしたが、維持するのに大幅に安くなったことを保証できます。誰もがCPU時間よりもプログラマー時間の方が重要だと語る場合、開発と保守の両方でプログラマー時間が多くかかる複雑なモンスターを作成すると、彼らは悪い振る舞いの言い訳をしているのではないかと考えざるを得ません。

全コードの最大70%がASMのMOV命令で構成されていると(TBDを引用して)どこかで言われました-実際の計算ではなく、適切な変数でCPUレジスタをロードします。

つまりis CPUは何をするか、ビットをメモリからレジスタに移動し、それらを加算または減算してから、メモリに戻します。すべてのコンピューティングは、結局のところそれで終わりです。ちなみに、私はかつてスレッドコードを処理するよりもほとんどの時間コンテキスト切り替え(つまり、スレッドのレジスタ状態の保存と復元)に費やす非常にマルチスレッドのプログラムを持っていました。間違った場所での単純なロックは、そこにパフォーマンスを本当にねじ込んでおり、それもそのような無害なコードのビットでした。

だから私のアドバイスは、コードを他の人間に見栄えよくする、どちらか極端なものの間の賢明な中間点を見つけ、システムがうまく機能するかどうかをテストすることです。 OSの機能を使用して、CPU、メモリ、ディスク、ネットワークIOで期待どおりに動作することを確認します。

11
gbjbaanb

細心の注意を払わずに、これらの懸念などのマイクロ最適化は、保守不可能なコードにつながります。

最初は良いアイデアのように見えますが、プロファイラーはコードがより高速であることを通知し、V&V/Test/QAはうまくいくとさえ言っています。すぐにバグが発見され、考慮されなかった要件の変更と拡張が求められます。

プロジェクトの存続期間を通じて、コードは劣化し、効率が低下します。保守可能なコードは、劣化が遅くなるため、保守不可能なコードよりも効率的になります。その理由は、コードが変更されるとコードがエントロピーを構築するためです-

保守不可能なコードは、より多くのデッドコード、冗長パス、および重複をすばやく持っています。これはバグの増加につながり、コードのパフォーマンスが低下するサイクルを引き起こします。やがて、開発者は自分が行っている変更が正しいことに自信が持てなくなります。これは彼らを遅くし、注意深くし、彼らが見ることができる細部だけを扱うので、一般的にさらにエントロピーにつながります

小さなモジュールと単体テストを備えた保守可能なコードは変更が容易であり、不要になったコードは識別および削除が容易です。壊れたコードは、特定が容易で、自信を持って修復または置換できます。

結局のところ、それはライフサイクル管理に帰着し、「これはより速いので常により速くなる」ほど単純ではありません。

とりわけ、遅い正しいコードは速い正しくないコードよりも無限に速いです。

26
mattnz

私の理解では、インラインで指摘しているように、C++のような低レベルのコードでは、違いが生じる可能性がありますが、私は軽く言うことができます。

ウェブサイトはそれを要約しています-簡単な答えはありません。それはシステムに依存し、アプリケーションが何をしているかに依存し、言語に依存し、コンパイラと最適化に依存します。

たとえば、C++はインラインでパフォーマンスを向上させることができます。多くの場合、それは何もしないか、パフォーマンスを低下させる可能性がありますが、私は個人的には話を聞いたことはありません。インラインはコンパイラに最適化するための提案に過ぎず、無視できます。

より高いレベルのプログラムを開発している場合、そもそもオーバーヘッドがあっても心配する必要はないでしょう。最近のコンパイラは非常に賢く、とにかくこのようなものを処理する必要があります。多くのプログラマーは、存続可能コードを持っています。コンパイラーを信頼しないでください。これが当てはまる場合は、重要だと思われるわずかな最適化でも可能です。ただし、すべての言語がこの点で異なります。 Javaは、実行時にインライン最適化を自動的に実行します。JavaScriptでは、(個別のファイルではなく)Webページのインライン化がブーストであり、Webページのミリ秒ごとにカウントされる可能性がありますが、それ以上のIO問題。

しかし、プログラマーがC++のようなものと一緒に多くのマシンコード作業を行っている可能性がある下位レベルのプログラムでは、耳に聞こえることですべての違いが生じる可能性があります。ゲームは、特にコンソール上でCPUパイプラインが重要である良い例であり、インラインのようなものは、あちこちに少し追加されます。

具体的には、インラインでよく読んでください: http://www.gotw.ca/gotw/033.htm

17
user99999991

これは、2500行にわたるメソッドがあり、大きなクラスがすべてを実行する「古い」または「悪い」コードプラクティスと比較した変更です。

私は、それをすることは良い習慣だと思ったことはないと思います。そして、パフォーマンス上の理由でそれをした人々はそれをしたのではないかと思います。

ドナルド・クヌースの有名な引用はここで非常に関連があると思います:

小さな効率については忘れてください。たとえば、97%の時間です。時期尚早な最適化は、すべての悪の根源です。

したがって、コードの97%で、適切な方法を使用して、小さなメソッドを記述します(どのように小さいかは問題です。すべてのメソッドが数行である必要はないと思います)など。残りの3%では、パフォーマンス問題ありません測定それ。また、多くの小さなメソッドを使用すると、実際にコードの速度が大幅に低下することが測定で示されている場合は、それらを組み合わせて大きなメソッドにする必要があります。しかし、mightの方が速いという理由だけで、保守不可能なコードを記述しないでください。

12
svick

経験豊富なプログラマや現在の考え方に耳を傾けるように注意する必要があります。長年に渡って大規模なソフトウェアを扱ってきた人々には、貢献する何かがあります。

私の経験では、ここが減速につながるものであり、小さくはありません。それらは桁違いです:

  • コードの行には、他の行とほぼ同じ時間がかかるという仮定。例えば ​​cout << endla = b + c。前者は後者より数千倍時間がかかります。 Stackexchangeには、「このコードを最適化するためのさまざまな方法を試しましたが、違いが見られないようですが、なぜ違いますか?」という形式の質問がたくさんあります。その中に大きな古い関数呼び出しがあるとき。

  • もちろん、関数やメソッドの呼び出しは、いったん記述されると、必要になります。関数とメソッドは簡単に呼び出すことができ、通常、呼び出しはかなり効率的です。問題は、クレジットカードのようなものです。彼らはあなたが本当にしたいよりも多くを使うように誘惑し、あなたが費やしたものを隠す傾向があります。その上、大規模なソフトウェアには抽象化のレイヤーが重ねられているため、各レイヤーに無駄が15%しかない場合でも、5レイヤーを超えると2のスローダウンファクターに複合化します。これに対する答えは、機能を削除したり書き込むことではありません。より大きな関数、それはあなたがこの問題を警戒するようにあなた自身を訓練することであり、そして それを根絶する意欲があり、そしてそれを根絶することができる

  • ギャロッピングの一般性。抽象化の価値は、少ないコードでより多くのことができるようになることです-少なくともそれが望みです。このアイデアは極端に押し上げることができます。一般性が高すぎる問題は、すべての問題が特定のものであり、一般的な抽象化を使用してそれを解決する場合、それらの抽象化が必ずしも問題の特定のプロパティを利用できるとは限らないことです。たとえば、長さが3を超えないときに、大きなサイズで効率的なファンシープライオリティキュークラスが使用される状況を見てきました。

  • ギャロッピングデータ構造。 OOPは非常に便利なパラダイムですが、データ構造を最小化することを奨励するものではありません。むしろ、データ構造の複雑さを隠そうとすることを奨励します。たとえば、「通知」という概念があります。 "データムAが何らかの方法で変更された場合、Aは通知イベントを発行して、アンサンブル全体の整合性を保つようにBとCも自分自身を変更できるようにします。これにより、多くのレイヤーに伝播し、変更のコストを大幅に拡大できます。次に、Aへの変更がすぐに元に戻されるか、別の変更に変更された可能性があります。つまり、アンサンブルの整合性をもう一度行う必要があります。交絡は、これらすべての通知ハンドラーのバグの可能性、循環などです。データ構造を正規化しておくことをお勧めします。これにより、変更を1つで行う必要があります。配置のみ。正規化されていないデータを回避できない場合は、定期的なパスを使用して矛盾をペアにするのではなく、短い鎖で一貫性を保つことができます。

...もっと考えたら追加します。

11
Mike Dunlavey

短い答えは「はい」です。そして、一般的に、コードは少し遅くなります。

しかし、適切なOO風のリファクタリングにより、コードを高速化する最適化が明らかになる場合があります。複雑なJavaアルゴリズムをオブジェクト指向の複雑なネストされた配列の代わりに適切なデータ構造、ゲッターなどを使用して、はるかにオブジェクト指向にした1つのプロジェクトで作業しました。しかし、より良い分離とデータ構造へのアクセスを制限することで、Doubleの巨大な配列(空の結果の場合はnull)から、NaNの空の結果のより組織化されたdoubleの配列に変更できました。これにより、速度が10倍向上しました。

補遺:一般に、より小さく、より構造化されたコードは、マルチスレッディングに対応しやすく、大幅なスピードアップを実現するための最良の方法です。

8
user949300

特に、プログラミングはトレードオフに関するものです。この事実に基づいて、私は「はい」と答える傾向があります。遅くなる可能性があります。しかし、見返りに何が得られるかを考えてください。可読性、再利用性、容易に変更可能なコードを入手することは、起こり得るあらゆる欠点を簡単に上回ります。

@ user949300 言及 のように、このようなアプローチでアルゴリズム的またはアーキテクチャ的に改善できる領域を見つけるのは簡単です。それらを改善することは通常、可能性OOまたは関数呼び出しオーバーヘッド(これはすでに単なるノイズです)がないことよりもはるかに有益で効果的です) )。


また、実際にハードウェアで実行する前に、ASMに対して適切な最適化を行うことができると思います。

このような何かが私の心を横切るときはいつでも、コンパイラに取り組んでいる賢い人々が費やした何十年も、おそらくマシンコードを生成する上で、GCCのようなツールをはるかに優れていると思います。マイクロコントローラーに関連する何らかの作業をしているのでない限り、心配する必要はありません。

コードに関数やオブジェクト、クラスを追加することで、小さなコード間で渡されるパラメーターが増えると想定しています。

最適化するときに何かが時間の浪費であると仮定すると、コードのパフォーマンスに関する事実が必要になります。ほとんどの時間を専門のツールで費やしている場所を見つけ、それを最適化し、繰り返します。


まとめると、コンパイラーにその仕事を任せて、アルゴリズムやデータ構造の改善などの重要なことに集中してください。あなたがあなたの質問で述べたすべてのパターンはそれを助けるために存在します、それらを使用してください。

PS:これらの2つのクロックフォードの話は私の頭に浮かびました、そして私はそれらが幾分関連していると思います。最初の1つは、CSの非常に短い履歴です(これは、正確な科学で常に知っておくとよいでしょう)。 2つ目は、良いことを拒否する理由です。

7

あなたが特定した傾向は、ソフトウェア開発についての真実を示していると思います。プログラマーの時間は、CPU時間よりも高価です。これまでのところ、コンピュータはより速く、より安くなっているだけですが、複雑なアプリケーションの混乱は、変更に数千時間とまではいかなくても数百時間かかる場合があります。給与、福利厚生、オフィススペースなどのコストを考えると、実行速度は少し遅いかもしれませんが、変更の方が早く安全です。

4
Rory Hunter

ええと、20年以上前、私はあなたが新しいものではなく、「古いものでも悪いもの」でもないことを推測していますが、ルールは、印刷されたページに収まるように関数を十分に小さく保つことでした。私たちはドットマトリックスプリンターを持っていたので、行数はいくぶん固定されていました。一般に、ページあたりの行数は1つまたは2つしか選択できませんでした。間違いなく2500行未満でした。

あなたは問題の多くの側面、保守性、パフォーマンス、テスト容易性、読みやすさを求めています。パフォーマンスに傾くほど、コードの保守性と可読性は低下します。そのため、個々のプログラマーごとに異なる可能性のある快適レベルを見つける必要があります。

コンパイラーによって生成されたコード(可能であればマシンコード)に関する限り、関数が大きくなるほど、レジスターの中間値をスタックにスピルする必要性が高まります。スタックフレームが使用される場合、スタックの消費はより大きなチャンクで行われます。関数が小さいほど、データがレジスタに留まる機会が増え、スタックへの依存が少なくなります。当然、関数ごとに必要なスタックの小さなチャンク。スタックフレームには、パフォーマンスに関する長所と短所があります。関数が小さいほど、関数のセットアップとクリーンアップが多くなります。もちろん、それはコンパイルの仕方、コンパイラーに与える機会にも依存します。 2500行の関数1つではなく、10行の関数が250個ある場合があります。コンパイラーが取得する2500行の関数は、全体で最適化できるかどうかを選択します。しかし、これらの250の10行関数を使用して、2、3、4、250の個別のファイルに分散し、各ファイルを個別にコンパイルすると、コンパイラーは、可能な限り多くのデッドコードを最適化できなくなります。ここでの一番下の行は、両方の長所と短所があり、これに一般的なルールを置くことは不可能であるか、それが最善の方法です。

合理的なサイズの関数は、人が画面またはページ(合理的なフォント)で見ることができるものであり、非常に大きなコードよりもよく理解できるものです。しかし、それが他の多くの小さな関数を呼び出す他の多くの小さな関数への呼び出しを持つ小さな関数である場合、そのコードを理解するためにいくつかのウィンドウまたはブラウザが必要になるため、読みやすさの面で何も購入しませんでした。

uNIXの方法は、私の用語である、洗練されたレゴブロックを使用することです。テープの使用を停止してから何年もして、なぜテープ機能を使用するのでしょうか。 blobは非常にうまく機能し、裏側ではテープインターフェイスをファイルインターフェイスに置き換えて、プログラムの本質を利用できます。なぜscsiがideに置き換えられた主要なインターフェイス(後で戻ってくる)として廃止されたからといって、cdrom書き込みソフトウェアを書き直すのか。ここでも、洗練されたサブブロックを活用して、一端を新しいインターフェイスブロックに置き換えます(ハードウェア設計者がハードウェアデザインにインターフェイスブロックを追加しただけで、場合によっては、SCSIドライブにSCSIインターフェイスのアイデアを持たせることも理解してください。これを短縮するには、適切なサイズの洗練されたレゴブロックを構築し、それぞれに明確な目的と明確な入力と出力を設定します。これらのレゴブロックにテストをラップし、同じブロックを取得して、同じブロックとブロックにユーザーインターフェイスとオペレーティングシステムインターフェイスをラップできます。理論的には、十分にテストされ、十分に理解されている場合、デバッグする必要はありません。両端に新しいブロックを追加するだけです。すべてのブロックインターフェイスが適切に設計され、機能が十分に理解されている限り、最小限の条件で非常に多くの物を構築できます。既知のサイズと形状の青、赤、黒、黄色のレゴブロックと同じように、さまざまな接着剤を使用できます。

個人はそれぞれ異なり、洗練され、明確に定義され、テストされ、読みやすいものの定義は異なります。たとえば、教授がプログラミングルールを口述するのは不合理ではありません。なぜなら、それらはプロとしてのあなたにとって悪いかもしれないし、そうでないかもしれないからではありませんが、場合によっては、教授や大学院生のアシスタントであなたのコードを読み、グレーディングする作業を容易にすること...あなたも同様に、専門的には、各仕事にさまざまな理由で異なるルールがある可能性があることを見つける可能性があります。通常、権力を持つ1人または数人の人々が何かについて、正しいか間違っているかについて意見を持っています。それはそこにあります(または、やめる、解雇される、またはどういうわけか権力を握る)。これらのルールは、読みやすさ、パフォーマンス、テスト容易性、移植性に関する何らかの事実に基づいているのと同じくらい、意見に基づいています。

4
old_timer

コンパイラーのスマート度に依存します。一般に、オプティマイザを裏切ることは悪い考えであり、コンパイラから最適化の機会を奪う可能性があります。手始めに、あなたはおそらくあなたがそれが何をすることができるかについて何の手がかりも持っておらず、あなたがするほとんどのことは実際にそれがどれほどうまくいくかに影響を与えます。

時期尚早な最適化とは、プログラマーがそれを行おうとしていて、実際には彼らがやろうとしていたことのクリティカルパス上になかった、保守が難しいコードになるという概念です。ほとんどの場合、アプリが実際にブロックされているときに、できるだけ多くのCPUを絞り出そうとすると、IOイベントを待って待機します。たとえば、私がよく目にするものです。

最善の方法は、正確性をコード化し、プロファイラーを使用して実際のパフォーマンスのボトルネックを見つけ、クリティカルパス上の問題点を分析し、改善できるかどうかを分析することです。多くの場合、いくつかの単純な修正は大きな意味を持ちます。

2
Jilles van Gurp

[computer-time element]

緩い結合と小さな関数へのリファクタリングはコードの速度に影響しますか?

はい、そうです。しかし、この「シーム/配線」コードを取り除くのはインタープリター、コンパイラー、およびJITコンパイラー次第であり、他のコードより優れているものもそうでないものもあります。

複数ファイルの問題によりI/Oオーバーヘッドが増加するため、速度もかなり(コンピューター時間で)影響を受けます。

[human-speed element]

(そして私は気にする必要がありますか?)

いいえ、気にする必要はありません。最近のコンピューターと回路はかなり高速であり、ネットワーク遅延、データベースI/O、キャッシングなど、他の要因が引き継ぎます。

そのため、ネイティブコードの実行自体の2倍から4倍の速度低下は、他の要因によっておおわれてしまうことがよくあります。

複数ファイルの読み込みに関しては、多くの場合、さまざまなキャッシュソリューションによって処理されます。物事をロードして最初にマージするのにより時間がかかる場合がありますが、静的ファイルの場合、次回以降はキャッシュは単一のファイルがロードされているかのように機能します。キャッシングは、複数ファイルのロードに対するソリューションとして提供されます。

0
Dennis

解答(見逃した場合)

はい、気にする必要がありますが、パフォーマンスではなく、コードの記述方法に注意してください。

要するに

パフォーマンスは気にしないでください

質問の文脈では、よりスマートなコンパイラとインタプリタがすでにそれを処理しています

保守可能なコードの記述に注意してください

保守費用が合理的な人間の理解のレベルにあるコード。つまり、それぞれを理解してもコードを理解不能にする1000個の小さな関数を記述しないでください。また、大きすぎて理解できない1つの神オブジェクト関数を記述しないでください。メンテナンスが簡単。

0
Dennis