web-dev-qa-db-ja.com

ソフトウェアの欠陥に関する調査

に章があります。「ソフトウェアの作成:何が実際に機能し、なぜそれを信じるのか」By Andy Oram and Greg Wilson aboutソフトウェアの欠陥、およびそれらを予測するために使用できるメトリック。

要約すると(私が覚えていることから)、彼らはオープンソースであり、公開された欠陥追跡履歴を持つCコードベースを使用していると説明しました。彼らは、よく知られたさまざまなメトリックを使用して、欠陥の存在を予測するのに最適なものを確認しました。彼らが始めた最初のメトリックは、コード行(コメントを差し引いたもの)でした。これは、欠陥との相関関係を示しています(つまり、LOCが増加すると欠陥も増加します)。他のさまざまな指標についても同じことを行い(頭の中で何を覚えていないか)、最終的には、より複雑な指標は単純なLOCカウントよりも欠陥を予測することにはそれほど優れていないと結論付けました。

これから、冗長性の低い言語(動的言語?)を選択すると、コード行が少なくなり、欠陥が少なくなると推測するのは簡単です。しかし、「ソフトウェアの作成」の調査では、言語選択が欠陥または欠陥のクラスに及ぼす影響については説明されていません。たとえば、Javaプログラムはclojure(またはscala、groovy、...など)で書き直すことができ、LOCを10倍以上節約できます。さらに、それ。

しかし、簡潔な言語は冗長ではありませんが、(より冗長な言語に比べて)プログラマーエラーが発生しやすくなる可能性はありますか?または、冗長性の低い言語で記述された欠陥を見つけて修正するのが10倍難しいのでしょうか。 「ソフトウェアの作成」の調査は順調なスタートでしたが、それ以上のことを望んでいました。このトピックについて何か公開されていますか?

7
Kevin

私が見つけた唯一の興味深い論文は JavaおよびC++)の観察されたバグと生産性の比率の比較 (ACMメンバーシップが必要)で、1999年に発行されました。生産性と欠陥情報を収集するためのソフトウェアプロセス。著者は、C++プログラムに含まれる欠陥が2 = 3倍多いことを発見しましたJavaプログラム、C++は1行あたり15〜30%多くの欠陥を生成し、= Javaは、時間の経過とともに生成されたコード行で30〜200%生産性が向上しました。1人のプログラマのみが使用され、この個人はC++を経験しましたが、Javaを習得しただけなので、決定的ではなく、経験豊富なJavaプログラマはより熟練しているでしょう。しかし、この研究はプログラミング言語の生産性を測定するための方法論を提供するので注目に値します。

私はいくつかの可能性のある問題を指摘したいと思います...

コードの行は、せいぜい不安定な測定です。さまざまなツールを使用してカウントするのは簡単です。これらのツールには、組織のコーディングスタイルに最適なカウントを取得できるように構成可能なルールが含まれていることがよくあります。ただし、Pythonの行はCの行と同じではありません。Pythonの行では、Cの行よりも多くのことができます。 。

彼らがソフトウェアの作成で説明するメトリック、欠陥/ SLOCは、欠陥密度と呼ばれます。これはかなり一般的なメトリックですが、SLOCに基づいているため、SLOCベースのメトリックと同じ問題が発生します。標準化されたカウント方法を使用し、これを一貫して使用する必要があります。また、プログラミング言語間での欠陥密度と値を簡単に比較することもできません。

また、単にプログラミング言語を比較することは、必ずしも公平な比較ではありません。また、利用可能なツールとリソースを比較する必要もあります。たとえば、静的分析とコードレビューを使用すると、欠陥を減らすことができます。言語によって、静的分析、単体テストのサポートが異なり、コードのレビューを実施するのに十分な言語に精通した人にアクセスできない場合があります。

結局のところ、冗長性と欠陥について話すのは間違っていると思います。製品の許容レベルまで欠陥を減らすための手法とプロセスを検討することをお勧めします。これには、チームに与えられた生産性とサポートツールに関するプログラミング言語の選択が含まれます。

