10


3

大規模プロジェクトでのCヘッダポリシー(redux)

私はこのトピックについて見つけることができるすべてを読みました。このサイトに関する2、3の非常に役に立つ議論、NASAコーディングガイドラインとグーグルCガイドラインを含みます。 私はここで推薦された「物理的なCデザイン」本を買った(すみません、名前を忘れて)そしてそれからいくつかの役に立つ考えを得た。 ほとんどの情報源は同意しているようです - ヘッダファイルは自己完結型であるべきです。 cppファイルに他のものを含めずにヘッダーを含めることができ、コンパイルできるように、必要なものが含まれています。 また、可能な限り含めるのではなく、前方宣言をすることも重要です。

そうは言っても、 foo.cpp`が bar.h`と qux.h`を含んでいるとしたらどうでしょうか。しかし、 bar.h`自体が qux.h`を含んでいることがわかりますか? `foo.cpp`は qux.h`をインクルードするのを避けるべきですか? Pro: foo.cpp`をクリーンアップします(「ノイズ」が少ない) Con:誰かがbar.hを `qux.h`をインクルードしないように変更した場合、 foo.cpp`は不思議なことにコンパイルに失敗し始めます。 また、 foo.cpp`と qux.h`の間の依存関係がはっきりしないようにします。

あなたの答えが「cppファイルはそれが必要とするすべてのヘッダを#includeするべきである」であるならば、その論理的結論に連れて行かれ、それはほとんどすべてのcppファイルが `#include 'をしなければならないことを意味する ほとんどのコードはそれらを使用することになるので、それらを含む他のヘッダに頼ることになっていないのであれば、あなたのcppはそれらを明示的に含める必要があります。 それはcppファイルにたくさんの「ノイズ」があるようです。

考えですか?

これまでの議論

https://stackoverflow.com/questions/51561/how-do-i-automate-finding-unused-include-directives [未使用の#includeディレクティブを自動的に見つける方法を教えてください。]

ETA:ここでのこれまでの議論に触発されて、私はPerlスクリプトを書いてそれぞれの 'include’と 'using’を連続してコメントアウトし、それからソースファイルを再コンパイルして不要なものを見つけ出します。 また、VS 2005と統合する方法を考え出したので、ダブルクリックして「未使用」のインクルードに移動できます。 誰かがそれを欲しがったら私に知らせてください。

7 Answer


8


_ あなたの答えが "cppファイルは必要なすべてのヘッダーを`#include`するべきである "という場合、ほとんどすべてのcppファイルが` #include、 `などを持たなければならないという論理的な結論になります。 ほとんどのコードはそれらを使用することになるので、それらを含む他のヘッダに頼ることになっていないのであれば、あなたのcppはそれらを明示的に含める必要があります。 _

Yup. それが私が好む方法です。

「ノイズ」が大きすぎる場合は、通常の一般的なインクルード(多くのWindowsプログラムでは「stdafx.h」など)を含む「グローバル」インクルードファイルを作成し、各 `.cpp`ファイルの先頭(これはプリコンパイル済みヘッダーにも役立ちます)。


2


私はあなたがまだ両方のファイルを含めるべきだと思います。 これはコードの維持に役立ちます。

// Foo.cpp

#include
#include

私はそれを読み、それがどのライブラリを使っているかを簡単に見ることができます。 Library2`が Library1`を使っていて、それが次のように変形されたとします。

// Foo.cpp

#include

しかし、私はまだ `Library1`コードを見ました、私は少し混乱するかもしれません。 他のライブラリがそれを含める必要があることを推測するのは難しくありませんが、それはまだ発生しなければならない思考プロセスです。

明示的であるということは、たとえ余分な数秒のコンパイルであっても、私が推測する必要がないことを意味します。


2


耐えられなくなるまで両方を含めるべきだと思います。 次に、すべての依存関係を一覧表示するだけでは面倒であるという理由で、結合を減らすためにクラスとソースファイルをリファクタリングします。

妥協点は、 bar.h`の中に何かが qux.h`から別のクラス定義を必然的に必要とするクラス定義(または関数宣言)を含んでいるならば、 bar.h`はインクルードすることを仮定/要求することができる`qux.h`と bar.h`の中のAPIのユーザは両方を含めるのを気にする必要はありません。

