コードを見ると、どのものがすぐに警報を鳴らしますか?[閉まっている]


98

数週間前にソフトウェア職人のイベントに参加しましたが、コメントの1つは「見たときに悪いコードをすべて認識していると確信している」というもので、誰も議論することなく賢くうなずきました。

この種のことは、誰もが自分が平均以上のドライバーだと思っているという真実があるので、常に私を心配しています。悪いコードは認識できると思いますが、他の人がコードの匂いだと考えるものについては、人々のブログやほんの一握りの本で詳細に議論されることはめったにないので、もっと学びたいと思います。特に、ある言語ではコード臭があり、別の言語では臭いがないものについて聞くのは面白いと思います。

簡単なものから始めます。

コメントアウトされたコードの割合が高いソース管理のコード -なぜそこにあるのですか?削除するつもりでしたか?それは半分完成した作品ですか?多分それはコメントアウトされるべきではなく、誰かが何かをテストしているときにのみ行われたのでしょうか?個人的には、この種のことは、それがあちこちの奇妙な行であっても本当に迷惑だと感じますが、コードの残りの部分に大きなブロックが散在しているのを見ると、まったく受け入れられません。また、通常、残りのコードも疑わしい品質である可能性が高いことを示しています。


61
コードをコメントアウトし、チェックインし、「将来、再び必要になる可能性があります。今すぐ削除すると、失われます」と言う人に出会うことがあります。「えー、しかし、それがソース管理の目的です」と反論する必要があります。
タロンクス

6
時々、特に最適化の際に、古いコードをコメントとして残しておくと便利な場合があります。そのため、あいまいな最適化コードが何を置き換えているのかがわかります。1行のビットスワップスワップに置き換えるときに、tempを3ラインスワップのままにしておくことを考えてください。(ただし、プログラムサイズが非常に重要でない限り、1行のスワップを使用する必要はありません。)
クリスカドモア

4
私はエンジニアの一人によって書かれたコードを保守/クリーンアップしています。彼はいくつかの有用なものをコーディングしましたが、彼はプログラマーではないと認めています。内容を統合する際に、彼の古いコードをコメントアウトし、その後、変更点を調べて、彼をより小さく/より効率的/理解しやすいものに置き換えた方法を示します。その後、それらのブロックを取り除いてからチェックインします。古いコードがあると、物事をより簡単に行う方法を理解し、話しているときに物事を変更した理由を覚えているので、利点があります。
ティンマン

8
「使用される可能性のある」ものを1つのコミットに残し、問題が解決しない場合や必要性が見つからない場合は、次のコミットで削除されます。
ポールネイサン

24
うーん。printf("%c", 7)通常、私のために警報ベルを鳴らします。;)

回答:


128
/* Fuck this error */

通常、ナンセンスtry..catchブロック内にあり、注意を引く傾向があります。同様に/* Not sure what this does, but removing it breaks the build */

さらにいくつかのこと:

  • 複数のネストされた複雑なifステートメント
  • 定期的にロジックフローを決定するために使用されるtry-catchブロック
  • 一般的な名前を持つ関数processdatachangereworkmodify
  • 100行の6つまたは7つの異なるブレーススタイル

私が見つけたもの:

/* Stupid database */
$conn = null;
while(!$conn) {
    $conn = mysql_connect("localhost", "root", "[pass removed]");
}
/* Finally! */
echo("Connected successfully.");

なぜなら、MySQL接続を総当たり攻撃するのは正しいやり方だからです。データベースの接続数に問題があるため、タイムアウトが続いていたことがわかりました。これをデバッグする代わりに、彼らはそれが機能するまで何度も何度も試みました。


19
これを6回賛成できればいいのに!すべての良い例。私はrog慢/面白いコメントも嫌いです(特にそれらに宣誓が含まれている場合)。
FinnNk

5
私はあなたの例が好きですが、特定の状況では、複数のネストされたifステートメントは避けられないと言います。多くのビジネスロジックでは、コードが少し混乱する可能性がありますが、ビジネス自体が最初から混乱する場合は、コードを簡素化するためにプロセスをあまり正確にモデリングしないことになります。アインシュタインが言ったように、「物事はできる限り単純で、少し単純ではないはずです。」
モーガンハーロッカー

2
@Prof Plum-どのような例を挙げられますか?通常、複数のネストされたifの代替は、(多くの)メソッドに分割することです。ジュニア開発者は、ifよりも望ましくないかのように、これを避ける傾向があります。しかし、通常、押されたとき、彼らは「より少ない行でそれをすれば」と言います。OOPに自信を持って誰かが介入して、コードが少ない!=より良いコードであることを思い出させます。
STW