7
Thomas Owens

そこには興味深いものがあります。これらは経験的なデータを含み、バグに関するAccepted Dogmaと常に一致するとは限らないため、これらは私のお気に入りです。

4
Bruce Ediger

一部の言語では、プログラマーに実装の一部を提供するため、プログラムが短くなっています。コーダーが何かを実装する必要がない場合、コーダーは欠陥をうまく導入できません。 Cでハッシュマップを実装するとしたら、おそらく間違いや欠陥があるでしょう。 Pythonでは、私はすでにハッシュマップを持っているのでそうしません。

他の言語は、プログラマが同じプログラムを取得するために書き込むテキストを少なくできるため、より短くなっています。 C++を比較します。

for(int x = 0;x < 10;x++)
{
    std::cout << x << std::endl;
}

とPython:

for x in range(10):
    print x

pythonはC++よりも文字数が少ないという単純な例でも確認できます。ただし、入力する必要がある文字数ではなく、取得できるものの数pythonは、C++バージョンの場合よりも間違いを少なくすることができます。

他の条件はすべて同じで、簡潔にするほどバグが少なくなると思います。なぜなら、バグが少なくなるからです。しかし、他のすべては等しくないかもしれません。冗長性は他の理由で役立つ可能性があり、それ自体は採算が取れます。

3
Winston Ewert

これから、冗長性の低い言語(動的言語?)を選択すると、コード行が少なくなり、欠陥が少なくなると推測するのは簡単です。しかし、「ソフトウェアの作成」の調査では、言語の選択が欠陥や欠陥のクラスに及ぼす影響については触れられていませんでした。たとえば、Javaプログラムはclojure(またはscala、groovy、...など)で書き直すことができ、LOCを10倍以上節約できます。さらに、それ。

no no no:-) Cコードのより多くの行がより多くの欠陥と相関しているという事実から、より表現力のある言語よりも推論する方法はありません同じ問題の欠陥が少なくなります。 1つ目は、特定の開発者にとって、ある言語が与えられた場合に、簡単なことです。コードの行数が増えると、バグも増えます。

しかし、簡潔な言語は冗長ではありませんが、(より冗長な言語に比べて)プログラマーエラーが発生しやすくなる可能性はありますか?または、冗長性の低い言語で記述された欠陥を見つけて修正するのが10倍難しいのでしょうか。 「Making Software」の研究はすばらしいスタートでしたが、それでも私はもっと欲しくなりました。このトピックについて何か公開されていますか?

それは間違いなく可能です。たぶんそれは読みにくくなりますか?多分それは覚えにくいと混乱しやすい関数名と演算子を持っていますか? Cを取り、printf()をp()に、sin()をs()に、cosをc()に名前変更します。短いコードでしょ?

この種のものを研究することは非常にトリッキーです。制御する必要があるすべての変数について考えます。経験、プロジェクトの規模、アプリケーション領域、言語、環境、管理。たぶんこれは数値分析には有効ですが、Web開発には有効ではありませんか?学生には表示できるが、上級開発者には表示できないのではないでしょうか。おそらくそれは、オフィスではなくオープンスペースに座っている開発者に当てはまりますか?多分それはアメリカ人には当てはまるが日本人には当てはまらないのでしょうか?多分それはオープンソースには当てはまるが商業開発者には当てはまらないのでしょうか?

プログラミング言語の生産性に関する多くの研究があります。例:

Haskell対Ada対C++対awk対...ソフトウェアプロトタイピングの生産性の実験

人々がエイダを求めていた当時、欠陥率と生産性の面でどれほど優れているかを示すいくつかの研究がありました。 Adaは、欠陥をなくすことを目的とした言語の例です。

この質問は、このブログ投稿を思い出します ヒューム、因果関係、科学

私の提案は、youがあなたの強みとアプリケーション領域。何をすべきかを教えるために研究を探すのではなく、研究はいくつかの良いアイデアを与えることができますが、これらの研究の限界を理解する必要があります。

