入力されていないように見えるコードを安全に削除するにはどうすればよいですか?


125

余分に見えるコードを見つけましたが、コンパイラーはそれに気付きません。このコードを削除してもリグレッションが発生しないことを確認する(またはできる限り確実に近くする)ために何をしますか。

2つのアイデアが思い浮かびます。

  1. 「単純に」、コードが実行されるように見えるかどうかに基づいて演deを使用します。ただし、これは複雑で時間のかかる作業であり、実質的なビジネスリターンが得られないため、わずかにリスクが高い(評価がエラーになりやすい)場合があります。

  2. そのコードセクションにロギングを配置し、実際に入力される頻度を確認します。十分な実行後、コードを削除しても安全であると合理的に確信できます。

より良いアイデアや標準的なアプローチのようなものはありますか?


55
バージョン管理履歴を確認すると役立つ場合があります。「デッドコード」が作成されたのはいつですか。作成されたときに死んでいたように見えましたか?作成と同時に、それを使用する他のコード(それ以降に変更または削除された)がチェックされましたか?
ChrisW

9
リフレクションなどの何らかのメタプログラミングが機能している場合、コンパイラは信頼できません。基本ディレクトリの適切なgrepは必須のプラクティスです。複数のアプリケーションがコードを共有することも一般的であるため、正しいディレクトリレイヤーでgrepを実行してください。
アダムキャビネス

16
「どうしてわざわざ削除するの?」ブルームーンで一度呼び出されるエッジケースで使用されている場合は、破損しています。一度も使用せずにそのままにしておくと、実行可能ファイルのサイズが少し大きくなるという損害があります。これが一部の組み込みデバイス用でない限り、これは大したことですか?それにコメントを貼り、あなたの時間を生産的に使うことに進みましょう。
mickeyf

40
@mickeyf被害は、誰かがそのコードを維持しなければならないことです。つまり、開発者はその機能を理解する必要があります。状況が変化した場合、開発者はそれを変更する必要があり、その周りのコードは現在、別のことをしなければなりません。私を信じてください、あなたが漂流物を横に置いたままにしておくと、それは後で物事を理解しようとしている人にとって大きな頭痛の種です。
jpmc26

9
@MichaelJ。私のポイントは、そもそもそこにあるべきはなかったということです。そして、私がそれを辞めた場合、状況はさらに悪くなります。現在、他の開発者も同様に調査する必要があります。長い間、それを理解するのにより多くの時間が費やされます。これは余分なコードのコストです。
jpmc26

回答:


112

100%の単体テストカバレッジがある私の完璧なファンタジーの世界では、それを削除して単体テストを実行し、赤にならないテストがなければコミットします。

しかし残念なことに、私は毎朝目を覚まし、多くのコードに単体テストがないか、存在するすべてのエッジケースを実際にカバーすることを信頼できないという厳しい現実に直面しなければなりません。だから私はリスク/報酬を考慮し、それは単に価値がないという結論に達します:

  • 報酬:コードは将来維持するのが少し簡単です。
  • リスコーダー自身ではない利害関係者に。

249
エンジニアが10〜12年間、ほとんどの場合、「価値のない」アプローチに従って余分なコードを削除する大規模なソフトウェアプロジェクトの状態を観察したため、このアプローチお勧めできません
-njuffa

125
また、単体テストでは、このコードが実際に運用環境で使用されているかどうかについては何もわかりません。コードは完全にテストできますが、実稼働ではまだ使用されていないため、不要です。
ナブ

8
私の経験では、そのようなプロジェクトの状態は、事後にコードを修正する「価値のない」アプローチによるものではありません。それは、まず悪いコードが最初に書かれているためです。悪いコードを書くのは間違いですが、コードをきれいにすることが常に価値があると考えるのは間違い(より高度な間違い)です。
ウェイランドユタニ

42
@Weyland Yutaniそれは私の経験とはまったく一致しません。私が見た可能性のある余分なコードのほとんどは、10年前に存在していたソフトウェア仕様、ハードウェアプラットフォーム、またはオペレーティングシステムバージョンを十分に記述し、完全に合理的であり、以前に利用可能なツールチェーンまたはハードウェアのバグや制限を回避するために必要でした。
njuffa

20
Answerは、先に進んで変化を起こすことの最も重要で重要な利点の1つ、つまり、物事を学ぶことを見逃しています。学習した後、構造(コメント、テスト)を追加して、後でメンテナンス開発者を支援できます。結果を知らないために何かを変更しないことを選択することは、たとえその選択が何かを削除しないことであっても、カーゴカルトプログラミングです。
小次郎

84

このプロセスには2つの半分があります。1つ目は、コードが実際に死んでいることを確認することです。2つ目は、間違っているコストを把握し、適切に軽減することです。

