デッドコードを削除する





Ned Batchelderの投稿「Code Removal」は最近HNに登場しましたが、元々は2002年に書かれました。 ここで、私はネッドのいくつかの考えを繰り返し、ネッドよりも決定的な立場を取ります。不要な質問なしに、コードが不要になったらすぐにコードを削除します。 また、デッドコードの候補を特定する方法について、トレンチからいくつかのヒントを提供します。



それは死ぬことはありません!



これは、単に「非常に賢い」ポップカルチャーへのタイムリーな参照ではありません。 デッドコード、つまり、プログラムで決して実行されないコードは、コードベースを維持する上での本当の障害です。 この関数の隣で機能するはずのコードの複雑さに困惑していたからといって、単純な関数または改善のように見えるものを追加できなかったことが何度ありますか? 新しい機能を追加したり、バグを修正したりするのが、仕事を計画したときに思っていたほど簡単だったら、あなたの人生はどれほど楽しかったでしょうか?



変更を行うたびに、既存のすべての関数、「クランチ」、周囲のコードの既知のエラーおよび制限との相互作用を考慮する必要があります。 これは、追加するオブジェクトの周りのコードを少なくして簡単に実行できます。 そうすることで、考慮する必要のあるものが少なくなり、何かがうまくいかないオプションが少なくなります。 デッドコードは、それとの相互作用を考慮する必要があるように思われるため、特に有害ですが、デッドコードであるため、気が散る操作です。 それは決して達成されないので、あなたに利益をもたらすことはできません。



デッドコードが決して死なない可能性があるという事実は、このコードベースで作業する能力に対する真の脅威です。 最悪の場合、呼び出されないコードが削除されないと、アプリケーションのサイズは永久に大きくなります。 おそらく実際に機能している数千行のみが、何の役にも立たない多くのコードで数桁に囲まれていることに気付く前に。



彼は去らなければならない



この記事では、Ned( Starkではなく、Batchelder)が私よりも少し繊細で、巧妙でした。

メソッドがたくさんある優れたクラスがあるとします。 ある晴れた日、特定のメソッドが呼び出されなくなったことを発見します。 そのままにするか、削除しますか?



この場合、クラスとメソッドに依存するため、この質問に対する単純な答えはありません。 答えは、このメソッドが将来再び必要になると予想するかどうかによって異なります。

出所


私はこれを言います:地球を燃やし、コードを生きたままにしないでください。 あなたがコードを持っていない最高のコード。



あなたが私ほど勇敢でないなら、このコードが再び必要になった場合に備えてバージョン管理システムがあなたをカバーすることを覚えておいてください。



ただし、少なくとも削除したコードのセクションを逐語的に逐語的に返さずに、すでに削除したものを返す必要性を感じたことはありませんでした。



もちろん、私は誤ったコミットを返すようなことについて話しているのではありません-私たちは皆人であり、私は他の人と同じくらい多くの間違いをします。 つまり、実稼働環境に送信されたオブジェクトを削除したことはなく、数週間または数か月後にそれらを返しました。「1年以上前に書いたコードは非常に良かったので、彼を取り戻させてください。 コードベースは長期にわたって存続し、開発されるため、古いコードは、現在使用されている新しいアイデア、手法、フレームワーク、スタイルに適合しない可能性があります。 特にこれらが微妙な点である場合、更新のために古いバージョンに戻ることができましたが、コードを大量に戻すことはありませんでした。



それで、あなた自身とあなたのチームを助けて、気づいたらすぐに死んだコードを削除してください。



どうやってここに来たの?



Nedの投稿では、「デッド」コードが発生する方法と理由を詳細に説明しています。おそらく、変更を行った人は、コードが永久に消えてコメントを付けたり、条件付きコンパイルを追加すべきだとは思わないでしょう。 おそらく、変更を行う人は、コードが実際に死んでいることを理解するのに十分な知識を持っていません(これについては後で説明します)。



リストにもう1つの仮説を追加します。私たちはみんな怠け者になります。 もちろん、何かをする(削除する)よりも、何かをしない(つまり、そのままにする)方が簡単です。



結局のところ、怠azine はプログラマーの3つの大きな美徳の 1つです。 しかし、 ラリーウォールが語る怠は別の種類のものです。「全体的なエネルギーコストを下げるためにより多くのことをせざるを得ない品質」。 この観点から、デッドコードを削除するのは大文字のLの怠azineです-将来複雑なことをする必要から自分を守るために今やることが簡単なことをすることです。 私たちは皆、そのような怠inessを育てようとするべきです。 私は彼女を私たちの毎日の習慣である「規律ある怠」と考えるのが好きです。



どうやってここから出るの?



私はほとんどの時間をPythonでプログラミングしていますが、残念ながらIDEは通常、完全なコードベースを正しく解析できず、呼び出されないコードを自動的に見つけることができません。 しかし、規律と実行時にプログラムを分析するためのツール(実行時ツール)を組み合わせることで、この問題に2つの側面からアプローチできます。



