デバッグに時間がかかりすぎている


24

昨日、約6週間(オンとオフ、つまり)作業してきたWebプロジェクトのv1.0リリースを公開しました。私は自分の時間を正確に記録していませんが、私の経験によると、プログラミングに費やした時間のうち、半分がデバッグに費やされたと推定します。デバッグに15〜20時間ほど費やしていると推定します。これは、新しいコードの作成やプロジェクトの早期終了に費やすことができた貴重な時間です。また、5週間以内に大学1年生になることも特に助けになりません。

大事なことは、デバッグに時間を費やすのは気分が悪いことです。デバッグに費やしたすべての時間は、プロジェクトの開発中にかなりバカなミスを犯したことを実感させてくれます。ミスは修正にかなりの時間を要しました。

将来これが起こらないようにするにはどうすればよいですか?デバッグに50%の時間を費やしたくはありません。10%のデバッグに費やし、残りは新しいコードの作成に費やします。この目標を達成するのに役立つテクニックは何ですか?


22
私が新入生だったとき、私も遅いコーダーでした。ちょうど20年を与えます。
仕事

27
うーん、それで幸運。「デバッグがバグを削除するプロセスである場合、プログラミングはバグを入れるプロセスでなければなりません。」
マット

7
それらの間違いから何かを学びましたか?行った場合、次回はそれらを作成せず、これによりデバッグ時間が短縮されます。
クレイグT

5
これは「経験」と呼ばれ、次のプロジェクトで役立ちます。

4
1940年代後半と言えば、モーリス・ウィルクスは次のように書いています。「プログラミングを開始するとすぐに、思ったよりもプログラムを適切に取得するのが簡単ではないことに驚きました。デバッグを発見する必要がありました。 EDSACの部屋と「階段の角度でatする」パンチング機器との間の私の旅は、私の人生の残りの部分が自分のプログラムのエラーを見つけることに費やされることに全力で私を襲いました。」
トレバーパウエル

回答:


35

あなたはソフトウェア工学の聖杯を求めていますが、この質問に対する「その」答えはまだありません。

不可欠なのは、作成しているエラーの種類を追跡し、それらのエラーの分析を行って、共通の傾向があるかどうかを判断することです。根本原因分析は、このタイプの内観の正式な名前であり、それに関する多くの資料がウェブ上にあります。

専門家はバグ追跡システムを使用して、(1)何を修正する必要があるかを知るだけでなく、(2)事後に修正する必要があるものを分析することもできます。あなたはそれほど正式である必要はありません-ノートブックに集計を保持するだけでいいかもしれません。

設計段階の欠陥

ほとんどのエラーが問題ステートメントの誤解に起因している場合、または問題を解決するために間違ったアルゴリズムまたはパスを選択し続けていることに気付いた場合、設計段階で問題が発生します。

プロジェクトの最初により多くの時間をかけ、何をする必要があり、どのようにそれを行うべきかを正確に書き出すことは、あなたにとって重要なことです。この作業を慎重に検討し、元の問題を再検討して、本当に正しい方法で取り組んでいるかどうかを判断してください。開始時に1時間または3時間余分に時間をかけると、道を何時間も節約できます。

コーディングエラー

デザインがしっかりしているが、コーディングしている言語と常に戦っている場合は、コードを分析して、間違いを犯していることを早期に警告するツールを入手してください。

Cでプログラミングしている場合は、すべてのコンパイラ警告をオンにしlint、などのセマンティックチェッカーを使用し、同様のツールを使用して、valgrind一般的なダイナミックメモリ関連の問題をキャッチします。

Perlをプログラミングしている場合は、電源を入れてstrictwarningsそれが言っていることに注意してください。

使用している言語に関係なく、デバッグ段階に到達するずっと前に、よくある間違いを見つけるのに役立つ多くのツールが存在する可能性があります。

統合段階の欠陥

優れたモジュール方式のプラクティスに従ってコードを開発するとき、別々の部分を一緒に接着し始める必要があります。たとえば、コードのさまざまなセクションは、ユーザー入力、データベースインタラクション、データ表示、アルゴリズム/ロジックに関連している可能性があり、これらはそれぞれ比較的独立して構築されています(つまり、手元のセクションに集中する傾向があります)他のすべてとの統合を心配するのではなく)。