ここでの多くの回答には、前半に対する優れた解決策があります。静的アナライザーなどのツールは、デッドコードの特定に最適です。 grep場合によってはあなたの友達になれます。私がよくとる珍しい手順の1つは、コードの本来の目的が何であるかを特定することです。「Xは製品の機能ではなくなり、コードセグメントYは機能Xをサポートするように設計されました」と言うのは、「コードセグメントYの目的がわからない」と言うよりもはるかに簡単です。

後半は、コードを削除する必要があるかどうかを判断するための重要なステップです。答えが間違っていることの意味を理解する必要があります。答えが間違っていると人々が死ぬのであれば、注意してください!たぶん、コードクラフトが時間の経過とともに発展することを受け入れ、代わりに自分でもっとクラフティングを書かないようにしようとするのが良い時期かもしれません。人々が死なない場合は、ユーザーがどの程度寛容であるかを自問してください。何かを破って顧客との関係を維持した場合、修正プログラムを送信できますか?このような問題を見つけるために支払われるQ&Aチームはありますか?これらの種類の質問は、削除キーを押す前にどれだけ確実でなければならないかを理解するために不可欠です。

コメントの中で、rmunは、削除する前にコードの本来の目的を理解するという概念の優れた表現を指摘しました。引用は現在チェスタートンのフェンスとして知られています。コメントで直接引用するには大きすぎますが、ここで適切に引用する価値があると思います。

物事を変形させることとは異なり、物事を改革することに関しては、1つの単純で単純な原則があります。おそらくパラドックスと呼ばれる原理。そのような場合、特定の機関または法律が存在します。簡単にするために、道路の向こう側にフェンスまたはゲートを設置しました。より近代的なタイプのリフォーマーは、これに積極的に取り組んでおり、次のように述べています。よりインテリジェントなタイプのリフォーマーは、答えを出すのにうまくいくでしょう。離れて考えてみてください。それから、戻ってきて、その使用を確認したと言ったら、私はあなたにそれを破壊することを許すかもしれません。


14
Chesterton's Fenceは、発見は純粋に思考によるものであり、頼りになるものではなく、古代ギリシャの哲学であると想定しています。科学的手法はより現代的です。構造を除去した結果を判断するために、制御された実験を考案してください。確かに、私はこの実験を実稼働で行うことをさりげなく提案しません。しかし、代替手段がなく、実稼働環境での試用のコストが非常に高い場合は、コードが存在する理由を知るための安全な手段を提供していない職場をすぐに離れるでしょう。そのような仕事での個人的なリスクは高すぎます。
小次郎

15
@kojiroそれは本当です。「現代の改革者」として来て、「このフェンスがここにある理由がわからないので、認める。私はそれを認めるためにそれを赤く塗りたい」新しい情報を提供してくれます」とチェスタートンはおそらく喜んでいるでしょう。
コートアンモン

41
VMS OSカーネルモードクロックデコーディング方法SYS $ ASCTIMには、春分点の恒星ドリフトを修正するのに役立つコード行が含まれています。DECの単体テストでは、このコードを実行しません。2000-02-28の23:59:59:999に1回(正しく)実行されました。2400年まで再度実行されません。削除しないでください。
AI Breveleri

13
私はStackExchangeでこれを説明する、とだけではなく、ここでのコード自体にコメントがあることを願っていなければならない@AIBreveleri:D
カイルストランド

11
@KyleStrand何のことを言ってるの?これドキュメントです。StackExchangeよりも他の人が見つけられるように重要な情報を配置するより良い場所を考えられますか?;-)
コートアンモン

43

またgrep、コード内の関数/クラス名を使用する傾向があります。これにより、たとえば、コメントやドキュメントファイル、またはスクリプトで名前が言及されている場合など、コードアナライザーにはない追加の利点が得られます。ソースツリーのファイルに対してgrepを実行し、結果をファイルに保存します。通常、結果は要約された情報を提供します:ファイル名/パス、行番号、名前が出た行、これは関数/クラスが呼び出されたり、意味的な意味なしに言及されている場所の手がかりを与えることができます(コードアナライザとは対照的に)、およびファイル拡張子に関係なく。間違いなく究極のソリューションではなく、分析への素晴らしい追加です。


11
私はダウンボーターではありませんが、実行が疑われるコードセクションが完全な関数またはクラスではなく、メソッド/関数のセクションである場合はどうでしょうか。
Tulainsコルドバ

9
言語によっては、これは常に信頼できるとは限りません。一部の言語では、メソッド呼び出しを動的に行うことができます。たとえば、PHPの場合:$object->$variableMethod($arg1, $arg2);
Dezza