ここに個人的な観察があります:あなたはあなたの欠陥率を下げるためにあなた自身を訓練することができます。欠陥についてすぐにフィードバックが得られるTopCoderコンテストを実施すると、いくつかの一般的な欠陥を排除し、コーナーケース(多くの欠陥が見つかる場所)について考えるようにかなり早くトレーニングできることがわかりました。この種のものは興味深い研究になります...

予測不良率の観点から、静的分析の結果と欠陥の相関関係について少し前に論文を読みました: 自動静的分析の有効性障害検出およびリファクタリング予測のためのツール (tl; drは正確には相関していませんが、不良コードは問題が特定されない可能性がありますが、問題が多くなる傾向があります)。

3
Guy Sirton

私はソフトウェアの作成をまだ読んでいないので、彼らが本で描いた結論についてコメントすることはできません。エラー対コード行のプロットは、コード行が必ずしもその中に含まれるロジックの複雑さの度合いを示唆するわけではないため、よくても誤解を招く可能性があります。多くの場合、コード行は、時間と労力/コストを決定するときに、チームの作業能力を大まかに測定するための管理ツールとしてより有用であり、それでも欠陥がある可能性があります。

メトリックを使用してコードの品質とエラーの可能性を測定する場合、次のものが非常に役立つことがわかりました。

  1. コードカバレッジ
  2. 命令パスの長さ
  3. 循環的複雑度

優れた profiler を使用すると、コードを最適化するだけでなく、かなりの数のバグが固有のバグである可能性についての感触を得るために役立つ測定を提供するのに非常に役立ちます。システム。 FWIW、私は Redgate ANTプロファイル が優れた.NETプロファイラーの1つであることを発見しました。

さてあなたの質問に戻りましょう。ソフトウェアメトリックについては、少なくとも70年代前半から私の知る限りで説明されていますが、推測しなければならないのであれば、それよりも以前のトピックに関心があった可能性が高いと思います。

...簡潔な言語は、冗長性は低くなりますが、(より冗長な言語に比べて)プログラマーエラーが発生しやすくなる可能性はありますか?または、冗長性の低い言語で記述された欠陥を見つけて修正するのが10倍難しいのでしょうか。

私はそれが完全に可能であるだけでなく、言語の簡潔さのためにも、またその固有の複雑さのためにも可能性が高いと言います。たとえば、アセンブラは、言語が構文的に取得できるのと同じくらい簡単であり、バグを最小限に抑えるために細部に非常に注意深い注意を払う必要がありますが、さらに詳細になると、事実上すべての状態にブレークポイントを設定することで状態を確認する多くの機会が与えられます変化する。とはいえ、よく分解されたコードを備えた高レベルの言語と比較して、アセンブラで目だけで問題を特定することは通常困難です。

一方、冗長性が低下したことにより、1つのコマンドで多くの一般的な操作を処理する高水準言語を意味する場合は、ショートカットとしてのコマンド自体がエラーなしであり、その目的がコマンドを適用してもエラーは発生しません。コマンド構文の冗長性を低くすると、構文の使用方法によっては、コードに難読化の要素を導入する効果も得られます。

このトピックについて何か公開されていますか?

Software Metrics に関するWikipediaの記事には、いくつかの論文へのリンクがいくつかあります。そのため、前にリストした各メトリックもそうです。ピアがそのすべての情報をどれだけよくレビューしたかについては、私は完全に確かではありませんが、はい、このまさにこの主題については多くの公開された情報があるようです。これは、多くの高度なCompSci論文の肉とじゃがいもです。 ;)

2
S.Robins

これから、冗長性の低い言語(動的言語?)を選択すると、コード行が少なくなり、欠陥が少なくなると推測するのは簡単です。

簡単で、そのデータセットで取得できる限り正確に近い。コードの行は、エラーが発生する場所です。コードが少ないほど、エラーが発生する場所が少なくなります。

しかし、「ソフトウェアの作成」の調査では、言語の選択が欠陥や欠陥のクラスに及ぼす影響については触れられていませんでした。

実は。ありました。それはあなたに事実を与えました。コードの行数が少ないほど、エラーが少なくなります。