2
@STWそれは良い点ですが、ネストの深さによって異なります。私は確かに、3ネスト以上の深さはリファクタリングを必要としていることに同意します。ただし、保険の見積もりは、マルチネストが実際に現実世界を非常にうまくモデル化できる良い例です。特定の料金/プレミアムの例外を除き、マニュアルでは、「これがプロパティであり、5.6未満の最低料金があり、NCであり、敷地内にボートがある場合、そのようにし、そのような。" 他の多くのオプション。
モーガンハーロッカー

4
@josh、「彼らは」同僚あるならば、私はあなたが「私たち」...言わなかった理由について熟考するだろう

104

私にとって大きな危険は、コードブロックが重複していることです。これは、その人がプログラミングの基礎を理解していないか、既存のコードベースに適切な変更を加えるのが怖すぎることを示しているためです。

以前はコメントの欠如を危険信号とみなしていましたが、最近はコメントを付けずに非常に優れたコードの多くを作成しました。


1
+1:同僚から、Linuxの専門家であると宣伝し、単純なループアプリケーションを1つの長い関数として、main()で何度も繰り返し書いているコードを見ました。うわぁ。
KFro

4
@KFro、それはループの展開です。それはコンパイラが常に何をするかです:)非常に効率的です!

3
@Thorbjorn:時には、コンパイラを少し助けなければならないことがあります。結局のところ、あなたは賢い人間であり、彼はただの愚かなコンピュータです。
yatima2975

3
私が見たもう一つの理由:コンサルタントは、できるだけ早く機能を実装するために支払われました(もちろん、テストとドキュメントも欠落している理由です)。コピー/貼り付けは、物事を正しく行う方法を考えるよりも高速です。
レニープログラマー

4
コードの重複を避けることは、強迫観念になります。C ++のような言語では、さまざまな部分を除外することは簡単であるとは限りませんが、堅牢で効率的なコードがあります。場合によっては、カットアンドペーストを少し行う方がより実用的なオプションです。また、最適化の原則は適用することができます-あなたが後でリファクタリングすることができ、迅速かつ簡単な解決策を得ることができますカットアンドペースト場合に必要に。メンテナンスのための頭痛の種を後回しにすることできますが、遅延を避けていることは確かです。
Steve314

74

実際の価値を追加しないにもかかわらず、プログラマーがどれほど賢いかを見せようとするコード:

x ^= y ^= x ^= y;

12
うわー、それはすっごくはるかに読みやすい未満だswap(x, y);
JBRWilkinson

8
xとyがポインターであり、この割り当てがかなりの時間にわたって行われた場合、Boehm GCのような保守的なガベージコレクターが正常に破損します。
SingleNegationElimination

12
ちなみに、このコードはCとC ++で定義されていません。シーケンスポイントが介在しない複数の変更があるためです。
fredoverflow

9
それを見て、頭に浮かんだのは絵文字だけでした^_^
。–ダリエン

62
  • 20,000(誇張)行関数。2つ以上の画面を必要とする関数では、リファクタリングが必要です。

  • 同じ行に沿って、永遠に続くように見えるクラスファイル。すべての内部メソッドである場合を除き、元のクラスの目的と機能、およびおそらくそれが使用されている場所を明確にするクラスに抽象化できる概念がおそらくいくつかあります。

  • 非記述的、非自明な変数、または自明でない非記述的変数が多すぎる。これらは、実際に何が起こっているのかを推測することを謎にしています。


9
可能な限り、機能を1画面に制限する傾向があります。
マットディトロリオ

20
1画面も一瞬です。10行ほどで汚れた気分になります。
ブライアンロウ

54
さて、私は不評な意見かもしれないものを表明するつもりです。開発者がいくつかの「関数は短くあるべき」貨物カルト主義にしがみついているので、独立した関数に分割されるアトミックでトップツーボトムのプロセスである関数を書くのはコード臭だと言います。関数は、神話上の「正しいサイズ」であるべきという理由だけでなく、FUNCTIONAL行に沿って分割する必要があります。それが関数と呼ばれる理由です。
ダン・レイ

7
@Dan、関数は短くするために短くするべきではありませんが、一度に頭の中に保持できる情報はあまりありません。たぶん私は小さな脳を持っているので、その制限はいくつかの画面です:)。ミスを避けるために境界のテストが必要になったときに、関数を複数の関数に分割する 一方でカプセル化を提供するため、より高いレベルで考えることができ、もう一方では、何が起こっているのかを隠して、関数の動作を理解しにくくします。関数を分割するのは、読みやすさを高めるためであり、「完全な長さ」に合うようにするべきではないと思います。
ドミニクマクドネル