単純なケースでは、コードのセンスが良いため、変更中にデッドコードを特定して削除できます。 特定の関数で作業している場合、if / elseブランチのいずれかを実行できないことに注意してください。 私はそれを「小さなコードのデッドコード」と呼んでいます。 *見つけて削除するのは非常に簡単ですが、あなたが費やすことができるよりも少し手間がかかります。



通常のすべての通常の作業中にこれに気付く習慣を身に付けるまで、コミットする前に実行するアクションにもう1つのステップを追加できます。変更の横にデッドコードがあるかどうかを確認します。 これは、同僚にコードを送信する直前に発生する可能性があります( コードレビューを行いますよね?)。したがって、変更を確認しながらこのプロセスを繰り返す必要はありません。



別の種類のデッドコードは、そのクラスまたは関数を使用する最後のコードを削除するとき、これがそれを使用する最後の場所であることを認識せずに変更するときに表示されます。 これは「大規模なデッドコード」 *であり、 理想的なメモリ確保できる幸運がないか、手の甲のようなコードベースを知らない限り、通常のプログラミング中に検出するのは困難です。



そのとき、実行時にプログラムを分析するツールが役立ちます。 Magneticでは 、Nedパッケージ(はい、同じNed)のcoverage.pyを使用して、デッドコードに関する決定を支援します。 通常、カバレッジは、テストケースがテスト対象のコードを正しく実行することを保証するためにテスト中に使用されますが、使用されるものとされないものを理解するために「通常どおりに動作する」コードでも使用されます:

import coverage cov = coverage.Coverage( data_file="/path/to/my_program.coverage", auto_data=True, cover_pylib=False, branch=True, source=["/path/to/my/program"], ) cov.start() # ...  - ... cov.stop() cov.save()
      
      





これにより、レポートをより便利にするための複数のオプションを持つCoverageオブジェクトが作成されます。 まず、データを保存する場所を指定し(後で使用して、使用しないものと使用しないものに関する便利なHTMLレポートを作成します)、auto_data = Trueを使用して自動的に開いてこのファイルに追加するように依頼します。 さらに、標準ライブラリとインストールされたパッケージの処理について心配しないでください-これは私たちのコードではないので、含まれているものの多くは私たちによって使用されない可能性があると仮定できます。 これはサポートが必要なデッドコードではないため、無視しても問題ありません。 分岐カバレッジを計算するように依頼します(各ifステートメントでtrueとfalseの両方がtrueであるかどうか)。 そして最後に、ソースがどこにあるかを示します。そうすることで、ソースコードで使用されているものと使用されていないものに関する知識を組み合わせてレポートをコンパイルできます。



プログラムを開始した後、HTMLレポートを作成できます。

 $ COVERAGE_FILE=/path/to/my_program.coverage coverage html -d /path/to/output
      
      





これは次のようになります。



HTMLレポートの完全な例は coverage.pyドキュメントにあります



赤で強調表示された行は、プログラムの実行中に呼び出されませんでした。 これらの行(および場合によってはメソッド)は、デッドコードとしての削除の候補です。



このアプローチを使用してデッドコードを見つけて削除することについて、3つの警告を残します。

  1. カバレッジの結果を考慮するときは注意してください。プログラムの1回の実行中に行または関数が実行されなかったという事実は、それらが必ずしも死んでいるかアクセスできないという意味ではありません。 それでもコードをチェックして、アプリケーションで本当に死んでいるかどうかを判断する必要があります。
  2. カバレッジの計算は、プログラムがより多くの作業を行う必要があることを意味するため、このモードでの実行は遅くなります。 これを実稼働環境で実行することはお勧めしませんが、ステージング環境またはターゲットスクリプトではすべて問題ありません。 いつものように、パフォーマンスが重要なタスクである場合は、実行する前にカバレッジ計算の影響を正確に測定する必要があります。
  3. 最後に、テスト実行中にコードカバレッジレポートを信頼しないでください。 一部のコードは無効になっている可能性がありますが、テストでは引き続き実行されます。 そして、いくつかのコードは生きているかもしれませんが、テストによって実行されません!




さよならの言葉



親愛なる読者、私はあなたに謝罪しなければなりません。 ネッドの以前の引用で、ネッドの投稿の重要な部分を省略しました。

彼は言う:

この場合、クラスとメソッドに依存するため、この質問に対する単純な答えはありません。 [...]大まかな答えは次のとおりです。このクラスがフレームワークの一部である場合、それをそのままにして、アプリケーションの一部である場合、それを削除します。


アプリケーションではなくライブラリまたはフレームワークを作成している場合、デッドコードの問題は一方ではより複雑になり、他方ではより簡単になります。 本質的に、パブリックAPIの一部を削除することはできません( メジャーバージョンの非互換性を除く)。 実際、自分で使用しなくても、公開API全体はライブコードです。 ただし、外部インターフェイスの背後では、デッドコードが発生する可能性があるため、削除する必要があります。



デッドコードを削除してください!






* -「小さなプログラミング」と「大きなプログラミング」 のプログラミングパラダイム参照(約Transl。)



All Articles