9
@TulainsCórdovaそして、これは明らかに良い解決策ではないでしょう。すべての潜在的なソリューションに関しては、与えられたコンテキストで意味がある場合に使用します。しかし、たぶんgrep、例えば。コードセクションを含む関数は、関数がどのように使用されているか、したがってその内容に関する手がかりを与えることができますか?
ピウィ

7
「コメント、ドキュメントファイル、またはスクリプトで名前が言及されている場合」-または誰かがリフレクションを使用してメソッドを呼び出す場合(高レベル/ OO言語を使用している場合)。一部の言語ではメソッドを見つけて呼び出す非常に鈍い方法がサポートされているため、必ずしも100%正確であるとは限りません。
アロス

これは、関数を使用できるすべての可能なコードにアクセスできる場合に役立ちます。ただし、コードがライブラリの一部である場合、検索できない他の何かが壊れないことをどのようにして知ることができますか?
ケビンシェイ

30
  • 死んでいるように見えるコードを特定します(静的分析など)。
  • 死んだとされるコードの呼び出しごとにログメッセージを追加します。関数/メソッドを使用すると簡単です。定数のような静的メンバーを使用すると、扱いにくくなります。コードを非推奨としてマークするだけで、ランタイムが自動的にメッセージを記録する場合があります。それ以外のコードはそのままにしておきます。
    • デッドモジュールがロードされたときにメッセージをログに記録します。ほとんどの言語には、ロード時に静的初期化を実行する方法があります。
    • ログメッセージに適切なスタックトレースが含まれていることを確認して、デッドコードと呼ばれるものを理解できるようにしてください。
  • 変更したコードをすべてのテストスイートで実行します。また、テストスイートは、真夜中を越える、四半期の変わり目、年の変わり目などの特別な時間についてもテストする必要があります。ログを見て、何が死んでいるかの理解を更新します。単体テストは具体的にデッドコードをテストする可能性がありますが、他の単体テストや統合コードはそれに触れないことに注意してください。
  • 変更されたコードを本番環境で数週間実行します。月に一度のETL cronジョブなど、すべての定期的なプロセスがこの期間中に実行されるようにしてください。
  • ログを見てください。ログに記録されたものは、実際には死んでいません。残りのデッドコードに対するコールグラフの推移的閉包も、呼び出されていなくて潜在的にデッドではありません。分析してください。たぶん、いくつかのブランチは安全に死んでいます(たとえば、今では絶滅したサービスのAPIを使って作業しています)が、まだブランチはありません。モジュール/クラス全体は、その中に定義された定数に対してのみロードされ、簡単に使用できます。
  • 残っているものはすべて安全に死んでおり、削除することができます。

すべてが初めてなので、コードが以前に実行されなかったからといって、特に実行パスがある場合にコードが実行されないわけではありません。つまり、実行可能なものを削除することを決定することは、実行できるかどうかを判断することとは異なるプロセスです。

7
@nocomprendeは、このコードが年末の機能にのみ使用され、テストを2月から11月に実行した場合に正確に何が起こるかを示しています。
エリック

1
@ 9000理論上は同意しますが、レガシーシステムは、この種のテストを妨げる可能性のある隠れた依存関係に悩まされています。テストの例が機能するには、何らかの一時的なカップリングがあることを知る必要があります。一時的なカップリングがテスト対象のコードの外部にある場合、コードでそれを確認することはできず、一時的なカップリングが要因であることはわかりません。たとえば、サイロAのコードはGACにインストールされます。数年前、サイロBはサイロAに、サイロAのデータに対して実行する必要があるレポートのコードパスを追加するように依頼しました。続き
エリック

1
@ 9000続き 現在、サイロBのコードは、サイロAのコードを「デッド」コードパスに一時的に結合していますが、サイロAのコードを見ただけではわかりません。一時的な結合はサイロBのコード内でのみ行われるため、サイロBと対話することを知らないため、この一時的な結合についてどのように単体テストを行いますか?それでも、時間はコードの要素ではないので(サイロA)、一時的なテストはどのようになりますか?
エリック

2
Y2kパニックを覚えている人はいますか?2100では間違っていたため、2000年には一部のコードが正しかったのです。100年に1回、または400年に1回も発生する可能性のある問題がありました。
スティーブバーンズ

16

前述の既存の回答に加えて、複数のバージョンでコードを繰り返し削除することもできます。

初期バージョンでは、機能しているコードブロックで非推奨の警告を行うことができました。その後のバージョンでは、コードブロックを削除できますが、エラーメッセージを残して、ユーザーにこの機能を非推奨にし、使用できなくなります。最終バージョンでは、コードブロックとメッセージを削除します。

これは、エンドユーザーへの警告なしで予期しない機能を識別するのに役立つ場合があります。最良のシナリオでは、コードは実際には何もせず、発生することは、不要なコードが削除される前にいくつかのバージョンにわたって保持されることだけです。