6
@ドミニク、@ピーター、私たち3人は実際に同じことを言っていると思います。コードをより小さな関数に分解する正当な理由がある場合、私はそのためです。私が拒否しているのは、関数設計の短さのための短さです。必要な呼び出しスタックの3倍の長さですが、少なくともこれらの関数は短いです。私はむしろ、それぞれ前の呼び出しからのみ呼び出される12個の連鎖された関数を介して実行パスを追跡するよりも、1つのことを明確に行う高い関数をデバッグします。
ダン・レイ

61
{ Let it Leak, people have good enough computers to cope these days }

さらに悪いことに、それは商業図書館のものです!


32
これは警告音を鳴らしません。それは実質的に足の間を蹴ります。
スティーブンエバーズ

15
娘は覚醒剤です。誰も気にしない、少なくとも彼女は肥満になりません。::ため息::
エヴァンプライス

17
トラブルの時に自分自身を見つけたとき、母buntuは私に来ます。知恵の言葉を話す、それが漏れてみましょう。それを漏らしてください..それを漏らしてください。漏洩させましょう漏洩させましょう。それが一度だけ漏れる場合、それはleaaaaaakではありません。(ここまで読んだ場合、+ 1)。私は本当に聴覚障害者を考慮する必要があります。
ティムポスト

13
「締め切り速いアプローチ、漏れは、私が見ることができるすべてであるため、どこかで誰かがささやく、 『C ...... eeeeeeに書く!!!』」
chiurox

9
昔々、2つのOSがありました。1つは49日以上実行するとリークしてクラッシュしましたが、もう1つは完璧であり、永遠に実行されていました。1つは1995年に大規模なファンフェアで発売され、数百万人が使用しました。もう1つはバグがないことを確認しているため、出荷されませんでした。哲学と工学には違いがあります。
マーティンベケット

53

非常に冗長なコメントで、英語のコンパイラーがあれば、それは完全にコンパイルおよび実行されますが、コードにはないことは何も説明しません。

//Copy the value of y to temp.
temp = y;
//Copy the value of x to y.
y = x;
//Copy the value of temp to x.
x = temp;

また、廃止された可能性のあるコードに関するコメントでは、コードがいくつかの基本的なガイドラインに準拠していました。

//Set the age of the user to 13.
a = 13;

15
COBOLと呼ばれます:
Gaius

26
2番目のケースは最悪ではありません。最悪の場合:/ *ユーザーの年齢を13に設定* / a = 18;
ピロ

4
@PhiLho-いいえ、さらに悪いのは/from */が欠落しているため、次の末尾までのすべてのコード*/が無視されることです。幸いなことに、最近では構文の強調表示によってそのようなことがまれになっています。
Steve314

3
さらに悪いことに、auser_ageについては?本当に?
ガラスの

2
私は以前の雇用主でコード標準ドキュメントを維持していましたが、その1セクションは適切なコメントでした。:私のお気に入りの例では、MSDNからだったi = i + 1; //increment i
マイケルItzoe

42

コンパイル時に警告を生成するコード。


1
makefile / projectに「すべての警告をエラーとして」コンパイラオプションを追加する候補があります。
JBRウィルキンソン

3
あなたが単に信頼していない複数の人がいるプロジェクトにいる場合、それは便利だと思います-そのオプションが設定されているプロジェクトに参加する場合、それ自体が他の人の能力を心配するでしょうプログラマーです。
宮坂

1
私はこれに同意しません。いくつかのコンパイラ警告(型が異なる場合でも、両方の値が符号なしであることがわかっている場合の符号付きと符号なしの比較など)は、不要なキャストでコードを散らかすよりも望ましいです。整数に符号なしの値がある場合にのみ関数が変更する移植可能な符号付き整数を使用してコードを削減する場合、それを行います。
ティムポスト

13
むしろ(unsigned int)、警告/エラーリストを無害な警告で乱雑にするよりも、ほとんど不要なコードでコードを乱雑にします。警告リストが死角になるのは嫌だ。また、それはあなたが自然のキャストやっている理由を説明するよりも、あなたが警告を無視している理由PITAが他の人に説明するのはるかだintsとしますunsigned ints
宮坂

場合によっては、何をするにしてもエラーを吐き出すAPIを使用する必要があります。古典的な例は、APIが設計によって破損しているものに関して定義されている場合(一部の古いioctl()定数はそのようなものであり、OS開発者がヘッダーで間違った型を使用することを主張する場合)または良い代替品を残します(ありがとう、Apple)。
ドナルドフェロー

36

以下のように、説明的な名前はなく、名前に数字が含まれる関数

void doSomething()
{
}

void doSomething2()
{
}

関数名に何か意味があるようにしてください!doSomethingとdoSomething2が同様のことを行う場合、違いを区別する関数名を使用します。doSomething2がdoSomethingからの機能のブレイクアウトである場合、その機能に名前を付けます。


