web-dev-qa-db-ja.com

コメントアウトされたコードは貴重なドキュメントになりますか?

次のコードを書きました。

if (boutique == null) {
    boutique = new Boutique();

    boutique.setSite(site);
    boutique.setUrlLogo(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getLogo());
    boutique.setUrlBoutique(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getUrl());
    boutique.setNom(fluxBoutique.getNom());
    boutique.setSelected(false);
    boutique.setIdWebSC(fluxBoutique.getId());
    boutique.setDateModification(new Date());

    boutiqueDao.persist(boutique);
} else {
    boutique.setSite(site);
    boutique.setUrlLogo(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getLogo());
    boutique.setUrlBoutique(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getUrl());
    boutique.setNom(fluxBoutique.getNom());
    //boutique.setSelected(false);
    boutique.setIdWebSC(fluxBoutique.getId());
    boutique.setDateModification(new Date());

    boutiqueDao.merge(boutique);
}

ここにコメントアウトされた行があります。しかし、ifelseの違いを明らかにすることで、コードがより明確になると思います。違いは、色の強調表示でさらに顕著になります。

このようなコードをコメントアウトすることは良い考えですか?

83
Alexis Dufrenoy

ほとんどの回答は、この1つの特定のケースをリファクタリングする方法に焦点を当てていますが、コメントアウトされたコードが通常悪い理由に対する一般的な回答を提供させてください。

まず、コメントアウトされたコードはコンパイルされません。これは明らかですが、次のことを意味します。

  1. コードも機能しない可能性があります。

  2. コメントの依存関係が変更されても、明らかに壊れることはありません。

コメント付きコードは非常に「デッドコード」です。そこに長く留まるほど、腐敗し、次の開発者に提供する価値がますます少なくなります。

第二に、目的が不明確です。ランダムにコメントされた行がある理由のコンテキストを提供する長いコメントが本当に必要です。コメントされたコード行だけが表示された場合、なぜそこに到達したのかを理解するために、どうやってそこに到達したのかを調査する必要があります。誰が書いたの?何コミット?コミットメッセージ/コンテキストとは何ですか?等。

代替案を検討してください:

  • 関数/ APIの使用例を提供することが目的の場合は、単体テストを提供します。単体テストは実際のコードであり、正しくなくなると機能しなくなります。
  • 以前のバージョンのコードを保持することが目的である場合は、ソース管理を使用します。以前のバージョンをチェックアウトしてから、コードベース全体でコメントを切り替えて、変更を「元に戻す」ことをお勧めします。
  • 目的が同じコードのalternateバージョンを維持することである場合は、ソース管理(再度)を使用します。結局のところ、それがブランチの目的です。
  • 目的が構造を明確にすることである場合は、コードをどのように再構成してより明確にするかを検討してください。他の回答のほとんどは、これを行う方法の良い例です。
109
Chris Pitman

このコードの最大の問題は、これらの6行を複製したことです。重複を解消すると、そのコメントは役に立たなくなります。

boutiqueDao.mergeOrPersistメソッドを作成する場合、これを次のように書き換えることができます。

if (boutique == null) {
    boutique = new Boutique();
    boutique.setSelected(false);
}

boutique.setSite(site);
boutique.setUrlLogo(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getLogo());
boutique.setUrlBoutique(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getUrl());
boutique.setNom(fluxBoutique.getNom());
boutique.setIdWebSC(fluxBoutique.getId());
boutique.setDateModification(new Date());

boutiqueDao.mergeOrPersist(boutique);

特定のオブジェクトを作成または更新するコードは一般的であるため、たとえばmergeOrPersistメソッドを作成するなどして、一度解決する必要があります。これら2つのケースでは、割り当てコードをすべて複製するべきではありません。

多くのORMは、何らかの方法でこれに対するサポートを組み込んでいます。たとえば、idがゼロの場合は新しい行を作成し、idがゼロでない場合は既存の行を更新します。正確な形式は問題のORMに依存します。私はあなたが使用しているテクノロジーに精通していないので、私はあなたを助けることができません。


mergeOrPersistメソッドを作成したくない場合は、_isNewBoutiqueフラグを導入するなど、他の方法で重複を排除する必要があります。それはきれいではないかもしれませんが、割り当てロジック全体を複製するよりもはるかに優れています。