ここで、テスト駆動開発(TDD)が非常に役立ちます。コードの各モジュールには、それらが設計された方法に従って機能することを検証するテストを含めることができます。これらのテストは、プロセスの最初または非常に早い段階で作成する必要があります。これにより、正直な状態を保つための一連の "ヘルパー"を確保できます。すべてを連携させ始め、これまたは別のサブシステムとの実装または相互作用の方法を変更する必要がある場合、テストにフォールバックして、作成したことを確認できますすべて一緒に機能しても、コードの正確性が損なわれることはありません。

等々...

ソフトウェアエンジニアリングと実用的なコーディングテクニックに関する本をいくつか取り上げれば、開発の混乱を減らし、信頼性を高めるさまざまな方法を学ぶことができます。また、単純な古い経験-ハードノックの学校で学位を取得-があなたを形にすることにも気付くでしょう。

ほとんどすべてが要約すると、少しの時間と作業を前もって行うことで、開発/リリースプロセスの後半で莫大な利益が得られます。

キャリアの早い段階でこれらの問題に気付いたという事実は、あなたの将来にとって良いことであり、幸運を祈ります。


1
これは素晴らしい答えですが、わずかに異なる質問に対する私見です。OPは、私が何かを書くのに6週間を費やし、デバッグに多くの時間を費やさなければならないと言っています。たとえば、彼の製品の品質、保守性、拡張性などはまだ何もわかっていません。TDD、優れた設計、バグ追跡を想定する場合、欠陥の少ないコード(デバッグも必要なテストコードを含む)をどのように記述するかという問題があります。警告をオンにしたり、リントを使用したりすることなどをお勧めします。ハードノックの学校からのそれらの多く?:-)
ガイサートン

1
@Guy-うん... OPの質問は少し曖昧だったので、根本原因分析に重点を置いて行った。何が問題なのかを知るまで、何が問題なのかわかりません。問題領域の調査を行った理由は、多くの潜在的な落とし穴を認識してもらい、プロセスの各段階で独自の調査を行う必要があるためです。私が知っている限り、彼は次のトニー・ホアであるかもしれませんが、盲目の象のタイピングスキルを持つ人です-さまざまな原因に対するさまざまな修正。
-unpythonic

37

単体テストを書く

コードの単体テストを書くと、アーキテクチャについて考えるようになり、慎重に制御可能なテスト可能な小さなピースでコードを書くように促されます。これにより、デバッグの労力が大幅に削減され、実行する少量のデバッグは、コードの小さな、厳密に焦点を絞った部分に限定されます。

さらに、作成するテストはコードを「カバー」します。既存のテストの1つまたは複数が失敗するため、コードに加えた変更が何かを壊したときを知ることができます。これにより、デバッグ作業の全体的な複雑さが軽減され、コードが機能するという自信が高まります。

もちろん、デバッグに費やした時間はテストの作成に費やされているということです。 しかし、それらを一度書くだけでよく、それらを書いた後、必要な回数だけ実行することができます。


ユニットテストの+1-開発プロセスの早い段階でバグが発見されると、より安く簡単にバグを修正できます。
ポールR

26

(広義の)デバッグの50%はそれほど悪くはありません。通常、実際のコードを書くよりも、設計、テスト、バグ修正、リファクタリング、単体テストの記述に多くの時間を費やします。それは仕事の一部です。

正直なところ、メンテナンスプログラミングの方がはるかに悪いです-正確に何が問題なのかを把握するのに1時間を費やし、それを修正するためのコードを5分間書いてから、全体を30分テストします。これは、5%を超えるコーディングと、ほぼ95%の非コーディングです。