同様に、SQLの@Parm
Dave

2
+ mshtml
1-

3
これの例外はGUIコードです。たとえば、カタツムリメールフォームに2つのアドレスがある場合。address1とaddress2は、addressとalternateAddressよりも合理的です。静的のみの偽のラベルも合理的な例外です。
エヴァンプライス

@Evan-まあまあですが、機能性についてはもっと区別していました。
元気ウォンコ

1
+1-これは擬似バージョン管理方法として使用されることを見たことがあります。
EZハート

36

マジックナンバーまたはマジックストリング。

   if (accountBalance>200) { sendInvoice(...); }

   salesPrice *= 0.9;   //apply discount    

   if (invoiceStatus=="Overdue") { reportToCreditAgency(); }

4
2番目の2つではそれほど悪くはありませんが、少なくとも割引は説明されており、「期限切れ」は直感的です。200一方、...
Tarka

9
@Slokun-保守性と脆弱性ほど直感的ではありません。たとえば、割引額が変更され、6つの異なる場所で0.9がハードコーディングされた場合に何が起こるかを考えてください。また、定数/列挙の代わりに文字列を使用すると、大文字と小文字を区別する文字列を使用する言語で問題が発生します。
JohnFx

+1「timeout = 15;」という行が原因であることが判明した問題のデバッグにあまりにも多くの時間を費やしました。プログラムに埋もれた。
aubreyrhodes

invoiceStatusのデータがどこから来たのかに応じて、最後のものは時々大丈夫だと思います。デコードされたばかりのJSONを返すパブリックAPIからのものである場合、ハードコードされた文字列定数に対するチェックはおそらく大丈夫です。ただし、「200」と「0.9」は単なる魔法の定数であり、このようにハードコーディングしないでください。これらがこの1か所でしか使用されていない場合でも、ロジックコードに散在させるのではなく、構成セクションで個別に定義する方がメンテナンスが容易です。そして、それらが複数の場所で使用されている場合、メンテナンスがはるかに簡単になります。
ベン・リー

36
  • 最悪ではないかもしれませんが、明らかに実装者レベルを示しています。

    if(something == true) 
  • 言語にforループまたは反復子の構造がある場合、whileループを使用すると、言語の実装者レベルの理解も実証されます。

    count = 0; 
    while(count < items.size()){
       do stuff
       count ++; 
    }
    
    for(i = 0; i < items.size(); i++){
      do stuff 
    }
    //Sure this is not terrible but use the language the way it was meant to be used.
    
  • ドキュメンテーション/コメントのつづり/文法の悪さは、コードとほぼ同じくらい私を食い物にします。これは、コードは人間が読み取り、マシンを実行するためのものであるためです。私たちが高レベル言語を使用しているのはこのためです。もしあなたのドキュメンテーションがそれを通り抜けるのが難しいなら、私はそれを見ないでコードベースの否定的な意見を先制的に形成させます。


29

すぐに気づくのは、深くネストされたコードブロックの頻度(if、whileなど)です。コードが頻繁に2つまたは3つのレベルよりも深く進んでいる場合、それは設計/ロジックの問題の兆候です。そして、それが8つのネストの深さのようになった場合、それが分解されないためのかなり良い理由があります。


6
すべてのメソッドに1つのreturnステートメントのみを含める必要があることを知っている人もいますが、6レベル以上のif / thenネスティングを引き起こす場合、それは良いことよりもはるかに害があると思います。
ダリエン

28

学生のプログラムを採点するとき、私は時々「瞬き」スタイルの瞬間に伝えることができます。これらは即時の手がかりです:

  • 不十分または一貫性のないフォーマット
  • 3行以上の空白行
  • 非標準または一貫性のない命名規則
  • 繰り返されるコード、繰り返しが逐語的になればなるほど、警告は強くなります
  • 単純なコードである必要があるものは、非常に複雑です(たとえば、複雑な方法でmainに渡された引数をチェックする)

私の最初の印象が間違っていることはめったになく、これらの警告ベルはほぼ95%の割合で正しいです。例外として、この言語を初めて使用する学生は、異なるプログラミング言語のスタイルを使用していました。他の言語のイディオムで自分のスタイルを掘り下げて読み直すと、私にとっては警告音がなくなり、学生は完全に評価されました。しかし、そのような例外はまれです。

より高度なコードを検討するとき、これらは私の他の警告です:

  • データを保持するための「構造体」にすぎない多くの Javaクラスの存在。フィールドがパブリックであるかプライベートであり、ゲッター/セッターを使用するかは重要ではありませんが、考え抜かれたデザインの一部ではない可能性があります。
  • 単なる名前空間であり、コードに本当の凝集度がないなど、名前が貧弱なクラス
  • コードでさえ使用されていないデザインパターンへの参照
  • 説明のない空の例外ハンドラ
  • Eclipseでコードをプルアップすると、何百もの黄色の「警告」がコードに並んでいますが、これは主に未使用のインポートまたは変数が原因です