bool isNewBoutique = boutique == null;
if (isNewBoutique) {
    boutique = new Boutique();
    boutique.setSelected(false);
}

boutique.setSite(site);
boutique.setUrlLogo(CmsProperties.URL_FLUX_BOUTIQUE + fluxBoutique.getLogo());
boutique.setUrlBoutique(CmsProperties.URL_FLUX_BOUTIQUE + fluxBoutique.getUrl());
boutique.setNom(fluxBoutique.getNom());
boutique.setIdWebSC(fluxBoutique.getId());
boutique.setDateModification(new Date());

if (isNewBoutique)
    boutiqueDao.persist(boutique);
else
    boutiqueDao.merge(boutique);
263
CodesInChaos

これは完全に恐ろしいの考えです。それは意図が何であるかを明確にしません。開発者が誤ってその行をコメントアウトしましたか?何かをテストするには?どうしたの?!

両方のケースで絶対に等しい6行が表示されるという事実は別として。むしろ、このコードの重複を防ぐ必要があります。次に、あるケースでは、さらにsetSelectedを呼び出すことがより明確になります。

いいえ、それはひどい考えです。そのコードの一部に基づいて、以下の考えが私の頭に浮かびます。

  • 開発者がデバッグしていて、行を以前の状態に戻すのを忘れていたため、この行はコメント化されています
  • この行は、以前はビジネスロジックの一部であったためコメント化されていますが、現在はそうではありません。
  • この行はコメントアウトされています。これは、本番環境でパフォーマンスの問題を引き起こし、開発者は本番システムへの影響を確認したかったためです。

何千行ものコメントアウトされたコードを確認した後、私はそれを目にしたときに唯一の賢明なことを行っています。すぐに削除します。

コメントアウトされたコードをリポジトリにチェックインする合理的な理由はありません。

また、コードでは多くの重複が使用されます。できるだけ早く人間が読みやすいように最適化することをお勧めします。

120
Dibbeke

私はCodesInChaosの答えに追加したいと思います 小さなメソッドにさらにリファクタリングする できることを指摘することによって。構成ごとに共通の機能を共有すると、条件を回避できます。

function fill(boutique) {    
  boutique.setSite(site);
  boutique.setUrlLogo(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getLogo());
  boutique.setUrlBoutique(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getUrl());
  boutique.setNom(fluxBoutique.getNom());
  boutique.setIdWebSC(fluxBoutique.getId());
  boutique.setDateModification(new Date());
}    

function create() {
  boutique = new Boutique();      
  fill(boutique);
  boutique.setSelected(false);
  return boutiqueDao.persist(boutique);
}

function update(boutique) {
  fill(boutiquie);
  return boutiquieDao.merge(boutique); 
}

function createOrUpdate(boutique) {
  if (boutique == null) {
    return create();
  }
  return update(boutique);  
}
51

これは明らかにコメントアウトされたコードの良いケースではありませんが、私がそれを正当化すると思う状況があります:

// The following code is obvious but does not work because of <x>
// <offending code>
<uglier answer that actually does work>

明らかな改善がそうではないというのは、後で見る人への警告です。

編集:私は小さなことについて話している。それが大きい場合は、代わりに説明します。

27
Loren Pechtel

この特定の例では、コメントアウトされたコードveryがあいまいです。主な理由は Dibkkeの回答 で概説されています。他の人は、コードをリファクタリングしてこれを実行する誘惑さえも回避できる方法を提案していますが、それが何らかの理由で不可能である場合(たとえば、行が類似しているが、十分に接近していない場合)、次のようなコメントをいただければ幸いです。

// [WHATEVER]なので、このブティックの選択を解除する必要はありません

ただし、コードを残す(またはコメントアウトを追加する)だけでは理解できない状況もあると思います。 MATLABやNumPYのようなものを使用する場合、1)配列を反復処理して一度に1つの要素を処理するか、2)配列全体を一度に操作する同等のコードを記述することができます。場合によっては、後者の方がはるかに高速ですが、読みにくくなります。いくつかのコードをベクトル化された同等のものに置き換える場合、次のように、元のコードを近くのコメントに埋め込みます。

%%以下のベクトル化されたコードはこれを行います:

% for ii in 1:N
%    for jj in 1:N
%      etc.

%ですが、マトリックスバージョンは通常の入力で最大15倍速く実行されます(MK、2013年3月10日)

