コメント付きの短い派手なコードとコメントなしの長く理解しやすいコード-どちらが好ましいですか?


18

アルゴリズムは2つの方法で記述できる場合があります。

  • 短く、派手な方法。または
  • より長く、理解しやすい方法。

たとえば、Cに文字列sourceをコピーする、より長く簡単な方法を次に示しますdest

*dest = *source;
while (*source != '\0') {
    source++;
    dest++;
    *dest = *source;
} (true);

そして、ここに短い、派手な方法があります。

// Copy string source to dest
while (*dest++ = *source++);

私はいつも派手なコードを避けるべきだと聞いて読んでおり、私は同意する傾向があります。しかし、コメントを考慮するとどうなりますか?上記の例のように、コメントのない、より長く、おそらく理解しやすいと思われるコードと、コメントの良い、短い、派手なコードがあるとしますか?派手なコードはまだ優先されますか?

編集:多くの人が変数名についてコメントしているので、他のコードよりも優先する場合に要因にならないようにサンプルコードを変更しました。最初の例では二重の割り当てを削除しようとしましたが、コードが読みにくくなりました。

おそらく、これは最良の例ではありませんでした。なぜなら、多くの人は、長いコードよりも「派手な」コードの方が読みやすく理解しやすいためです。アイデアは、非常に短いが複雑なコードよりもはるかに理解しやすい1つの長いコードを持つことでした。

EDIT2は:ここで私はから得た新しいexamleだSO

コメント付きのファンシーバージョン:

//direct formula for xoring all numbers from 1 to N
int Sum = (N & (N % 2 ? 0 : ~0) | ( ((N & 2)>>1) ^ (N & 1) ) );

コメントなしのロングバージョン:

int Sum = 0;
for (int i = 1; i < N; ++i)
{
   Sum ^= i; //or Sum = Sum ^ i;
}

2
@gablin:「goodly」は単語ですが、「good」とは多少異なる意味を持つ形容詞であり、(少なくとも米国では)広く使われていません。「good」の副詞形式は「well」です「よくコメントされたコード」のように。
ジョンMガント

@ジョン:もちろん、はい。それに応じて質問を更新しました。ありがとう。
ギャブリン

2
短い方法は「空想」とはどういう意味ですか?これは、Cを知っていると主張する人なら誰でも問題なく読むことができるはずの教科書のCコードです。簡潔さは「空想」を意味しません。
JBRウィルキンソン

@JBRWilkinson:質問の修正された部分で述べたように、この例は「ファンシー」バージョンは明らかにそれほどファンシーではないので、良い例ではありません。目的は、コメントを使用して短いが理解できない方法を使用し、コメントを使用しないでより長く読みやすい方法を使用することでした。
ギャブリン

@gablin:編集すると、現在の回答が損なわれます。
マニエロ

回答:


28

私は一般的に、独自のメソッドに派手なコードを抽出することを好みます。

派手なコードにコメントするのではなく、メソッド名を明確にするために必要なものだけにしてください。

char *copy_string(char *s, const char *t) {    
    while (*s++ = *t++); 
    return s;
}

3
素晴らしい点。自己完結型のコードは、コメントよりもはるかに優れています。コンパイラは、必要に応じてインライン化する方法を知っています。
dbkk

ああ、それはコメントを時代遅れにする素晴らしい方法です。しかし、それにもかかわらず、長いコードよりも派手なコードを常に好むでしょうか?
ギャブリン

一般に、はい。短く、適切な名前のメソッドを使用すると、コードの読み取りと保守が容易になると思います。独自のメソッドに複雑さを織り込んでいるため、再利用がよりアクセスしやすくなります。例外は常に存在し、最終的には常にコードに依存します。
モンガスポン

確かにあなたの関数は 'strcpy'と名付けられるべきですか?
JBRウィルキンソン

そのコードにはエラーがあります。何が返されますか?何が返されることになっていましたか?ただそれを無効な方法にして、それでやりなさい;)
クリスチャン・マン

10

私はすべてより長いバージョンです。短いバージョンのコードの問題は、一部のプログラマーにとって読みにくいことは別として、ほとんどの場合、見ただけでは間違いを見つけるのが難しいということです。

実生活の例があります。この製品には、次のコードスニペットがありました。

if (++someCounter < MAX_VALUE) {
    // Do something that has to be done only MAX_VALUE times
}

このコードは一見したところ完全に合理的に見えますが、長時間経過するとこのカウンターがオーバーフローし、条件を破ります(実際のシナリオでは、OOMを使用してクライアントの運用システムを破壊しました)。このコードは少し「洗練された」ものではありませんが、想定されていることを実行することは明らかです。

if (someCounter < MAX_VALUE) {
    ++someCounter;
    // Do whatever it is we came here for
}