ただし、デバッグ時間を短縮するためにできることがいくつかあります。

  • デバッグ可能なコードを記述します。これは、適切なエラー処理(いくつかの考えを入れて)、コードを構造化して追跡しやすくすること、アサート、トレース、およびデバッガーの生活を楽にする他の方法を使用することを意味します。複雑な線を避けます。複数のことを行う行は、個別にステップスルーできるように分割する必要があります。
  • テスト可能なコードを記述します。コードを単純な関数(または選択した言語がサポートするその他のもの)に分割します。副作用はユニットテストでキャプチャするのが難しいため、避けてください。分離して実行できるように関数を設計します。多目的機能を避けてください。エッジケースを避けてください。あなたの関数が何をすべきかを文書化してください。
  • テストを書きます。単体テストがあるということは、関数が入力の少なくともサブセットに対して機能することを知っていることを意味します。また、変更が何も壊さないことを確認するための健全性チェックがあることも意味します。コードカバレッジと入力カバレッジの概念、および単体テストの制限を必ず理解してください。
  • 「ワークベンチ」をセットアップします。これを正確に行う方法は、問題の言語によって異なります。PythonやHaskellなどの一部の言語には、インタラクティブインタープリターが付属しており、既存のコードを読み込んで再生できます。最小限の労力で好きなコンテキストで関数を呼び出すことができるため、これは完璧です-バグを見つけて分離するための非常に貴重なツールです。他の言語にはこのような贅沢はありません。また、インタラクティブなテストプログラムをほとんど書く必要はありません。
  • 読み取り可能なコードを記述します。あなたの意図をできるだけ明確に表現するコードを書くことを習慣にしてください。完全に明らかではないすべてを文書化します。
  • 簡単なコードを書きます。あなた自身の脳がコードベース全体を理解するのに苦労している場合、それは簡単ではなく、他の誰かがそれを完全に理解できる可能性は非常に低いです。コードの実行内容を理解しないと、コードを効果的にデバッグできません。
  • [削除]ボタンを簡単にします。不要なコードは今はゴミ箱に入っています。後で必要になった場合は、ソース管理から復活させます(経験上、これは非常にまれです)。処理するコードが多いほど、デバッグの対象は小さくなります。
  • 早期かつ頻繁にリファクタリングします。リファクタリングを行わないと、新しい機能を追加する際にコードをデバッグ可能な状態に保つことはできません。

1
また、問題が発生した場合、世界は予想と異なる動作をする場合があります。これにより、非常に微妙なバグが発生する場合があります。

2
+1。特に、確立されたコードベースだけでなく、デバッグ作業に50%しか費やさないと思います。バグが割り当てられている場合、コードの関連部分をほとんど完全に書き直す必要がない限り(ほとんどありません)、何が間違っているのかを考えて修正をテストするだけで、合計時間のその部分よりはるかに長い時間を費やす可能性があります。修正自体はしばしば迅速であり、多くの場合、変更されたコードは1行または数行に過ぎません。
CVn

@ThorbjørnRavnAndersenHellはい、特にOPの言及のようなWebプロジェクトではそうです。今週は仕事中に文字エンコーディングで素晴らしい時間を過ごしています
...-Izkata

5

より多くの計画

デバッグにかなりの時間を費やすことは避けられません。10%はかなり野心的な目標です。デバッグと開発に費やす時間を削減する最善の方法の1つは、計画段階により多くの時間を費やすことです。

これは、ダイアグラムから、計画パッド上の擬似コードまでさまざまです。いずれにせよ、開発中にこれらの間違いを犯すのではなく、あなたが計画していることをじっくりと考える時間があるでしょう。


1
+1これはデバッグ時間を短縮するために私がすることだからです。新しいプロジェクトを開始するとき、私はこれからすることをすべてコメントに書き、コメントに戻ってコードに置き換えます
-CamelBlues

コメントでも同じことをします。それで、中断した場所を忘れないようにしています。しかし、私は紙にクラス図を描くこととその依存関係が好きです。これは、私が当時何を考えていたかについての良い洞察を与えてくれます。
ブライアンハリントン

5

もっと注意深く働く

これは、「1度2回切断する」と同等のソフトウェアです。

  • 気が散ったり疲れたりしている場合はコーディングしないでください。
  • クリーンでエレガントなソリューションが得られるように、問題について十分な時間をかけて考えてください。単純なソリューションでは問題が発生する可能性は低くなります。
  • タスクにすべての注意を払ってください。フォーカス。
  • コーディング後すぐにコードを読んで、間違いを見つけてください。自己コードレビュー。
  • コーディングとテストの間に長く待たないでください。改善には即時のフィードバックが重要です。
  • 一般的にエラーにつながることは避けてください。コードの匂いを読んでください。
  • ジョブに適したツールを選択してください。

つまり、欠陥を完全に排除するものは何もありません。これを人生の事実として受け入れる必要があります。この事実計画の欠陥、たとえば単体テストを考えてみましょう。また、これを「永遠に取る」ことを意味しないでください(別名分析-麻痺)。バランスを見つけることです。


4

他の答えは、私が言いたいことのほとんどをすでにカバーしましたが、とにかく、私はまだ(正直に)意見を述べたいと思います:

