オープンソースリポジトリにおける バグ修正履歴の再利用性評価 九州工業大学 塩塚 大○ 九州大学 鵜林 尚靖 SIGSS2011 in 沖縄 20分発表 5分質疑 オープンソースリポジトリにおけるバグ修正履歴の再利用性評価と題しまして、 九州工業大学の塩塚が発表致します。
(Debug Concern Navigator) 研究の概要 過去のバグ修正の情報を利用したい dcNavi (Debug Concern Navigator) public class Property { public String readFile (String pathname) throws IOException { FileRReader(fileReader); File file = new File(pathname); String val = null; return val; val = br.readLine(); } } File file = new File(pathname); 問題コード public class Property { public String readFile (String pathname) throws IOException { File file = new File(pathname); String val = null; BufferedReader br = new BufferedReader(fileReader); FileReader fileReader = new FileReader(file) ; } } return val; val = br.readLine(); public class Property { public String readFile (String pathname) throws IOException { File file = new File(pathname); String val = null; FileReader fileReader = new FileReader(file) ; BufferedReader br = new BufferedReader(fileReader); return val; val = br.readLine(); } } public class Property { public String readFile (String pathname) throws IOException { File file = new File(pathname); String val = null; BufferedReader br = new BufferedReader(fileReader); FileReader fileReader = new FileReader(file) ; } } return val; val = br.readLine(); 分析&検索 推薦 プロジェクトXXXの リポジトリ まず研究の概要を説明します。 ソフトウェア開発において、バグの修正(デバッグ)をする際には、 例えば、バグの有りそうな箇所を検査したり、関連するソースコードを参照・検索したり、 あるいは過去のデバッグの経験をもとに、ソースコードの修正をおこないます。 本研究では、過去のバグ修正情報を効率的に活用するための推薦システムとして dcNaviを提案してきました。 dcNaviでは、問題コード、バグを含んでいそうなコードを入力とし、 それに対して、例えば利用しているAPIの誤り易い例や、同じ例外に関連した修正などの推薦をおこないます。 今回このシステムについてのオープンソースを対象として評価を行ったので、それを中心に発表します。 例)利用しているAPIの誤り易い例 例)同じ例外に関連した修正 今回は、バグ修正情報の再利用性について発表
発表の流れ 1.研究の動機 2.dcNavi 3.実験 4.関連研究 5.まとめと今後の課題 ・DCG(Debug Concern Graph) ・推薦アルゴリズム 3.実験 4.関連研究 5.まとめと今後の課題 発表の流れはこのようになっています。 まず研究の動機を述べた後、dcNaviについて説明します。 そして、デバッグ関心事グラフ(DCG)について説明します。 dcNaviでは、推薦を行う前に、リポジトリから役に立ちそうな情報だけをふるいにかけて、DCGというものを作ります。 推薦の際にはリポジトリ全体を探すのではなく、このDCGを用います。 そして、推薦のアルゴリズムを説明した後、オープンソースを対象として行った実験について説明します。 そして、関連研究を紹介し、最後にまとめと今後の課題を述べます。
1.研究の動機 背景:類似したバグ修正が行われることがある 目的:バグ修正の際に役立ちそうな過去の修正情報を見つけたい! 例:subclipseプロジェクトでの修正 目的:バグ修正の際に役立ちそうな過去の修正情報を見つけたい! では研究の動機について説明します。 デバッグを行う際、開発者は実行結果やプログラムの挙動から 「過去に同じようなバグに遭遇したことがある気がする」と感じ、 実際に似たようなバグ修正を行うことがあります。 例えば、図1(上の図)はsubclipseというプロジェクトのリビジョン984における実際に行われたremoveメソッドの修正です。 一方図2(下の図)は同じプロジェクトの、さらに少し前のリビジョンであるリビジョン920で行われたmoveメソッド修正です。 いずれもメソッドのパラメータの変更を行っています。 ソースコードから察するに両者ともコマンドを実行する際に強制実行することを指定していなかった、 という同じ誤りであると推測できます。 もし、リビジョン984のremoveメソッドを修正する際に、 リビジョン920のmoveの修正方法というものを参照することができれば、 互いに類似した誤りであるから修正のヒントになるのではないかと考えました。
解決すべき課題 バージョン管理システムから役立ちそうな情報を検索&推薦したい しかし、以下のような4つの課題がある 1.バグ修正に関する変更情報の選別 仕様変更などはできるだけ排除したい どの時点のリビジョンをバグ修正の開始、終了とするか 2.再利用のメリットがありそうな変更情報の選別 コメントの変更などのように、再利用のメリットが少なそうなものは排除したい 3.類似したバグの検索 できるだけ類似しているバグを発見したい 4.型情報の考慮 単純にテキストベースの検索ではコメントや変数名などがヒットしてしまう場合がある そこで、本研究ではバージョン管理システムなどのリポジトリから役立ちそうな情報を検索&推薦したいと考えました しかし、次のような4つの課題があります。 まず、バグ修正に関する情報を取得する際、実際のバージョン管理システムでは、バグ修正以外、たとえば仕様変更などのコミットもあります。できるだけそういったものを排除したいと考えました。また、どのリビジョンからどのリビジョンまでをバグ修正と判断すべきか、どこからどこまでの差分を見るべきか明確にする必要があります。 第二に、全てのバグ修正情報が必ずしも役に立つとは限りません。たとえば、コメントの変更などのように、再利用のメリットが少なそうなものは検索から排除する必要があると考えました。 第三に、膨大なバグ修正情報の中から、できるだけ現在の状況と類似した状況での修正を見つけられる必要があります。というのも、全く違う状況で起きたバグ修正であれば、あまり修正の参考にはならないのではと考えたからです。 最後に、特定のAPIを検索したい場合に、単純にテキストベースで検索しただけでは、クラスやメソッド以外のコメントや変数名の一部がヒットしてしまう場合があります。型まで考慮して検索できる必要があります。 ★4:30
2.dcNavi [DCG生成機能] [推薦機能] ・DCGはバージョン管理システム から生成(後述) (1) ライブラリの誤り易い例と、 から生成(後述) [推薦機能] (1) ライブラリの誤り易い例と、 そのときの修正方法(後述) (2) 過去にある例外に関連した ソースコードとそのときの修正方法 修正後 rev920 の修正 バグ修正パターン 修正前 プログラム要素 実装したツールdcNaviについて説明します。 dcNaviは統合開発環境Eclipseのプラグインとして作成しました。 機能としてはDCG生成機能と推薦機能があります。 DCG生成機能では、バージョン管理システムを分析し 役に立ちそうな情報だけをふるいにかけて、DCGというものを作ります。 DCGについては次のスライドで説明します。 推薦機能では、 (1) ライブラリの誤り易い例と、そのときの修正方法(後述) (2) 過去に、ある例外に関連したソースコードとそのときの修正方法 などを提供しています。 これらの推薦は生成したDCGを用いて行います。 ~dcNaviのスナップショット~ ・moveメソッドの修正前から修正後までに作られたDCG ・Eclipseのプラグインとして実装
DCG(Debug Concern Graph) 下の図が、moveメソッドの修正前から修正後までに作られるDCG DCG = プログラム解析情報 + バグ修正情報 から成るデバッグ履歴の表現 :メソッド宣言 move のデバッグ :メソッド内のプログラム要素 :バグ修正パターン diff-1 diff-2 calls move move calls バグ修正パターン(全27種) MC-DM:同一オブジェクトに対する呼び出すメソッドの変更 MC-DAP: メソッド呼出しのパラメータの変更 SQ-AROB: メソッド呼出しの追加/削除 getBaseDir move catches calls calls バグ修正パターン*: MC-DM move DCGについて説明します。 下の図が、先ほどのリビジョン920のmoveメソッドのバグ修正によって作られるDCGです。DCGでは、バグ修正の始まり、および終わりの判断基準として、バージョン管理システムのコミットログに含まれるキーワードに着目します。コミットの際のキーワードに「bug, fix, patch」が含まれていれば、そのリビジョンを修正後のリビジョンと判断し、その直前のリビジョンを修正前のリビジョンと判断します。 そして、デバッグ開始時で修正に関連していたメソッドなどのプログラム要素を収集します。さらにソースコードを解析し、メソッド内で呼び出しているメソッド(calls)や、インスタンス生成(creates)や、補足している例外(catches)を収集します。ここで収集したプログラム要素を活用し、類似した修正を検索します。 そして、修正前と修正後ファイルの編集の差分から、どのような修正をおこなったか、つまりバグ修正パターンをもとめます。バグ修正パターンは先行研究で提案されたものを使っています。全部で27種類あり、代表的なものに、呼び出すメソッドの変更、メソッド呼出しのパラメータの変更、メソッド呼出しの追加、などがあります。とくにこの3パターンが、プログラマが間違えやすいと知られているので、DCGでもこの3パターンの誤りを支援の対象とします。DCGでは、すべての修正情報をリポジトリから収集するのではなく、このパターンに合致する修正のみを収集します。これは、先ほど説明したように、実際にはコメントの変更などの修正もありますが、そういったものは再利用するメリットが少ないと考えたからです。 wrapException toString デバッグ開始(修正前) デバッグ終了(修正後) キーワード「bug, fix, patch」 *Pan, K., et al.: Toward an understanding of bug fix patterns. Empirical Software Engineering, pp.286-315, 2009.
推薦アルゴリズム ライブラリの誤り易い例とそのときの修正方法 修正対象:rev984のremoveメソッド ①関連したメソッドが修正されている履歴を検索 remove のデバッグ ②類似度(共通要素数の割合)を計算し類似しているものを優先 diff-1 ③バグ修正パターンや修正差分を推薦 remove toString delete move のデバッグ バグ修正パターン*: MC-DM wrapException diff-1 diff-2 推薦アルゴリズムについて説明します。ここでは例として、リビジョン984のremoveメソッドを修正対象とし、リビジョン920のmoveメソッドの修正をどのようなステップで発見し推薦するのかを説明します。 まずステップ1では、修正対象メソッドのremoveメソッド内で利用しているメソッド、この場合toString, とdeleteが該当しますが、修正されたような履歴を探します。wrapExceptionは例外捕捉でメソッド呼出しではないので無視します。これにより、修正対象メソッド内で呼ばれていたメソッドに関連した修正のみが取得できます。完全に同じメソッドtoString, deleteを探すか、あるいはこれらが定義さているクラス内のメソッドまでを探すか、などが指定できます。ここでは、同じクラス内のメソッドまでを含めて探すようにしています。これによりmoveメソッドの修正履歴、DCGが発見されます。 次に類似度を計算し類似しているものをより優先して推薦するようにします。類似度は2つの履歴間の共通要素の割合で計算します。この例では、共通要素が2つなので類似度を求めると0.57となります。実際この数字は高い方で、0.5を超える場合はわりと稀です。moveメソッドの修正履歴が推薦の上位に来ます。 最後に、類似度の高い順に、そこに含まれているバグ修正パターン、および関連したメソッドを推薦します。 ★9:00 SvnCommandLineクラスのメソッド 類似度 : 共通要素数 ÷ {(G1の要素数 + G2の要素数) / 2} = 2 / {(3 + 4) / 2} = 0.57 move move getBaseDir wrapException move move toString 推薦対象:rev920のmoveメソッド
3.実験 DCG 目的 対象プロジェクト 手順 推薦量/推薦時間/推薦の質の確認 EclipseプラグインでMylynに関連した9つのオープンソース 手順 リポジトリからライブラリに関連したバグを含んでいたメソッド(修正対象)を選択し、 修正方法(修正例)を推薦 推薦元データ オープンソースを対象として、dcNaviの評価実験を行いました。 実験では、推薦量、推薦時間、および推薦の質の確認をしました。 対象プロジェクトとして、EclipseプラグインでMylynに関連した9つのオープンソースで実施しました。 実験の手順ですが、まず、リポジトリからライブラリに関連したバグを含んでいたメソッドを取出します。 この時、そのメソッドがその後どのように修正されたか分かっているものを使いました。 そのメソッドに対して、 先ほど説明したアルゴリズムで修正方法(修正例)を推薦します。 推薦元データとして、自プロジェクトのリビジョンの80%と、他の8プロジェクト全部を使い、 これに対し、自プロジェクトの残りの20%のリビジョンに推薦を行いました。 異なるプロジェクトを混ぜて使うことで、 一般的な誤りやドメインに特化した情報が集まるのではないか、 と考えこのような選定・方法を用いました。 生成 DCG 推薦 修正対象 + 自プロジェクトの リビジョンの80%内 のバグ修正情報 他の8プロジェクト バグ修正情報 自プロジェクトの残りの20% のリビジョン内のバグ
正解の定義 実際の修正方法と修正例のバグ修正パターンを比較 一致! 条件1は満たす 不一致! 条件2は満たさない 条件1.バグ修正パターンの種類が一致 条件2.修正されたメソッドが一致 条件1 バグ修正パターン*: MC-DM 条件2 修正されたメソッド delete 一致! 条件1は満たす 不一致! 条件2は満たさない 推薦されたものの正解の判断基準として、2つの条件、バグ修正パターンの種類と、修正対象となったメソッド、これらの一致/不一致を用いました. 例えば、removeメソッドとmoveメソッドの例では、いずれも呼び出すメソッドの変更、MC-DMパターンの修正をしているので、バグ修正パターンの種類は一致となります。一方で、修正対象となったメソッドが異なっているので、この例では不正解となります。修正対象となったメソッドが一致しているかどうかの基準を、たとえば同一クラス内のメソッドまで正解とする、のように緩くすればこの例では正解となるのですが、とりあえず実験ではメソッドが完全に一致している場合のみを正解としました。 推薦されたものが、これらの条件を満たした場合、実際の修正方法と修正例がある程度似ていることから、修正の参考になり得るのではないか、と考えこのような条件にしました。論文の方では、条件1のみを満たした場合を正解とした推薦の精度、および条件2のみを満たした場合を正解とした推薦の精度を載せています。以降では、この2条件を満たした場合を正解として結果を述べていきます。 条件1 バグ修正パターン*: MC-DM 条件2 修正されたメソッド move
質の表現 適合率(推薦の精度の指標) 再現率(正解の網羅率の指標) F値 推薦結果内にどれだけ正解が含まれるか、ノイズが少ないか 推薦結果内に含まれる正解の割合 再現率(正解の網羅率の指標) 推薦候補内に含まれる正解をどれだけ網羅できたか、漏れが少ないか 全推薦候補内(自プロジェクト80%+他の8プロジェクト)に含まれる正解に対する,推薦結果内の正解の割合 F値 適合率と再現率の調和平均 読み上げる ★12:30
結果1 Note.条件1および2を満たした場合を正解とした場合の結果 プロジェクト NOM ANR ATR(msec) 適合率(%) 再現率(%) F値(%) 9 プロジェクトの推薦結果はこのようになりました。 推薦の際は推薦量の上限を30個、類似度の下限、閾値を0.2に設定し行いました。 つまり、類似度の高いものから順番に推薦していくので、30個以上ある場合はそれ以上は推薦されません。 結果ですが、例えばqcMylyn プロジェクトでは修正対象メソッド数(NOM)が54 個で, 1 個に対して平均して5.7 個のメソッドを推薦できています 全て推薦し終えるのに平均して36.46msec 掛かっています. 適合率は34.42%,再現率は50.24%,F 値は40.85%でした. 9 プロジェクトを平均すると,適合率は22.15%,再現率は40.16%,F 値は28.55%でした.
結果2 次に、正解と、類似度の関係を調べるために、類似度の閾値を変化させていった場合の、9 プロジェクトを平均した推薦の質を説明します。 結果を示すように、類似度の閾値を高くすると適合する推薦が多く得られることが分かりました. 一方で正解が類似度の低い部分に多く存在することから, 正解であれば類似度が高いとは必ずしも言えないことが分かりました. 理由として,例えばクラスライブラリのように幅広く利用される一般的なAPI では, 必ずしも類似した状況でなくても、同じ修正が発生し得るためと考えました. しかし,実際には類似度の低い部分には正解以外も多く存在するため, ノイズを抑えるために類似度を考慮することには意味があったと考えます. ※ 9プロジェクトで平均した値
結果3 次に、推薦に当たっての入力のサイズである、修正対象メソッド内部のプログラム要素数の合計と正解の関係を調べました。 これは、何十行、あるいは何百行もあるような大きなメソッドに対する推薦と、 数行程度の小さいメソッドに対する推薦では、推薦の精度が変わってくるのではないかと考えこのような実験を行いました。 結果ですが、メソッドのサイズが1個~5個と小さい場合では、比較的推薦の質が高くなることが分かりました。 これは、メソッドのサイズが小さいと必然的に、メソッド同士の実装がかなり類似することになり、 結果として正解し易くなったのではと考えます。 ※ 9プロジェクトで平均した値
結果4 推薦候補内に存在する正解からなる集合 推薦結果のうち正解だった要素からなる集合 最後に、実際にどのようなドメインのメソッドが頻繁に修正されて、 どのドメインへの推薦がうまくいったのか調べました。 正解集合というのは、推薦候補内に存在する正解からなる集合で、 適合集合というのは推薦結果のうち正解だった要素からなる集合です。 結果から分かるように、EclipseのAPIに関する修正が最も多く、かつ一番多く推薦で来ています。 また、今回Mylynに関するオープンソースで実験を行いましたが、 Mylynに関する修正が12%あり、正解だった推薦の14%がMylynに関するものでした。 ある程度Mylynのドメインに関連した修正が推薦で来たと思います。 また、自プロジェクトの誤りは、全体的に見てそこまで多くないことが分かりました。 ★16:30 推薦候補内に存在する正解からなる集合 推薦結果のうち正解だった要素からなる集合
4.関連研究 修正履歴を活用した研究 BugMem [Kim, S. FSE2006] ソースコード差分の検索を支援 クラスライブラリやstatic呼出しを排除して差分を検索可能 DebugAdvisor [Ashok, B. FSE2009] バージョン管理システム,バグデータベース,デバッガログなど統合して類似バグが検索できるクエリ(fat query)を提案 FixWizard [Nquyen, T. T. ICSE2010] メソッド呼出しなどの順序を考慮して類似バグの検索を支援 関連研究を3つ紹介します。 1つ目の、BugMemでは、ソースコードの差分の検索を支援しています。 検索の際に、フィルタリングなどしてクラスライブラリやstatic呼出しなどを排除して類似した修正の検索を支援しています。 2つ目の、DebugAdvisorでは、バージョン管理,バグデータベース,デバッガログなど統合して類似バグが検索できるクエリ(fat query)を提案しています。 本研究では、バージョン管理システムを利用し検索しました。 またプログラム解析情報、メソッド内でどういうメソッドが呼ばれているか、どういったクラスのインスタンスが生成されているか、を用いて検索を行いました。 3つ目の、FixWizardでは、メソッド呼出しなどの順序を考慮して類似したバグの検索を支援しています 本研究では、特に順序は考慮せず共通要素数を持って推薦しました。
5.まとめと今後の課題 まとめ 今後の課題 オープンソースを用いた評価実験によりdcNaviの推薦機能(ライブラリ利用例)の性能を確認 正解の定義の妥当性の確認 定性的な評価が必要 現状では必ずしも「正解⇒修正に役立つ」ではない 読み上げる