スタイルの観点から、私は一般的に見たくない:

  • コードをエコーするだけのJavadocコメント

これらは悪いコードの手がかりすぎません。プログラマーの意図がわからないため、悪いコードのように見えるかもしれませんが、実際にはそうではありません。たとえば、何かが過度に複雑に思える正当な理由があるかもしれません-遊びで別の考慮事項があったかもしれません。


ある言語のスタイルを別の言語で使用すると、深刻なエラー(インデントごとに2、4、8スペース...)がどのように発生するかがわかりません。生徒が従うべき他のスタイルがほとんどない場合、自己矛盾がないことは何も悪いことではありません。採点者には10億のプログラムが表示されるため、その範囲の反対側にいますが、それは別の(しかし一貫性のある)スタイルを完全に却下する理由ではありません。
ニックT

18
単純にデータを集約するクラス、つまり構造体には何も問題はありません。これがデータ転送オブジェクト(DTO)であり、たとえば20個のパラメーターをメソッドに渡すなど、コードを読みやすくすることができます。
ネミ

1
構造体に関するあなたのコメントはスポットです。データが最も生の形式であり、いかなる方法でも変更されない場合は問題ありません。ただし、95%の時間で、データをフォーマット/操作するためのクラスの関数が必要になります。本質的にそのパターンを使用するコードの一部を思い出し、改善する必要があります。
DisgruntledGoat

2
一貫性のないスタイルと余分な改行のために+1(ランダムなインデント、インデントなし、ランダムで変化する命名規則などを見てきました-これは本番コードで!)あなたがそれを正しくすることさえ気にすることができないなら、あなたは他に何をすることを気にすることができないのですか?
ディーンハーディング

1
本体に対してインデントされすぎているメソッドの宣言行を探します。これは、他の人のファイルからコピーアンドペーストされたサインです。
バリーブラウン

25

個人的なお気に入り/ペットのピーブ:コミットされたIDE生成の名前。TextBox1がシステム内の主要かつ重要な変数である場合、コードレビューが近づいています。


25

特に使用されている変数名に似た名前の変数の場合は、完全に未使用の変数


21

多くの人々が言及しています:

//TODO: [something not implemented]

私はそれらが実装されたことを望みますが、少なくとも彼らはメモしました。私が悪いと思うのは:

//TODO: [something that is already implemented]

あなたがそれらを削除することを決して気にしないなら、Todoは価値がなく、混乱しています!


1
リリース製品に含まれるすべてのTODOのレポートと、それらを廃棄するための計画を作成する必要があるという演習を行ったところです。ほぼ半分が時代遅れであることが判明しました。
AShelly

1
-1 TODOコメントは、MS Visual Studioで使用され、まだ作業が必要なプロジェクトの部分を追跡します。IEでは、IDEがTODOを追跡するリストを保持しているため、TODOを簡単にクリックして、TODOが存在する行に直接移動できます。TODOを明示的に配置して、まだ実行する必要がある作業を確認したいです。dotnetperls.com/todoを参照してください。
エヴァンプライス

3
@Evan Plaice:うわー、何かを実装したときにVS IDEが認識し、//TODOコメントを削除するということですか?驚くばかり!
JBRウィルキンソン

4
@Prof Plum TODOの責任者がコメントに自分の名前を入れるポリシーを作成してはどうですか。そのように、いくつかの残り物がある場合は、それ
エヴァンプライス

3
より良い計画を立てるには// TODO 、バグトラッカーを使用してください。
SingleNegationElimination

20

すべてを読むために下にスクロールする必要がある方法。


14
うーん、これは実装されているものに依存します。いくつかの複雑なアルゴリズムを実装するときにこれが定義されるので、これが発生するのは不合理ではありません。もちろん、メソッドの大半がその方法である場合、それは危険です。
ビリーONeal

9
全面的な声明として、私は同意しません。時間を常にリファクタリングして、すべてがこの種の自己課されたルールに適合するようにすると、プロジェクトの全体的なコストが実際に増加します。
匿名タイプ

1
このルールはプロジェクトの全体的なコストを増加させる可能性があることに同意しませんが、開発者に依存するため、主観的だと思います。開発中に「懸念の分離」の一般原則を守れば、リファクタリングを行うことを選択した場合、リファクタリングの作業は少なくなります。考慮すべき点は、元のプロジェクトをコーディングしなかった開発者が、300行以上のコードで多数のメソッドをバグ修正しようとしている場合、3年後にどれくらいの費用がかかるかです。それはいくらですか?
BradB