そして、あなたはこのコードを書いた開発者はちょうど十分ではなかったと言うかもしれません(それは真実ではありません、彼はかなり明るい男でした)が、あなたのコーディングテクニックがあなたがあなたのコードを正しくするために、あなたは何か間違ったことをしている。あなたのコードは、あなたのために、そしてあなたの後にこのコードを保守しなければならない人(あなたほど賢くないかもしれない人)のために、可能な限り愚か者であるべきです。

だから-私はすべてシンプルさと明快さのためだ。

編集:ああ、そしてコメントに関して-それは問題ではありません。とにかく多くの人々はコメントを読まないでしょう(http://www.javaspecialists.co.za/archive/Issue039.html)、コメントなしであなたのコードを理解できない人は、彼らと一緒にそれを十分に理解しないので、維持できます。目標は、人々が助けにある参照特定のコードはコメントはそれで助けることができない、「正しい」であること。


1
「クライアントの本番システムを

「短いバージョンのコードの問題は、一部のプログラマーが読むのがより難しいことは別として」-コードの一部は、「一部のプログラマーにとって」読むのが難しい場合があります。愚かな十分なプログラマを見つける必要があります。最小の分母までコードを馬鹿にしないでください。
quant_dev

@quant_dev:逆に、「デバッグは最初にコードを書くよりも2倍困難です。したがって、コードをできる限り巧妙に書くと、定義上、デバッグするのに十分ではありません。」—ブライアンW.カーニハン
マイケルボルグワード

@MichaelBorgwardt Kernighanのhanを盲目的にあらゆる状況に当てはめるつもりはありません。OPの例は、「可能な限り巧妙に」(またはそれに近い)記述された関数ですが、デバッグが必要な場合はデバッグが非常に簡単である必要があります。一方、複雑なビット調整のワンライナーは非常に賢い場合がありますが、デバッグはさらに難しくなります。(また、Kernighanは、コーディングスキル=デバッグスキルであると想定しています。必ずしもそうである必要はありません。コードをデバッグできたので、書くことができなかったでしょう。)
quant_dev

6

私は一般的に長いバージョンを好むでしょう。2つの主な理由が思い浮かびます。

  • より多くの人がより少ない労力でそれを理解する可能性があります(この文字列コピーのような「標準的な」例ではないと仮定します)。
  • 個々のステートメントにブレークポイントを設定し、デバッガーでステップスルーすることができます。

両方の長所を生かすために、コードを関数でラップします。関数の名前はコメントを提供します:

void copy_string(char *s, char *t)
{
    *s = *t;
    while (*t != '\0') {
        t++;
        s++;
        *s = *t;
    }
}

これを行わない唯一の理由は、パフォーマンスが問題であり、プロファイリングが機能のオーバーヘッドが著しいことを本当に示した場合です。


1
それはインラインの目的ではありませんか?
アントサン

実際、インライン化には、ヘッダーファイルで関数本体を公開する必要があるなど、独自の問題があります。とにかく、最新のコンパイラーは、賢明なところで自動的にインラインのものを用意しませんか?
ポールスティーブンソン

4

最も明確なものは何でも。多くの場合、これは2番目の例のように、コメントを必要としないコンパクトで理解しやすいコードスニペットです。

一般に、コードの短い断片は、読者が一度に頭に留めておくことが少ないため、理解しやすいです。明らかに、コードが過度に難読化されると制限があり、ホワイトスペースを強化する明瞭さをトリミングする必要があるという意味ではありません。

コメントは、コードから明らかなことを決して述べてはならず、読者に同じことを二度読ませるだけです。私にとって、最初のスニペットには説明が必要です。開発者がdo...whileループを使用して*s = *t;割り当ての重複を削除しなかったのはなぜですか?文字列コピーを実装していることを理解するには、さらにコードを解析する必要があります。コメントは、短いコードよりもこの長いコードの方が役立ちます。

2番目のスニペットのコメントは、ループは実質的に慣用的であるため、ほとんど冗長ですが、コード自体が有用なコメントを作成するコードよりも高いレベルでコードが何をするかを示しています。


開発者(私)はdo ... while、質問を書いたときに考えていなかったという理由だけで使用していません。それを指摘してくれてありがとう。^^ 2番目のスニペットはあなたには明らかかもしれませんが、私にとっては確かではありません。
ギャブリン

4

問題はshort fancy code、プログラマのレベルに大きく依存するため、明確な定義がないことです。while(*s++ = *t++);表現を理解するのに問題がない人もいれば、そうする人もいます。

個人的には、while(*s++ = *t++);完全に読みやすく、長いものは読みにくいと感じています。しかし、他の人は同意しないかもしれません。

とにかく、それはただ常識を使うことの問題です。読みやすさは間違いなく優先事項ですが、コードが長くなるとコードが長くなると読みにくくなる点があります。冗長性は、多くの場合、私の経験から読みやすさを低下させます。


これは、これらの答えの多くのテーマは「開発者がCでのstrcpy()を書くの標準的な方法を認識しないかもしれない」であることを私は悲しくなります
AShelly

それはすべきではありません-それは良いプログラマーがいないという意味ではなく、a)Cをあまり教えておらず、b)Cの強さはその弱点でもあるということです-そのループはCで実践している人には理解しやすいことであり、Cで何ができるかについて暗示するものに対してかなり怖いセキュアなコードを書くことを試みている世界でも
マーフ