基本的に、重要なソフトウェア作業の場合、圧倒的多数の時間をメンテナンスとデバッグに費やすことを期待してください。 成熟した実稼働ソフトウェアシステムで作業していて、メンテナンスとデバッグに費やす時間が80〜90%未満の場合、うまくいっています。

明らかに、「保守」と「デバッグ」の区別は少し主観的です。「バグ」は、リリースされてユーザーが不満を言った後に発見されたコードの問題であるとのみ考えていますか?または、何かを追加するとコードに問題が発生するのは、ごくわずかなことですか(独自のプレリリーステストフェーズで見つかりました)?自明ではないソフトウェアシステムでは(使用パターンに応じて)、一方が他方よりもはるかに大きくなる可能性があります。しかし、いずれにせよ、これはおもちゃの「Hello world」プログラムよりも大きなプログラミングが必要とするものです-たくさんのメンテナンスとデバッグ。一部の人々は、コードの最初の行以降はすべて「メンテナンスモード」であることが期待されるはずです」と言っています。

TL; DR:自明ではないソフトウェアシステムのプログラミングが何であるかについて、少し非現実的なイメージを持っているように思えます。努力の大部分は、微調整、メンテナンス、リファクタリング、バグの修正、および一般的に「デバッグ」(メンテナンス)の対象となるもの-少なくとも非常に一般的な意味では-まったく新しい作業とは対照的です。新しいコードを書く。


2

何をしているのか、どの技術を使用しているのかについての具体的な詳細なしに、特定の技術を提供することは困難です。しかし、本当に優秀なコーダーでさえ、テストとデバッグに多くの時間を費やしています。

多くのバグのない良いコードを書くことの多くは経験です。あなたは間違いを犯し、それからあなたはそれを修正し、そして間違いが何であったかを思い出し、そしてあなたが正しいことをするために代わりに何をしなければならなかったかを思い出します。そして、まだ大学に通っておらず、間違いを減らす方法について真剣に考え始めているなら、間違いなくあなたはゲームの先を行っていると思います。


1
自分の過ちから学ばない(または彼らが学んだことを覚えようとするのをわざわざする)私が見る人々を驚かせます。そして、何かが彼らの顔に大きな方法で爆発した直後、彼らは振り向いて、次のプロジェクトでまったく同じことをします。
HLGEM

2

継続的統合(CI)が答えです。

継続的統合=構成管理システム(つまり、Git、Mercurial、SVNなど)+ CIツール+ユニットテスト+煙テスト

その式は、継続的インテグレーション(CI)の詳細を読むよう促すはずです。以下は、この分野のリソースです。


1

実際、デバッグを減らすために、より詳細に計画することにより、デバッグをフロントロードできます。まだ大学に行ったことがありませんか?大学の授業の後半から後半にかけて、ソフトウェア開発のライフサイクルの詳細をカバーし、あなたの愚痴に光を当てることができると思います。

雇用主に説明しようとしていますが、コードのメンテナンスと技術サポートを削減する最善の方法は、コードを事前に包括的に計画する時間を費やすことです。


1

テスト駆動開発は、次の方法でデバッグ時間を短縮できます。

  • 多数の小規模で集中的なテストがあるということは、1つが失敗しても、問題を引き起こす可能性のあるコードはごくわずかであることを意味します。
  • 小さなステップで(失敗したテストを記述して合格することで)作業することは、一度に1つのタスクに集中できることを意味します。つまり、現在のテストを過去のものにします。
  • テストパスを行った後のリファクタリングは、コードを明確かつわかりやすいものにすることをお勧めします。問題が発生した場合に簡単に追跡できるようにします。

TDDを使用する場合でも、デバッガーを使用する必要がある場合があります。これが発生した場合は、デバッグセッションの原因となったシナリオを再現する単体テストを作成する必要があります。これにより、その問題が再び発生した場合、テストが失敗するとすぐにキャッチされ、テストは問題の原因となったコード領域のマーカーとして機能し、デバッグの必要性を減らします。


1

プログラミングではデバッグは避けられませんが、ここで重要なのは、コードをデバッグするのは簡単かどうかです。単純なものをデバッグするためだけに時間を費やす必要がある場合は、コードアーキテクチャに本当に問題があるはずです。

きれいなコードを書くことに慣れ、コードのコピーペーストや長いメソッドの作成などの悪い習慣を取り除く必要があります。