18
私は、下にスクロールするよりも右にスクロールすることにイライラしています。空白は「無料」です。
元気ウォンコ

4
コードが何をしているのかを理解するために、ファイル(または複数のファイル)全体をスキップするよりもスクロールしたいです。
TMN

20

メソッド名の接続詞:

public void addEmployeeAndUpdatePayrate(...) 


public int getSalaryOrHourlyPay(int Employee) ....

明確化:これが警告を鳴らす理由は、メソッドが単一の責任原則に違反している可能性が高いことを示しているためです。


うーん...関数名が関数の動作を正確に定義している場合、私は同意しません。この方法は、分離するのが良いだろう二つの別々のことを行い場合は、私があり、状況に応じて、同意するものとします。
元気なウォンコ

2
それがポイントです。接続詞は、それが複数のことを行う可能性が非常に高いことを意味します。質問ごとに、それは何かが間違っているかもしれないという私の認識を高めるものです。
JohnFx

3
では、従業員を追加して、複数の場所で給与を更新する必要がある場合はどうでしょうか?そのメソッドに2つのメソッド呼び出し(addEmployee(); updatePayrate();)が含まれている場合、それは問題ではないと思います。
マットグランデ

13

明らかにGPLのソースコードを商用のクローズドソースプログラムにリンクする。

それはすぐに法的問題を引き起こすだけでなく、私の経験では、通常、コードの別の場所にも反映されている不注意または無関心を示しています。


6
ポイントは優れていますが、トーンは不要です。
JBRウィルキンソン

@JBRWilkinson:ありがとう、あなたは正しい。すべてに私の謝罪。
ボブマーフィー

あなたの見出しは書き直す必要があると思います。静的および動的GPLなソースコードへのリンクの両方が... GPLの違反である
のGavinコーツ

良い点。投稿全体を書き直しました。ありがとうございます。
ボブマーフィー

9

言語に依存しない:

  • TODO: not implemented
  • int function(...) { return -1; } (「実装されていない」と同じ)
  • 非例外的な理由で例外をスローします。
  • の誤用または一貫性のない使用0-1またはnull例外的な戻り値として。
  • なぜ失敗しないのかを説得するコメントのないアサーション。

言語固有(C ++):

  • 小文字のC ++マクロ。
  • 静的またはグローバルC ++変数。
  • 初期化されていない変数または未使用の変数。
  • どれarray new明らかにRAII-安全ではありませんこと。
  • 明らかに境界セーフではない配列またはポインターの使用。これにはが含まれprintfます。
  • 配列の初期化されていない部分の使用。

Microsoft C ++固有:

  • Microsoft SDKヘッダーファイルのいずれかで既に定義されているマクロと衝突する識別子名。
  • 一般に、Win32 APIを使用すると、警告音が鳴ります。常にMSDNを開いて、疑わしいときはいつでも引数/戻り値の定義を調べてください。(編集済み)

C ++ / OOP固有:

  • 親クラスに仮想メソッドと非仮想メソッドの両方がある実装(具体的なクラス)の継承。

18
// TODO:この回答に対するコメント
johnc

8
「言語に依存しない」とは「C / C ++ / Java」を意味すると思いますか?
イナイマシ

+1「例外的でない理由で例外をスローする」は、これ以上同意できませんでした!
billy.bob

2
@Inaimathi-TODOコメント、関数スタブ、例外の乱用、ゼロ/ヌル/空のセマンティクスの混乱、無意味な健全性チェックは、すべての命令型/ OOP言語、およびある程度すべてのプログラミング言語に固有です。
宮坂Re

小文字のCプリプロセッサマクロ問題ありませんが、引数を1回だけ評価し、単一のステートメントのみを生成する場合に限ります。
ジョーD

8

奇妙なインデントスタイル。

いくつかの非常に人気のあるスタイルがあり、人々はその議論を墓場に持ち込むでしょう。しかし、時々私は誰かが本当に珍しい、あるいは自家製のインデントスタイルを使用しているのを見ます。これは、彼らがおそらく自分自身以外でコーディングしていないことを示しています。


2
または、「ベストプラクティス」とはまったく関係のない同種のコーディングプラクティスのウェブに巻き込まれていない、非常に高く評価された個人主義の才能であるという兆候です。
匿名タイプ

1
私はあなたが皮肉であることを願っています。誰かがそのような異常な方法でコーディングしている場合、それは警告音を鳴らすはずです。彼らは望みどおりに芸術的でありえますが、それでも...警鐘が鳴ります。
ケン