たとえば、Javaプログラムはclojure(またはscala、groovy、...など)で書き直すことができ、LOCを10倍以上節約できます。さらに、それ。

notは正しいでしょう。彼らはそれが相関していると言いました。彼らは関係が線形であるとは言いませんでした。

エラーがありますoutsideコード。仕様エラー。エラーのテスト。非コード欠陥とコード欠陥があります。

しかし、簡潔な言語は冗長ではありませんが、(より冗長な言語に比べて)プログラマーエラーが発生しやすくなる可能性はありますか?

いいえ。簡潔な言語ではエラーが少なくなります。とても簡単です。

問題は、超簡潔な言語を書くのが難しいことです。したがって、エラーの数が減少しても、コストは増加します。メンテナンスは非常に困難です。 APLやIのような言語は、多くの場合、追記型言語です。コードは非常に密集しているため、変更を加えるのは困難です。多くの場合、最初からやり直してすべての新しいプログラムを作成する方が簡単です。

他の問題は、非コードエラーがしばらくすると支配し始めることです。優れた簡潔な言語(特に、問題のあるドメインに本当に適しているDSL)は、他にも多くのエラーの原因があることを示しています。


多くの微妙な(そして無意味な)議論を避けるため。

  • 引用された研究は明らかに不完全です。

  • より微妙な説明がある場合は、独自の調査を実施し、独自の結果を公開して、それらについて議論できるようにしてください。

  • できれば質問に集中してください。新しい証拠を紹介したい場合は、新しい質問を開くか、質問自体にコメントして新しい証拠を紹介します。

1
S.Lott

編集:別のポイントを強調したいので、私は自分の答えを再配置しました。

冗長性は、欠陥の検出と修正を容易にするのに役立つ場合があります。 2次式を考えます(単純化のために正の根のみ)。

float quad(float a, float b, float c)
{
   return (-b + sqrt(b*b - 4*a*c)) / (2*a);
}

そして、これと同等の実装:

float quad(float a, float b, float c)
{
    float discriminant = b*b - 4*a*c;
    float numerator = -b + sqrt(discriminant);
    float denominator = 2*a;
    float root = numerator/denominator;
    return root;
}

後者は多少極端ですが、デバッガーへのステップインを容易にする一般的なスタイルであり、ブラケットのミス(一般的なミス)のリスクも軽減します。複合式は、高級言語では明らかに一般的な機能ですが、ユビキタスではなく、バグを見つけにくくすることがよくあります。

前者のスタイルを好む人が書いた数学ライブラリは3KLOCであり、後者を好む人が書いた数学ライブラリは10KLOCである可能性があり、後者には欠陥が少ないと考えられます。

「Making Software」の研究はすばらしいスタートでしたが、それでも私はもっと欲しくなりました。このトピックについて何か公開されていますか?

純粋なLOCは、Cでの効果的な対策であるとしても、多くの(ほとんどの)言語のバグ数を適切に推定できるとは思いません。制約により、LOCが増加し、欠陥が減少することがよくあります。 Cでは使用できない言語機能を含む多くの種類の制約があります。

  • 適切な英語の命名規則
  • 単体テスト/ TDD
  • ランタイムアサーション
  • タイプセーフ
  • 事前/事後条件
  • 不変
  • 測定単位 (おそらくタイプセーフのタイプ)

しかし、 this study によると、TDDはLOCをほぼ2倍にすることができますが、バグを減らすことができます。 (これはTDDの結果が単体テストの結果であるほど多くはないと思いますが、それはまた別の話です。)

いいえ、TDDは言語機能ではありません。ユニットテストコードをLOCに直接カウントする必要はないと思いますが、 is は非常に別の形式の制約であり、その制約は、たとえコードを増やしても、バグを減らすために機能します。

また、たとえば、1つの言語を除くすべての言語が測定単位をサポートし、他のすべての言語が等しい場合、その言語はより簡潔になり、その言語のプログラムには oneを含むより多くのバグがあります墜落した宇宙船

1
Rei Miyasaka