したがって、クライアントが自分自身を「本当に」bar APIのみに関心があると見なしたいが、quxも使用する必要があるとします。これは、値によってquxオブジェクトを受け取るまたは返すbar関数を呼び出すためです。 それから、quxがそれ自身のヘッダを持っていることを忘れることができ、それが `bar.h`で定義された一つの大きなバーAPIであり、quxはそのAPIの一部にすぎないと想像できます。

これは、例えば、qux.hの記述をcppファイルから検索して、quxのすべてのクライアントを見つけることができないことを意味します。 一般的に、既に間接的に含まれている依存関係を明示的に含めることを誤って見逃すことはあまりにも簡単であり、関連するすべてのヘッダーが一覧表示されていないことに決して気付かないためです。 ですから、いかなる場合でもヘッダーリストが完全であると想定するべきではありませんが、代わりにdoxygen(またはgcc -M、またはその他)を使用して依存関係の完全なリストを取得し、それを検索してください。


1


_ foo.cppにbar.hとqux.hが含まれているが、bar.h自体にqux.hが含まれている場合はどうでしょうか。 foo.cppはqux.hをインクルードするのを避けるべきですか? _

もし foo.cpp`が qux.h`から直接何かを使うのであれば、それはこのヘッダ自身を含むべきです。 そうでなければ、 bar.h`は qux.h`を必要とするので、私はそれが必要とするすべてを含めて `bar.h`に頼るでしょう。


0


各ヘッダファイルには、ある種のサービスを使用するために必要な定義(クラス定義、マクロなど)があります。 ヘッダーファイルを介して公開されているサービスを直接使用している場合は、別のヘッダーファイルにも含まれている場合でも、そのヘッダーファイルを含めてください。 一方、これらのサービスを他のヘッダーファイルのサービスのコンテキスト内でのみ間接的にのみ使用している場合は、ヘッダーファイルを直接含めないでください。

私の意見では、これはどちらにしても大した問題ではありません。 ヘッダーファイルの2番目のインクルードは完全には解析されません。基本的にはコメントアウトされていますが、初めて含まれる場合はコメントアウトされています。 状況が変わり、直接インクルードしていないヘッダーファイルを使用していることがわかったので、それを追加することは大したことではありません。


0


foo.cppがqux.hを直接使用しているかどうかを考える1つの方法は、foo.cppがbar.hをインクルードする必要がなくなった場合にどうなるかを考えることです。 それでもfoo.cppにqux.hをインクルードする必要がある場合は、明示的にリストする必要があります。 それがqux.hから何かをもはや必要としなくなるなら、おそらくそれを明示的にインクルードする必要はないでしょう。


0


ここでは「プロファイリングなしで最適化しない」という規則が適用されます。

(この答えは「クラッタ」よりも「パフォーマンス」に偏っています。一般的に、クラッタは後で自由になることが困難ですが、パフォーマンスは定期的にあなたに影響を与えます。)

両方の方法を試してみて、コンパイラの速度が大幅に向上するかどうかを確認してから、「重複」ヘッダを削除することを検討してください。

http://technet.microsoft.com/en-us/sysinternals/bb896642.aspx[Sysinternals FileMon]のようなものを入手して、これらの複製インクルードに対して実際にファイルシステムヒットを生成しているかどうかを確認することを検討してください(ほとんどのコンパイラはそうではありません正しいヘッダーガード付き)

ここでの経験は、未使用の(または適切な前方宣言がある可能性がある)ヘッダーを積極的に探し出して削除することが、重複の可能性があるインクルードチェーンを考え出すよりもはるかに時間と労力がかかることを示しています。 そして良い糸くず(splint、 PC-Lintなど)がこの決心を手助けしてくれるでしょう。

1回の実行で複数のコンパイル単位を処理するようにコンパイラーに処理させる方法を考え出すことは、私たちの時間と労力にもっと価値がありました(ある程度の線形スピードアップ - ある程度まではコンパイルはコンパイラーの始動によって支配されていました)。

その後は、「シングルビッグCPP」の狂気を検討することをお勧めします。 とても印象的です。