2
Haskell / ML / F#以外では非常に珍しいにもかかわらず、やや珍しいスタイル(ユトレヒトスタイルと呼ばれると思います)が非常に便利だと思います。「モジュールシェイプ」:learnyouahaskell.com/making-our-own-types-and-typeclassesまでスクロールします。このスタイルの良いところは、新しい行を追加するために前の行の区切り文字を変更する必要がないことです。これはよく忘れます。
宮坂

@ReiMiyasaka 7年遅れですが、...ユトレヒトスタイルは本当に私をいらいらさせます。Haskell仕様では、垂直に編成されたリストに別の「レイアウト規則」を課さないのは誤りだと思います。そうすれば、パーサーはインデントをチェックするだけで新しいリストエントリを検出できます。これは、とにかく全員がリストを整理する方法です。
ライアンライク

@RyanReich Weird、7年後、今でも気に入っています。しかし、私は同意します。F#では、構文上の扱いにくい点と失敗点の両方について、改行とインデント(ほとんどの場合)だけで項目を区切ることができるため、コードが整然としています。
宮坂

8

列挙型またはグローバルに定義された変数ではなく、多くのテキストブロックを使用します。

良くない:

if (itemType == "Student") { ... }

より良い:

private enum itemTypeEnum {
  Student,
  Teacher
}
if (itemType == itemTypeEnum.Student.ToString()) { ... }

ベスト:

private itemTypeEnum itemType;
...
if (itemType == itemTypeEnum.Student) { ... }

または最高:ポリモーフィズムを使用します。
Lstor

8

メソッドの弱い型指定のパラメーターまたは戻り値。

public DataTable GetEmployees() {...}

public DateTime getHireDate(DataTable EmployeeInfo) {...}

public void FireEmployee(Object EmployeeObjectOrEmployeeID) {...}

2
+1:明確な構文エラーであるものを渡す場合でも、すべてを擬似HTMLテーブルとして返す「REST」Webサービスを使用する必要があります。許可されていません?完全なジャンクを入力しますか?サーバーが容量を超えていますか?200(さらに、1列、1行のテーブルに不気味な形式のメッセージ)。AAaaaaaaaargh!
ドナルドフェロー

7
  • 複数の三項演算子が連結されているため、if...elseブロックに似ているのではなく、ブロックになりif...else if...[...]...elseます
  • アンダースコアまたはcamelCasingのない長い変数名。私がプルアップしたコードの例:$lesseeloginaccountservice
  • ファイル内の数百行のコード、コメントはほとんどまたはまったくなく、コードは非常に非自明です
  • 過度に複雑なifステートメント。コードからの例:if (!($lessee_obj instanceof Lessee && $lessee_obj != NULL))私がぎっしり詰めたif ($lessee_obj == null)

7

コードの匂い:ベストプラクティスに従っていない

この種のことは、誰もが自分が平均以上のドライバーだと思っているという真実があるので、常に私を心配しています。

yaのニュース速報は次のとおりです。世界の人口の50%が平均的な知能を下回っています。わかりましたので、一部の人々は正確に平均的な知性を持っているでしょうが、うるさくなりません。また、愚かさの副作用の1つは、あなた自身の愚かさを認識できないことです!これらのステートメントを組み合わせると、物事はそれほど良く見えません。

コードを見ると、どのものがすぐに警報を鳴らしますか?

多くの良いことが述べられていますが、一般的にベストプラクティスに従わないことはコードの匂いです。

通常、ベストプラクティスはランダムに考案されたものではなく、多くの場合、理由があります。多くの場合、それは主観的である可能性がありますが、私の経験ではほとんど正当化されています。ベストプラクティスに従うことは問題ではないはずです。なぜそうなっているのか疑問に思っている場合は、それを無視したり、文句を言ったりするのではなく、研究してください。

ベストプラクティスの1つの例は、1行しか含まれていない場合でも、すべてのifブロックでカーリーを使用することです。

if (something) {
    // whatever
}

あなたはそれが必要だとは思わないかもしれませんが、私は最近それがバグの主な原因であることを読みました。Stack Overflowでは常にブラケットの使用についても説明されています。ifステートメントにブラケットがあることを確認することは、Javaの静的コードアナライザーであるPMDのルールでもあります。

覚えておいてください:「それがベストプラクティスだから」は、「なぜあなたはこれをしているのですか?」という質問に対する容認できる答えではありません。何かがベストプラクティスである理由を明確にできない場合、それはベストプラクティスではなく、迷信です。


2
これはつまらないことかもしれませんが、どの平均を選ぶかが重要だと思います。私が理解しているように、世界人口の50%は知能の中央値を下回っています(定義上)。しかし、他の平均は同じようには機能しません。例えば、2の算術平均有する(5、1、1、1)集団を取る
flamingpenguin