また、コードを時々リファクタリングする必要があります。Martin Fowlerの本:Refactoring:Improving the Design of Existing Codeを読むことをお勧めします


1

他の人はテストとコードレビューに言及しています。これらは両方とも非常に便利ですが、重要な違いがあります-いつ実行するのが最適か。テストはコードを最初に書いたのとほぼ同じ場所で行うのが最善です。そのため、特定の方法で何かをした理由をより簡単に思い出すことができ、テストに失敗したときに問題をより迅速に特定できます。一方、コードレビューは、少し後でより適切に実行されます。考えたことを覚えているが、入れなかった詳細を把握しないように、完全に思い出すことなくコードを確認する必要があります。コードが明確でない場所を認識したい場合。あなたは、コードが何をしているのかを理解しなければならない少し余分な労力が必要です。問題または他のコードまたは新しいテクニックとの相互作用について獲得した新しい知識を適用できるようにしたい。基本的に、

ただし、これらはすべてあなたの質問にまだ関係しています。デバッグに費やす時間を短縮するには、最初にデバッグする必要がある理由を理解する必要があります。問題を誤解し、ツールとテクノロジーの知識が不完全であり、「実際のデータがサンプルデータと一致しなかった」タイプの問題に遭遇することは、さまざまな形で現れ、回避するためにはさまざまな手法と実践が必要です。将来は。

最後のポイントは経験です。これを取得する簡単な方法はありません。時間を入れるだけです。経験を積むにつれて、最初からより適切なコードを記述し、問題に早く気づき、問題の原因が何であるかについてより良い直観を開発するため、デバッグに費やす時間が少なくなります。それを維持し、あなたはこれをあなたのキャリアにわたって着実に成長させます。


0

上記の素晴らしい答えですが、誰も直接言及していません(ただし、これについて最も示唆されています):

読む読む読む読む読む吐き気...

知れば知るほど、分からなくなる。少し決まり文句ですが、それでも基本的な真実です。

上記のヒントに従い、バグを分析的に文書化したら、それらを分類し、関連する文献を読んでください。

それは設計上の決定の問題でしたか?デザインパターンを読んでください。

それはフレームワークまたは言語の知識の欠如でしたか?それで骨が折れます!

(ライブ)開発者が決して逃れることのできない2つのことがあります:変更(ITで唯一の定数)とRTFMing ...


0

単体テストとアサート

可能な場合は、コードを個別にテストできる小さな断片に分解します。ただし、これは常に実用的とは限りません。機能の一部は、非常に複雑な入力に依存しています。画面に物を描くなど、自動化された方法では簡単に検証できないものを実行する人もいます。非決定性が関与する場合などがあります。

優れた単体テストを作成できない場合、次善の策はアサートです。ユニットテストでは、事前に決められた入力で正しい答えが得られるかどうかを確認しますが、アサートでは、実際の入力での中間ステップの健全性を確認します。コードにバグがある場合、あいまいなエラーメッセージで問題から遠く離れるのではなく、問題の根本に近い、明確なエラーメッセージですぐに失敗します。さらに、ドキュメントの前提を表明し、コードを読みやすくします。


0

プロジェクトを開始するとき、いくつの代替アプローチを特定しますか?

それぞれに長所と短所がある、2から4つの異なるアプローチがありますか?次に、それらの中から合理的な選択をしますか?

次に、最も重要なことは、シンプルさを非常に重要だと考えていますか?

私が尋ねる理由は、私の経験では、コード量、したがってバグの数(パフォーマンスは言うまでもありません)が、設計アプローチごとに1桁以上異なる可能性があるためです。経験豊富な人々がやっているのは、必要以上のコードを使わずに仕事を終わらせることです。

彼らは、完全に有能で、すべてのデータ構造アルゴリズムを認識しているオブジェクト指向言語の特徴などが、そのコードのルックスそうでないかのように、彼らはそれらのものを使用しているため、控えめに問題がない場合は、すべてではない、またはそれらを必要としません。


0

バグを修正するたびに、同じ間違いを二度としないようにします。そのためには、次のことができます。

  • 以下を含む欠陥記録ログ記録します

    • 欠陥タイプ
    • 欠陥が注入された段階
    • 削除されたフェーズ
    • 修正時間
    • 問題の説明と修正
  • スタイルガイドを採用して、記述するコードのスタイルを正規化します

  • 安全なコーディングルールをコードレビュープロセスに統合する

  • 制御フローデータを視覚化する

参照資料

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