明らかに、2つのバージョンが実際に同じことを行い、コメントが実際のコードと同期したままになるか、コードが変更された場合はコメントが削除されるように注意する必要があります。明らかに、時期尚早の最適化に関する通常の警告も当てはまります...

14
Matt Krause

コメントアウトされた便利なコードを確認したのは、構成ファイル内だけでした。すべてのオプションのコードが提供されていますが、コメントアウトされているため、コメントマーカーを削除するだけで簡単に設定を有効にできます。

## Enable support for mouse input:
# enable_mouse = true

この場合、コメント化されたコードは、使用可能なすべてのオプションとその使用方法を文書化するのに役立ちます。また、全体を通してデフォルト値を使用することも一般的であるため、コードはデフォルト設定も文書化しています。

12
Carl Smith

一般的に言って、コードはコードを書いた人に自己文書化するだけです。ドキュメントが必要な場合は、ドキュメントを作成します。ソースコードベースを初めて使用する開発者が何千行ものコードを読んで、何が起こっているのかを高レベルから把握しようとするのは受け入れがたいことです。

この場合、コメントアウトされたコード行の目的は、重複するコードの2つのインスタンスの違いを示すことです。違いをコメントで微妙に文書化しようとする代わりに、意味のあるようにコードを書き直してください。次に、コードにコメントする必要があると感じた場合は、適切なコメントを記述します。

7
Mike Van

いいえ、コメントされたコードは古くなり、すぐに価値のないものよりも悪くなります。現在のすべての仮定とともに、実装のいくつかの側面を固めるので、それはしばしば有害です。

コメントには、インターフェースの詳細と目的の機能を含める必要があります。 「意図した機能」:含めることができます。最初にこれを試し、次にそれを試し、次にこの方法で失敗します。

私が見たところ、コメントにコメントを残そうとするプログラマーは、彼らが書いたものにただ恋をしているので、たとえ完成品に何も追加していなくても、それを失いたくありません。

4
Grady Player

非常にまれな場合もありますが、実際にはそうではありません。他の答えは、その理由をかなりうまく説明しています。

まれなケースの1つは、テンプレートです RPM仕様 私たちのショップでは、すべての新しいパッケージの出発点として使用しています。すべてではありませんが、ほとんどのパッケージには、標準的な名前があり、タグで指定されるソースを含むtarballがあります。

Name:           foomatic
Version:        3.14
 ...
Source0:        %{name}-%{version}.tar.gz

ソースのないパッケージの場合は、タグをコメント化し、その上に別のコメントを付けて標準フォーマットを維持し、誰かが開発プロセスの一部として問題を停止して考えたことを示します。

Name:           barmatic
Version:        2.71
 ...
# This package has no sources.
# Source0:        %{name}-%{version}.tar.gz

他の人がカバーしているように、そこに属するものと間違えられる可能性があるため、使用されないことがわかっているコードを追加しないでください。できる。ただし、そこにあるはずのコードがない理由を説明するコメントを追加すると便利です。

if ( condition ) {
  foo();
  // Under most other circumstances, we would do a bar() here, but
  // we can't because the quux isn't activated yet.  We might call
  // bletch() later to rectify the situation.
  baz();
}
2
Blrfl

コメントアウトされたコードはアプリケーションでは使用されないため、理由が使用されていないことを示す追加のコメントを添える必要があります。しかし、その中でコンテキスト、コメントアウトされたコードが役立つ状況があります。

私の頭に浮かぶのは、一般的で魅力的なアプローチを使用して問題を解決する場合ですが、実際の問題の要件はその問題と少し異なることがわかります。特に、要件がかなり多くのコードを必要とすることが判明した場合、メンテナーが古いアプローチを使用してコードを「最適化」する誘惑はおそらく強いですが、それをしてもバグは元に戻ります。コメントで「間違った」実装を維持すると、これを払拭するのに役立ちます。これは、この状況でそのアプローチが間違っている理由を正確に示すために使用できるためです。

これは私が想像できるほど頻繁に発生する状況ではありません。通常、サンプルの「間違った」実装を含めずに説明するだけで十分です。しかし、私はできるそれが十分ではない場合を想像します、それで問題はそれが有用であるかどうかについてですので、はい、それはできます。ほとんどの場合ではありません。

1
The Spooniest