えーと、あなたはソースが無い中括弧についての大胆な発言をした「何が迷信ですか、プログラマーが持っている」投稿を引用しました。ベストプラクティスの良い例とは思いません。
エヴァンプライス

@エヴァン:はい、あなたは正しいです。私はそれについてもう少し追加しました、これが役立つことを願っています。
ベトル

4
これの裏側は、なぜ「ベストプラクティス」であるかについての批判的な考えなしに、「ベストプラクティス」を従順に従う人々です。これが、「ベストプラクティス」という用語を強く嫌う理由です。一部の人々にとっては、思考を止めて群れに従うことの言い訳だからです。「それがベストプラクティスだから」という質問に対する答えは決して受け入れられません。何かがベストプラクティスである理由を明確にできない場合、それはベストプラクティスではなく、迷信です。
ダン・ダイアー

非常に良いコメント、ダン!答えに最後の2行を追加しました。
Vetle

6

「これは、frozサブシステムの設計が完全に損なわれているためです」と言うコメント。

それは段落全体にわたって続きます。

彼らは、次のリファクタリングを行う必要があることを説明しています。

しかし、それをしませんでした。

今、彼らは、時間や能力の問題のために、上司によってそれを変更できないと言われたかもしれませんが、おそらくそれは人々がささいなためでした。

スーパーバイザーがj.randomと考えている場合。プログラマーはリファクタリングを実行できません。スーパーバイザーが実行する必要があります。

とにかくこれは起こりますが、コードは分割されたチームによって書かれており、権力の政治があり得るので、中途半端なサブシステム設計をリファクタリングしませんでした。

実話。それはあなたに起こる可能性があります。


6

絶対パスでコードを合法的にファイルを参照する必要がある例を考えることができますか?


1
XMLスキーマは重要ですか?
ニックT

1
システム構成ファイル。通常は./configureで設定する必要がありますが、それでもどこかにデフォルト値が必要です。
エスワルド

4
/dev/null友達も大丈夫です。しかし、そのようなものでさえ/bin/bash疑わしい-あなたが持っている何か変なシステムなら/usr/bin/bashどうでしょう?
トムアンダーソン

1
JAX-WSツール(少なくともJBossWSおよびMetro)によって生成されたWebサービスクライアントコードには、WSDLファイルへのハードワイヤード絶対パスが含まれています(2回!)。これはおそらく非常に不適切なもの/home/tom/dev/randomhacking/thing.wsdlです。これがデフォルトの振る舞いであるということは犯罪的に非常識です。
トムアンダーソン

4
about /dev/null:Windows上で開発してアプリとライブラリを管理する習慣がありますc:\dev。どういうわけか、フォルダnullは常にそのフォルダ内に自動的に作成されます。誰がそれをするのかわからないと誓います。(私のお気に入りのバグ/機能の1つ)
ショーンパトリックフロイド

6

一般的な例外をキャッチする:

try {

 ...

} catch {
}

または

try {

 ...

} catch (Exception ex) {
}

リージョンの過剰使用

通常、使用するリージョンが多すぎるということは、クラスが大きすぎることを示しています。これは警告フラグであり、そのコードをさらに調査する必要があることを示しています。


一般的な例外をキャッチすることは、何もせずに再スローする場合にのみ問題になります。実際、ほとんどの場合、1つの例外クラスで十分です。runtime_errorを使用する傾向があります。
CashCow

「キャッチアンドスローアウェイ例外」の例では+1。例外で何もしていない場合は、キャッチしないでください。少なくとも、ログに記録します。少なくとも、すべての例外をキャッチして、コードのその時点に進むことができる理由を説明するコメントを入れてください。
EZハート

5

作成しようとしている抽象化に対する不十分な理解を示すクラス命名規則。または、抽象化をまったく定義しません。

極端な例は、タイトルが付けDataられ、最初のファイルで30,000行以上だったVBクラスで思い浮かびます。少なくとも半ダースの他のファイルに分割された部分的なクラスでした。ほとんどのメソッドは、などの名前を持つストアドプロシージャのラッパーFindXByYWithZ()です。

それほど劇的ではない例でさえ、完全に一般的なタイトルを与えられ、後でそれを後悔しているので、私たちはみな、考えの悪いクラスにロジックを「ダンプ」したに違いない。


5

言語の基本機能を再実装する関数。たとえば、JavaScriptで文字列の「.length」プロパティの呼び出しの代わりに「getStringLength()」メソッドが表示された場合、問題があることがわかります。


5
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...

もちろん、いかなる種類のドキュメントも、時々ネストされた#defines もありません


私は昨日、この「パターン」をプロダクションコードで見ました...さらに悪いことに、C ++プロダクションコードで見ました:-/
オリバーワイラー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.