7
+1。開発者(またはその管理者)がすべてを満たすために一度にすべてを投げ入れるのではなく、プロジェクトを2つまたは3つの安全なフェーズに分割することを望んでいれば回避できるはずの非常に多くのバグと顧客に直面する問題を見てきました次のプロジェクトに進む前の任意の期限。
-ruakh

これはタイトルで尋ねられた質問に答えますが、あなたが私に尋ねると、質問のタイトルは間違っています。タイトルはコードを削除する方法を尋ねますが、本文はコードが最初に削除しても安全かどうかを識別する方法に関するものです。前者には間違いなく答えますが、OPが本当に求めていたのかどうかはわかりません。
underscore_d

7

多くの人々は、「安全な」ことは、コードが使用されていないことを証明できない場合にコードを残すことだと提案しています。

しかし、コードは資産ではなく、負債です。

それが重要である理由を説明し、そのテストを示すことができない限り、「より安全な」代替手段はそれを削除することです。

それでもわからない場合は、少なくともゾンビコードを実行するためのテストを追加してください。


ステップ1:すべてのコードを削除します。ステップ2:必要なものを元に戻します。ステップ3:繰り返します。

1
@エイドリアンナイトキャピタルに注目してもらえますか?en.wikipedia.org/wiki/…-参照してポイントを強化したい場合に備えて。いくつかの古いコードが復活し、彼らのために5億ドル近くを親切に失ったため、彼らは基本的に破裂しました。その後の調査では、リリース手順に焦点を当てましたが、中心的な問題は「デッド機能が削除されなかった」ことでした。
スーザンW

6

機能トグルを使用して、ソフトウェアの実行パスを変更し、問題のコードを完全に無視することができます。

これにより、使用していないコードを使用して変更を安全に展開し、トグルをオフにできます。コードに関連する重大な障害に気付いた場合は、トグルをオンに戻し、コードへの可能なパスを調査してください。

このアプローチは、長期間にわたって問題が見られない場合の信頼性と、ライブw / oaデプロイメントでそれを元に戻す機能を提供します。ただし、さらに良い方法は、問題のある領域の周りに追加のロギングとテストカバレッジを適用し、使用されているかどうかの証拠を提供することです。

トグルの詳細については、https//martinfowler.com/articles/feature-toggles.htmlをご覧ください。


6

もちろん静的分析...そして、素晴らしいことは、新しいツールは必要ないということです。コンパイラには、必要な静的解析ツールがすべて備わっています。

メソッドの名前を変更DoSomethingし(例:に変更DoSomethingX)、ビルドを実行します。

ビルドが成功した場合、このメソッドは明らかに何も使用されていません。削除しても安全です。

ビルドが失敗した場合、それを呼び出すコード行を分離しif、呼び出しを囲むステートメントを確認して、呼び出し方法を決定します。トリガーとなる可能性のあるデータユースケースが見つからない場合は、安全に削除できます。

あなたはそれを削除することについては本当に心配している場合は、コードを維持するが、とそれをマーキング考えるObsoleteAttribute(またはあなたの言語で同等)。1つのバージョンのようにリリースし、問題が発見されなくなったらコードを削除します。


8
これは、完全なdynamic / lateバインディングを持たないプログラミング言語に対する大丈夫なアドバイスです。しかし、持っている人にとっては、よりトリッキーです。そして、もちろん、コードは本番環境で使用されていない場合でもメソッドを使用している場合があります。
eis

質問は、コンパイル時のシンボル解決を前提としています(したがって、余分なコードが見つかりました。コンパイラはそれを認識しません。)また、通常、遅延バインドされた関数またはオブジェクトでさえ、インターフェイスまたはマップファイルなどの2つの場所で定義されるため、ビルドは失敗します。
ジョン・ウー

1
うーん...私は興味をそそられています、あなたが言う後者は本当だとは思いません。バニラジャバスクリプト(プリコンパイルされていない)、ルビー、パイソン、スモールトークなどではありませんよね?存在しないものを参照すると、これらのエラーは実行時にのみ発生します。
eis

多分、私は論理的表現の物理的表現への解決を示す「束縛」とはどういう意味なのか、例えば住所へのシンボルに反対する。Javascript関数は、タグを含むオブジェクト内の値のペアとして格納されるため、バインディングの概念は非馬鹿げに見えます。
ジョン・ウー

1
はい、私たちは本当に同意しません。この用語は、完全な遅延バインディングを持たない言語では異なる意味を持ちます(最初のコメントで説明したように)。実行時にメソッドをバインドするとき-実行時にメソッドのランタイムを追加および削除できる言語で-あなたは私がそれを理解する方法で遅延バインディングを使用しています。これはruby / python / smalltalkスタイルの言語に当てはまり、個別のマップファイルはありません。特にルビーとpythonは非常に広く使用されているため、「通常」の意味についてはあなたの考えに同意しません。
eis

