質問
コードの全体的な品質を向上させるためにどのようなガイドラインに従っていますか?多くの人は、間違いを犯しにくくする (おそらく) C++ コードの書き方に関するルールを持っています。人を見たことがある 主張する すべての if
ステートメントの後には中括弧ブロック ({...}
).
他の人がどのようなガイドラインに従っているのか、そしてその背後にある理由に興味があります。また、くだらないと思われているが一般的に受け入れられているガイドラインにも興味があります。誰かいくつか提案してもらえますか?
話を進めるために、まずいくつか挙げておきます。
- 毎回の後には必ず中括弧を使用してください
if
/else
という声明(前述)。この背後にある理論的根拠は、単一のステートメントが実際に 1 つのステートメントなのか、それとも複数のステートメントに展開されるプリプロセッサ マクロなのかを判断するのは必ずしも簡単ではないため、このコードは壊れるということです。
// top of file: #define statement doSomething(); doSomethingElse // in implementation: if (somecondition) doSomething();
ただし、中括弧を使用すると、期待どおりに機能します。
- プリプロセッサ マクロは条件付きコンパイルにのみ使用してください。プリプロセッサ マクロは C++ のスコープ ルールを許可しないため、あらゆる種類の地獄を引き起こす可能性があります。ヘッダー ファイルに共通の名前を持つプリプロセッサ マクロが原因で、何度も座礁してしまいました。注意しないと、あらゆる種類の大混乱を引き起こす可能性があります。
さあ、あなたに。
解決
私の個人的なお気に入りをいくつか紹介します。
というコードを書くように努めてください。 定数が正しい. 。コンパイラに協力して、修正は簡単だが、場合によっては厄介なバグを除去してもらいます。コードには、コードを書いたときに考えていたことのストーリーも含まれます。これは、新人や、辞めた後のメンテナにとって貴重なものです。
メモリ管理ビジネスから撤退します。スマート ポインターの使用方法を学びます。 std::auto_ptr
, std::tr1::shared_ptr
(または boost::shared_ptr
) そして boost::scoped_ptr
. 。それらの違いと、どちらを使用するか、いつ使用するかを学びます。別の。
おそらく、標準テンプレート ライブラリを使用することになるでしょう。読む ジョスティスの本. 。コンテナに関する最初の数章を読んだだけで、STL を知っていると思ってやめないでください。良いものを押し進めます。アルゴリズムと関数オブジェクト。
他のヒント
- 不要なコードを削除してください。
以上です。
- 共通のコーディング スタイルとガイドラインを使用し、適用します。 理論的根拠: チームまたは社内のすべての開発者は、中括弧のスタイルなどの違いによって気を散らされることなく、コードを読むことができます。
- ソースベース全体の完全な再構築を定期的に実行します(つまり、毎日のビルド、または各チェックイン後にビルドを実行し、エラーがあれば報告してください。 理論的根拠: ソースはほとんどの場合使用可能な状態にあり、問題は「実装」された直後に検出され、問題解決にかかる費用は安くなります。
コンパイラー (gcc: -Wall
これは良いスタートですが、すべてが含まれているわけではないのでドキュメントを確認してください)、エラーになるため修正する必要があります (gcc: -Werror
).
これらの回答の 1 つで言及されている Google のスタイルガイドは、かなりしっかりしています。意味のない内容も含まれていますが、悪いというより良いです。
サッターとアレクサンドレスクは、このテーマについてまともな本を書きました。 C++ コーディング標準.
以下は、私からの一般的なヒントです。
インデントと括弧のスタイルが両方とも間違っています。他の皆さんもそうです。したがって、これについてはプロジェクトの標準に従ってください。プライドを捨てて、コードベースの残りの部分と可能な限りすべてが一致するようにエディタをセットアップしてください。インデントが一貫していないコードを読まなければならないのは本当に面倒です。とはいえ、ブラケットとインデントは、「コードの改善」とは何の関係もありません。それは、他の人と仕事をする能力を向上させることです。
よくコメントしてね。これは非常に主観的なものですが、一般的に、次のようなコメントを書くのは常に良いことです。 なぜ コードが何をするのかを説明するのではなく、コードがそのように動作するということです。もちろん、複雑なコードの場合は、アルゴリズムやコードに詳しくないプログラマーにとっても、アイデアを得るのに役立ちます。 何 それもやってます。使用されているアルゴリズムの説明へのリンクは大歓迎です。
ロジックをできるだけ簡単に表現します。皮肉なことに、「比較の左側に定数を置く」といった提案は、ここでは間違っていると思います。これらは非常に人気がありますが、英語話者にとっては、読んでいる人にとってプログラムの論理的な流れが壊れてしまうことがよくあります。自分 (またはコンパイラ) が等価比較を正しく記述できるかどうかを信頼できない場合は、ぜひこのようなトリックを使用してください。しかし、それを行うと、明瞭さが犠牲になります。このカテゴリには、次のようなものも含まれます。「私のロジックには 3 レベルのインデントがありますか?もっと簡単にできないだろうか?」と同様のコードを関数にローリングします。機能を分割することもあるかもしれません。基礎となるロジックをエレガントに表現するコードを書くには経験が必要ですが、取り組む価値はあります。
それらはかなり一般的なものでした。具体的なヒントに関しては、Sutter 氏と Alexandrescu 氏よりも優れた仕事をすることはできません。
if ステートメントでは、定数を左側に置きます。つまり、
if( 12 == var )
ない
if( var == 12 )
「=」を入力し忘れると代入になってしまうためです。最上位バージョンでは、コンパイラはこれは不可能であると判断しますが、後者では実行され、if は常に true になります。
if が同じ行にない場合は、中括弧を使用します。
if( a == b ) something();
if( b == d )
{
bigLongStringOfStuffThatWontFitOnASingleLineNeatly();
}
開き中括弧と閉じ中括弧は常に独自の行を取得します。しかし、それはもちろん個人的な慣習です。
コードが何を行っているかを説明する必要がある場合のみ、コードを読んでも同じことが分からない場合にのみコメントしてください。
もう使用していないコードをコメントアウトしないでください。古いコードを回復したい場合は、ソース管理システムを使用してください。コードをコメントアウトすると、見た目が乱雑になるだけで、実際には重要なコメントが、コメント化されたコードの背景の混乱の中に溶け込んでしまいます。
- 一貫した書式設定を使用します。
- レガシー コードを扱う場合は、既存の形式のフォーマットを採用します。ブレーススタイル。
- Scott Meyer の著書『Effective C++』を入手してください
- Steve MConnell の著書『Code Complete』を入手してください。
素敵なもあります C++ スタイルガイド Google が内部で使用するもので、ここで説明するルールのほとんどが含まれます。
たくさんのコメントを書き始めます。ただし、それを機会としてコードをリファクタリングして、内容が一目瞭然になるようにしてください。
つまり:
for(int i=0; i<=arr.length; i++) {
arr[i].conf() //confirm that every username doesn't contain invalid characters
}
もっと似たものであるべきだった
for(int i=0; i<=activeusers.length; i++) {
activeusers[i].UsernameStripInvalidChars()
}
インデントにはタブを使用しますが、データをスペースに合わせます。これは、タブのサイズを変更することでインデントの量を決定できることを意味しますが、物事は整合したままであることを意味します(たとえば、すべての '='が垂直線にある場合に、値を割り当てるときに垂直線に必要な場合があります。 struct)
可能な場合はマクロの代わりに常に定数またはインライン関数を使用してください。
ヘッダー ファイルでは 'using' を決して使用しないでください。ヘッダーを含めるユーザーが (たとえば) std のすべてをグローバル名前空間に含めたくない場合でも、そのヘッダーを含むすべてのものが影響を受けるためです。
何かが約 80 列を超える場合は、複数の行に分割します。
if(SomeVeryLongVaribleName != LongFunction(AnotherVarible, AString) && BigVaribleIsValid(SomeVeryLongVaribleName)) { DoSomething(); }
ユーザーが期待することを実行する演算子のみをオーバーロードしてください。たとえば、2dVector の + 演算子と - 演算子をオーバーロードするのは問題ありません。
次のブロックが何を行っているかを示すだけの場合でも、必ずコードにコメントを付けてください (例: 「このレベルに必要のないテクスチャをすべて削除する」)。誰かが後で、おそらくあなたが去った後、その作業をする必要があるかもしれませんが、その人は、何が何をしているのかを示すコメントのない何千行ものコードを見つけたくありません。
- コーディング規約を設定し、関係者全員がその規約に従うようにします(適切にインデントされていないため、次のステートメント/式がどこにあるのかを理解する必要があるコードを読みたくありません)。
- コードを常にリファクタリングする (Martin Fowler 著の『リファクタリング』のコピーを入手してください。メリットとデメリットについてはこの本で詳しく説明されています)
- 疎結合コードを作成します (一目瞭然のコードを作成してコメントを作成することは避けてください。疎結合コードは管理/変更への適応が容易になる傾向があります)
- 可能であれば、コードの単体テストを行ってください (十分にマッチョな場合は TDD を試してください)。
- 早くリリース、頻繁にリリース
- 時期尚早な最適化を避ける (プロファイリングは最適化に役立ちます)
同様に、ここでも役立つ提案がいくつか見つかるかもしれません。 間違ったコードを間違ったように見せるにはどうすればよいでしょうか?セマンティックエラーを避けるためにどのようなパターンを使用しますか?
可能な場合は、事後インクリメントではなく事前インクリメントを使用してください。
私は C++ プロジェクトで PC-Lint を使用していますが、MISRA ガイドラインや Scott Meyers の「Effective C++」および「More Effects C++」などの既存の出版物を参照している方法が特に気に入っています。静的分析ツールがチェックする各ルールについて非常に詳細な根拠を記述することを計画している場合でも、ユーザーが信頼している確立された出版物を参照することをお勧めします。
これは、C++ の達人から私に与えられた最も重要なアドバイスであり、コード内のバグを見つけるいくつかの重要な場面で役立ちました。
- メソッドが以下の場合は const メソッドを使用します。 想定されていない オブジェクトを変更します。
- オブジェクトが次の場合は、パラメータで const 参照とポインタを使用します。 想定されていない オブジェクトを変更します。
これら 2 つのルールにより、コンパイラはコード内のロジックのどこに欠陥があるかを無料で教えてくれます。
また、いくつかの優れたテクニックについては、以下を参考にしてください。 Googleのブログ「トイレでのテスト」.
半年後見てください
インデントが適切であることを確認してください
うーん、もう少し具体的にするべきだったかもしれません。
私は自分自身へのアドバイスを求めているわけではありません。私は静的コード分析ツールを作成しており (現在の商用製品は私が望むものには十分ではありません)、可能性を強調するためのプラグインのアイデアを探しています。コード内のエラー。
const の正確性やスマート ポインタの使用などについて言及している人もいます。私がチェックできるのはそのような考えです。インデントのチェックとコメントの実行は、(とにかくプログラミングの観点からすると) 少し難しくなります。
スマート ポインターには、所有権を非常に明確に示す優れた方法があります。クラスまたは関数の場合:
- を取得したら 生のポインタ, 、あなたは何も所有していません。呼び出し元の好意で、あなたは、その指示先があなたよりも長く生き続けることを保証してくれるので、その指示先を使用することが許可されています。
- を取得したら 弱い_ptr, 、あなたは指示先の所有者ではなく、その上、指示先はいつでも消える可能性があります。
- を取得したら 共有_ptr, 、あなたは他の人と一緒にオブジェクトを所有しているので、心配する必要はありません。ストレスは軽減されますが、コントロールも低下します。
- を取得したら auto_ptr, 、あなたはオブジェクトの唯一の所有者です。それはあなたのものです、あなたは王様です。あなたはそのオブジェクトを破壊するか、他の人に与える(それによって所有権を失う)権限を持っています。
auto_ptr のケースが特に強いと思います。設計で auto_ptr が表示されると、そのオブジェクトがシステムのある部分から別の部分に「さまよう」ことになることがすぐにわかります。
これは、少なくとも私が大好きなプロジェクトで使用しているロジックです。このトピックにどれだけのバリエーションがあるかわかりませんが、これまでのところ、このルールセットは私にとって役に立ちました。