そのため、私たちは日々の仕事に別の課題を抱えています。コードレビューが建設的なままであるように、直接のピアの言語理解の一般的なレベルを推測する必要があります。戦いに陥らないことは、「正しい」、より明確な意図の表現です。
frogstarr78

2

私はここで他のほとんどの答えに同意する必要があります-私は(少なくともこの場合)短いコードが優れていると思います。あなたの主張に反して、少なくとも読者にとっては、長いコードは「簡単」ではありません。どちらかといえば、コードを理解しにくくしたり、正しい動作を保証したりするために、コードを長くしたいという気持ちから抜け出したようです。

具体的には、他のバイト、1がなければならない手段の割り当てとは別に、ループ外の文字列の最初のバイトの割り当てを持つ非常に必ずすべてのバイトが正しくコピーされていることであることを読んでより慎重に。短いバージョンのアクションの基本的なシーケンスは、確認がはるかに簡単です。その唯一の本当の問題はフォーマットにあります-意図的に空のループ本体がある場合、それを明確にすることが最善です:

while (*dest++ = *source++)
    ;

あるいは:

while (*dest++ = *source++)
    ; /* no body */

代わりに中括弧を使用することを好む人もいます:

while (*dest++ = *source++)
    {}

あなたが好む正確なフォーマットに関係なく、次のようなもので十分な間違いがなされています:

if (x>y);
     x = z;

... 1)フロー制御によって実際に制御されいるものが明らかであること、および2)それによって制御されいるものを知っているコードが書かれいることが明らかなので、それを読んでいる人が時間を無駄にしないことを確認することが重要ですバグを発見したかどうかを把握します。


はい、この特定の例を振り返ってみると、「ファンシー」バージョンはおそらく長いバージョンよりも読みやすいでしょう。もっと良い例が思い浮かぶなら、今はできません。しかし、私はそれを長くする「邪魔にならない」ことはしませんでした-それが、少なくとも最初は文字列のコピーを書く方法です。それは最善のアプローチではないかもしれませんが、意図的に必要以上に長くはされていません。
ギャブリン

2
Keep it simple, stupid!

他のプログラマーがあなたのコードが何をするのかを理解できることを確認してください。そして、それがひと目でわかるとさらに良いでしょう(これは良い名前とコメントが出てくるところです)。

派手なビットカンドリングカンフーとインラインアセンブリは、(おそらく不必要で時期尚早な)最適化の名においてすべて素晴らしいですが、2か月後にバグに遭遇したときに書いたコード理解できない場合でもです。 。ポイントは何でしたか?時間と労力がかかります。

これらの状況では、しばしばZen of Pythonを参照します。特に:

Explicit is better than implicit.
Simple is better than complex.

1

プロダクションソフトウェアで派手なコードを書かないでください。実際にそれを書くことができるのは気持ちが良いことを知っています。派手なコードを書くと、「WTF /分」の値が大幅に増加します。つまり、品質が低下します。

代替テキスト


1

もちろん、状況に完全に依存します。しかし、一般的に、私はこれが良い経験則であると思います:

デバッグは、最初にコードを記述するよりも2倍困難です。したがって、コードを可能な限り巧みに記述すると、定義上、デバッグするのに十分なほど賢くありません。

〜ブライアン・カーニガン


より長く、より意味のある、エレガントな、よりコンパクトなKISSの頭字語〜そこに皮肉が失われないことを願っています; p
violet313

0

私の経験では、空想コードが短いという点で最大のメリットは、反復ではなく再帰を使用することです。また、すべてが再帰的であるような言語で作業している場合を除き、コードを一目で理解することは最も難しいことの1つです。私はそれが提供する開発の優雅さとスピードのためにそれを好むだろうが、将来のメンテナーまたは私の将来の自分にとって不透明であるように見える場合は詳細なコメントを確実にしようとする。


0

私はコメントを決して信用し始めません。多くの場合、コメントはコードが更新されても更新されず、非常に古くなっているか、もはや関係のないクライアント/管理者からのルールを表します。

コメントがもはや説明しているコードと一致しない場合もあります。

短い/空想、より長い/簡単に理解することを選択する必要がある場合は、本当に正当な理由がない限り、常に後者を選択します。


0

読みやすさと保守性が重要であり、2番目の例(長い方の例)は両方ともはるかに多くなります。しかし、なぜ2つのオプションに制限するのですか?長いコードでさえ複雑すぎて(IMHO)、それ以上表記することはできません。適切なJavadoc(または何でも)と適切なメソッド名を持つ独自のメソッドに入れました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.