4
  • コードアナライザーを使用して、これがデッドコードかどうかを確認します
  • テストの確認を開始し、コードに到達しようとしました。テストケース内のコードに到達できない場合、デッドコードである可能性があります
  • コードを削除して、代わりに例外をスローします。1つのリリースでは例外がアクティブになり、2番目のリリースでは例外を削除できます。安全のために、顧客が例外に気付いたときに元のコードをアクティブにできるように、緊急フラグ(Javaではシステムプロパティ)を配置します。したがって、例外を無効にして、元のコードを実稼働環境でアクティブ化できます。

6
-1。これらの変更を生産的なコード、安全フラグ、またはそうでないものにすることは絶対に推奨できません。問題のコードが使用されていないこと確実な場合にのみ、生産的なコードで削除してください。そのような混乱は、異なる生産性とテスト環境が常に存在するべきである理由です。
ヨハネスハーン

3
これは、テストカバレッジがほぼ90%の場合に幻想的に機能しますが、そうでない場合は、プロジェクトに100.000行のコードが含まれています。そのため、コードのテストを試みて、コードに到達するテストがなければ...死んでいる可能性があります。
マルクスラスバーグ

私見コードを完全に削除することを十分に確信できない場合-本番環境で例外をスローするべきではありません-OPによって提案されたロギングははるかに優れた代替手段であり、同じことを達成し、顧客からの苦情に頼る代わりに診断を得ることができます
セビー

@JohannesHahn「生産コード」とは、実稼働環境で実行されるコードのことです。
jpmc26

@ jpmc26はい、もちろんです。
ヨハネスハーン

3

到達不能コードの削除

原則的な静的型付け言語では、コードが実際に到達可能かどうかを常に知っておく必要があります。それを削除し、コンパイルします。エラーがなければ到達できません。

残念ながら、すべての言語が静的に型付けされているわけではなく、すべての静的に型付けされた言語が原則化されているわけでもありません。問題が発生する可能性のあるものには、(1)リフレクションと(2)原則のないオーバーロードが含まれます。

動的言語、または精査中のコードの一部が実行時にリフレクションを介してアクセスされる可能性がある十分に強力なリフレクションを持つ言語を使用する場合、コンパイラーに頼ることはできません。そのような言語には、Python、Ruby、またはJavaが含まれます。

原則的なオーバーロードのない言語を使用している場合、オーバーロードを削除するだけで、オーバーロード解決を別のオーバーロードにサイレントに切り替えることができます。そのような言語の中には、コードの使用に関連するコンパイル時の警告/エラーをプログラムできるものがあります。そうしないと、コンパイラに頼ることができません。このような言語には、Java(使用@Deprecated)またはC ++(使用[[deprecated]]または= delete)が含まれます。

したがって、厳密な言語で作業することが非常に幸運でない限り(Rustが思い浮かびます)、コンパイラーを信頼することで、実際に足を踏み入れるかもしれません。また、残念なことにテストスイートは一般的に不完全であるため、これ以上の助けもありません。

次のセクションをキュー...


潜在的に未使用のコードを削除する

それどころか、コードが実際に参照されている、しかし、あなたは疑いの練習でそれを参照するコードの枝が取られることはありませんことを。

この場合、言語に関係なく、コードは明らかに到達可能であり、ランタイムインスツルメンテーションのみを使用できます。

過去に、私はこのようなコードを削除するのに3段階のアプローチをうまく使用しました:

  1. 実行されないことが疑われる各ブランチで、警告をログに記録します。
  2. 1サイクル後、特定のコードを入力すると例外をスロー/エラーを返します。
  3. 別のサイクルの後、コードを削除します。

サイクルとは何ですか?コードの使用サイクルです。たとえば、金融アプリケーションの場合、短い月間サイクル(月末に給与が支払われる)と長い年次サイクルが予想されます。この場合、年末の在庫に対して警告が発せられないことを確認するために少なくとも1年待つ必要があります。

うまくいけば、ほとんどのアプリケーションのサイクルが短くなります。

私は、次のステップに進むべき時期について助言する、日付とともにTODOコメントを書くことをお勧めします。カレンダーのリマインダー。


1
実際、C ++では、[[deprecated]]そのバージョンを呼び出すサイトを識別するために、疑わしいオーバーロードをマークできます。次に、それらを調べて、動作が変わるかどうかを確認できます。または、オーバーロードを次のように定義します。= deleteこの場合、他のバージョンのいずれかを使用するには、明示的に引数をキャストする必要があります。
トビースパイト

@TobySpeight:それは事実であり、良い代替案でもあります。私は中にそれを編集してみましょう。
マシューM.

「博士、これをやると痛い。」「まあそれをしないでください!」コードを管理不能にするアプローチを使用しないでください。

2

本番からコードを削除することは、家を掃除するようなものです。あなたが屋根裏部屋から物を捨てた瞬間、あなたの妻は1923年に亡くなった隣人からの偉大な祖母の3番目のthirdの帰郷の贈り物を捨てて翌日あなたを殺します。

真剣に、誰もが既に言及したさまざまなツールを使用した大まかな分析の後、および既に言及した段階的な廃止アプローチを使用した後、実際の削除が行われると会社から消えることがあることに留意してください。コードをそのままにして実行を記録し、実行のアラートが確実に確実にユーザー(または後継者と担当者)に伝達されるようにすることが不可欠です。

このアプローチに従わないと、妻に殺される可能性が高くなります。(すべての記念品のように)コードを保持する場合、ムーアの法則があなたの救助に来るという事実と、「私の靴の岩」のように感じるコードによって使用されるジャンクディスクスペースのコストで良心を休めることができます年になり、複数のウォータークーラーゴシップや廊下の奇妙な外観の中心になるリスクはありません。

PS:コメントへの応答で明確にするために..元の質問はもちろん「どうやって安全に削除するか..」です。もちろん、私の答えではバージョン管理が想定されています。貴重品を見つけるためにゴミを掘るようなものです。いかなる意味のあるボディもコードを捨てることはなく、バージョン管理はすべての開発者の厳格さの一部であるべきです。

問題は、余分なコードに関するものです。実行パスの100%が到達しないことを保証できない限り、コードが不要であることを決して知ることはできません。そして、これはこの保証が不可能に近いほど十分に大きいソフトウェアであると想定されています。そして、質問を間違って読んでいない限り、この会話のスレッド全体が関連するのは、削除されたコードが呼び出される可能性がある実稼働中の場合のみです。したがって、ランタイム/実稼働の問題があります。バージョン管理は、実稼働の失敗のために誰の背後にも保存されません。そのため、「バージョン管理」に関するコメントは、質問または私の元のポイントに関連しません。

私見、コメントは不要であり、削除の候補です。


12
バージョン管理と同等のものがあれば、妻の反対は簡単に覆されます。コードの削除についても同様です。それは殺人罪ではありません。リポジトリは決して捨てられません
JDługosz

オブジェクト指向プログラミングは、メソッドを呼び出すことができる範囲を狭めると考えられていました。それで、より簡単に理解され管理されるコードにつながるはずですよね?そうでなければ、なぜ私たちはそれをそうするのですか?

@nocomprendeこのスレッドのどこにも、議論がOOP設計/言語のみに限定されていることが示されていません。なぜあなたはそれが関連していると思うのか分かりません。
underscore_d

1

たぶん、コンパイラーはそれに気づいて、大騒ぎしません。

サイズに合わせて、完全なコンパイラ最適化でビルドを実行します。次に、疑わしいコードを削除し、ビルドを再度実行します。

バイナリを比較します。それらが同一である場合、コンパイラはコードに気づき、静かに削除しました。ソースから安全に削除できます。

バイナリが異なる場合...それは決定的ではありません。他の変更が必要になる場合があります。コンパイラの中には、コンパイルの日付と時刻をバイナリに含めるものもあります(そして、それは離れて設定できるかもしれません!)


1
すべての言語がコンパイルされているわけではなく、すべてのコンパイラが最適化されているわけではなく、すべての最適化が同等であるわけでもありません。コードが共有ライブラリ/ DLLにある場合、削除されません。
スティーブバーンズ

1
@SteveBarnesええ、そうですね。LTOを実行せず、すべてを静的にリンクしていなければ、苦痛を感じます。それは当然です。
ナビン

1

私は最近、「deleteFoo」と呼ばれるメソッドを使用して、この正確な状況に最近遭遇しました。メソッド宣言以外の文字列はコードベース全体のどこにも見つかりませんでしたが、私は賢明にもメソッドの先頭にログ行を書きました。

PHP:

public function deleteFoo()
{
    error_log("In deleteFoo()", 3, "/path/to/log");
}

コードが使用されたことがわかりました!一部のAJAXメソッドは、「method:delete、elem = Foo」を呼び出します。このメソッドは、連結されてcall_user_func_array()で呼び出されます。

疑わしい場合は、ログに記録してください!ログがいっぱいにならないまま十分な時間を過ごした場合は、コードを削除することを検討してください。ただし、コードを削除した場合でも、ログを残し、日付をコメントとして残しておくと、Gitでコミットを見つけやすくなります。


Tombstoneと呼ばれるPHPおよびPerlのライブラリ(php:github.com/scheb/tombstone)は、ここで役立つ可能性があります。
アリスターブルマン

0

grep最初に使用可能なツールを使用すると、コードへの参照が見つかる場合があります。(もともと私の指示/アドバイスではありません。)

次に、コードを削除するリスクがあるかどうか、または私の提案が使用できるようになるかどうかを決定します。

コードの関数/ブロックを変更して、ログファイルに使用されたことを書き込むことができます。そのようなメッセージがログファイルに「これまで」記録されていない場合は、おそらくログコードを削除できます。

2つの問題:

  1. 他のユーザーからログを取得します。 おそらく、終了時にプログラムをクラッシュさせるグローバルフラグを設定し、ユーザーに親切にエラーログを送信するように依頼することができます。

  2. 呼び出し元をトレースします。 一部の高レベル言語(Pythonなど)では、トレースバックを簡単に取得できます。ただし、コンパイルされた言語では、リターンアドレスをログに保存し、終了時にコアダンプを強制する必要があります(ポイント1)。
    Cでは、これは非常に単純なはずです。条件付きブロック(たとえば#ifdef ... #endif)を使用して、動作することがわかっている(そして動作することをテストした)ときにのみこれを使用し、単にリターンアドレスを読み取るスタックから(インラインアセンブリ言語が必要な場合と必要でない場合があります)。

ログファイルに引数を保存することは、役に立つ場合とできない場合があります。


0

それを取り巻くコードが何をしているのかを知っているなら、それテストして、それが壊れているかどうか確かめてください。これは、作業中のコードをリファクタリングするための最も簡単で費用対効果の高い方法であり、最初に作業中のコードに変更を加える場合は、とにかく実行する必要があります。

一方、あなたはしていないコードの一部リファクタリングしている場合は知っている、それが何を、それを削除しないでください。最初にそれを理解してから、安全であると判断した場合にリファクタリングします(リファクタリングが時間の適切な使用であると判断できる場合のみ)。

現在、「死んだ」コードが実際には何にも接続されていない状況があります(私は自分でそれに遭遇したことを知っています)。アプリが配信された直後に廃止されたために実際にどこにも実装されなかった請負業者によって開発されたコードのライブラリなど(なぜそうですか、私は具体的な例を念頭に置いています、どうやって知っていますか?)

私は個人的にこのコードのすべてを削除する羽目になるでしたが、それは巨大な私は軽く上の服用はお勧めしませんリスク-この変更は可能性がどのくらいのコードに応じて、潜在的に(あなたが何かを見落としてきた可能性が常に存在だから)、あなたに影響を与えます非常に注意して、積極的なユニットテストを実行して、この古いレガシーコードを削除してもアプリケーションが破損するかどうかを判断する必要があります。

言われていることはすべて、おそらくそのようなコードを削除しようとするのは時間や正気の価値はないでしょう。アプリケーションで深刻な問題にならない限り(たとえば、アプリケーションの肥大化のためにセキュリティスキャンを完了できない...なぜそうなのかまだ念頭に置いているので)、そうしないとお勧めできません。このような状況では、コードが本当にインパクトのある方法で腐敗し始めています。

要するに、コードが何をするのかを知っているなら、最初にテストしてください。そうでない場合は、おそらくそのままにしておくことができます。あなたが知っている場合することができないだけで、それを残して、変更を実装する前に積極的な変化をテストするためにあなたの時間を捧げます。


0

私のアプローチは、この場合常に業界標準であると想定していましたが、奇妙なことにこれまで言及されていませんでした。

2番目のペアを取得します。

さまざまな種類の「未使用のコード」があり、場合によっては削除が適切であり、他の場合はそれをリファクタリングする必要があります。あなたはそれがどれであるかを把握する必要があり、そうするためにあなたは最高の2番目とペアを組む-経験豊富です!-開発者、コードベースに精通している人。これにより、不必要なミスのリスクが大幅に削減され、必要な改善を行ってコードベースを保守可能な状態に保つことができます。そして、これを行わないと、ある時点で、コードベースに精通している開発者を使い果たしてしまいます。

ロギングアプローチも見てきました。より正確には、ロギングコードを見ました。10年の間、そこに残っていたさらに多くのデッドコードです。ロギングアプローチは、機能全体を削除する場合はかなり適切ですが、デッドコードの一部を削除するだけではありません。


0

あなたの質問に対する簡単な答えは、あなたが理解していないコードを安全に削除できないということです。多少のリスクがあります。

その避けられないリスクを軽減する最善の方法を判断する必要があります。他の人はロギングについて言及しています。ロギングは、もちろんそれが使用されていることを証明できますが、使用されていないことを証明することはできません。デッドコードの主な問題はそれが維持されることであるため、デッドコードの疑いがあるというコメントを追加することで逃げることができ、それを維持することはできないかもしれません。

コードがソース管理下にある場合は、いつコードが追加されたかをいつでも確認し、そのときの呼び出し方法を判断できます。

最終的に、あなたはそれを理解するか、そのままにしておくか、チャンスをつかむかのいずれかです。


0

問題のコードの開発者がまだ利用できる場合は、彼と一緒にコードの削除を確認してください。また、コードのコメントを読んでください

適切な説明、このコードが追加された理由、およびそれが機能する機能が表示されます。特定のユースケースを簡単にサポートすることもできますし、本当に必要でないかどうかを判断するのに十分な専門知識がない場合もあります。極端な場合、Cプログラムからすべての空きステートメントを削除し、間違ったことに気付かないことがあります(メモリ不足になるまで数分かかる場合があります)。

コードの作者があなたの隣に座っているのは本当に悪い文化ですが、彼は悪いコードを書いているだけで、あなたのものはすべて完璧なので、話す理由はありません。そしてもちろん、彼はコメントにランダムな単語を書くだけで、読書を無駄にする必要はありません。

コードにコメントを記述する最も重要な理由の1つは、この方法で実装された理由を説明することです。解決策に同意しない場合もありますが、問題を考慮する必要があります。

著者との議論はまた、コードが削除された、または終了しなかった何かの歴史的な残骸であるため、削除しても安全であることを明らかにするかもしれません。


-1

Markus Lausbergの最初のポイントに強く同意します。ツールを使用してコードを確実に分析する必要があります。類人猿の頭脳は、この種の仕事で信頼されるべきではありません!!

ほとんどの標準プログラミング言語は、IDEと、このような状況にぴったりのツールである「すべての使用法を見つける」機能を備えた、呼び出す価値のあるすべてのIDEで使用できます。(たとえば、EclipseでCtrl + Shift + G)

もちろん、静的分析ツールは完璧ではありません。問題のメソッドが呼び出されているという決定が実行時にのみ発生し、すぐに発生するより複雑な状況に注意する必要があります(Reflectionを介した呼び出し、スクリプト言語での「評価」関数の呼び出しなど)。


5
たぶん猿の脳はコードを書くべきではないのでしょうか?「人間の手で触れられていない」は、かつてマーケティングフレーズでした。私はいつもゴリラの手が仕事をしていると想像していました。

3
(猿の頭脳もツールを書いた)(シッ!あなたは物語を台無しにします!)

1
あなたは両方とも私のポイントを逃していると思います。静的コード分析がメソッドまたはクラスのすべての呼び出しを検出するという保証はないことを明確に述べました。それは、錫について述べているように、静的分析です。リフレクションやeval()などを介して動的な呼び出しを見つけることはできませんし、期待されるべきではありません。私のポイントは、静的コード分析はコードを削除するために必要な前提条件と見なされるべきであるということです。そして、大きなプロジェクトでは、人間の脳が...それを正しくやって全くおろかその分析を行うさえ可能であること、それはなりにくい
ヨハネス・ハーン

1
...静的コード分析は退屈で反復的な作業であり、コンピューターで行うのが最適です。コンピューターによって確実に実行できるが、類人猿の脳によって実行された場合に信頼性が低いことで有名なタスクの種類。後者は、コンピューターがそれらのトリッキーな反射やeval-callを見つけることのようにできないことだけに使用されるべきです。
ヨハネスハーン

1
繰り返しますが、ポイントがありません。猿の頭脳によって書かれたためにツールが完璧ではない場合でも(そして、それを認めるべきかどうかさえわかりません!静的呼び出し階層の計算はそれほど難しくありません)、それらは依然として手動タスク実行よりもはるかに優れています。これは、すべての状況またはまったく関係のない状況ではありません。99%の信頼性を備えたツールは、99%で始まる可能性がありますが、最初の1,000行のコードの後に​​ははるかに低いレートに急速に低下する脳にとってはなお望ましいです。
ヨハネスハーン

-1

2つの可能性:

  1. 99%以上のテストカバレッジがあります。コードを削除して完了です。
  2. 信頼できるテストカバレッジがない場合:答えは、非推奨の警告を追加することです。つまり、その場所に何か正気なことをするコードを追加します(たとえば、アプリケーションの日々の使用と競合しない、簡単に見える場所に警告を記録します)。その後、数ヶ月/年の間煮込みます。一度も発生したことがない場合は、非推奨を例外をスローするものに置き換えてください。しばらくそれを立てましょう。最後に、すべてを完全に削除します。

2
これは、前の17の回答で作成および説明されたポイントに対して実質的な何かを提供するようには見えません。カバレッジと非推奨の警告の両方については、すでにそこで議論されました
-gnat

@gnat、あなたは正しい。最初に答えをスキャンしたとき、なんらかの理由で、これらの2つのポイントに短時間で簡潔に到達しなかったものをいくつか見たと思った。答えの真ん中にそのようなものがあります。
-AnoE
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.