重複コードと非重複コードにおける 修正頻度の比較 大阪大学大学院情報科学研究科 佐野 由希子,肥後 芳樹,楠本 真二 保守コストという言葉を使わずに背景を書く 1
研究背景 一般にソフトウェア開発において,重複コードの修正頻度は非重複コードの修正頻度に比べて高いといわれている この考えに基づき,重複コードの検出や集約に関する研究が数多く行われている しかし,それが事実かどうか定量的に調査した研究は少ない 中には,重複コードの方が安定していると報告する研究もある 事実かどうかはっきりしていない ソフトウェア開発において・・・ あっさりしすぎ 重要だが,あまりされてないなど,もう少し詳しく 2
既存研究 調査の粒度 調査の尺度 対象ソフトウェア 修正頻度計測結果 [1] ファイル ファイルの改版数 1つ(商用ソフトウェア) 重複コード>非重複コード [2] メソッド メソッドの変更される割合 4つ(すべてJava言語のOSS) [3] 行 変更された行数 5つのシステムから200バージョンずつ抽出(OSS) 重複コード<非重複コード 結果 [1]門田暁人,佐藤慎一,神谷年洋,松本健一,”コードクローンに基づくレガシーソフトウェアの品質の分析,”情報処理学会論文誌,Vol.44,No.8,pp.2178-2188,Aug.2003 [2]Angela Lozano,Michel Wermelinger,”Assessing the effect of clones on changeability,” International Conference on Software Maintenance,pp.227-236,2008 [3]Jens Krinke,”Is cloned code more stable than non-cloned code?,” Proceedings Eighth IEEE International Working Conference on Source Code Analysis and Manipulation, pp. 57–66, 2008.
研究概要 重複コードの修正頻度,非重複コードの修正頻度,ソースコード全体の修正頻度をそれぞれ計測 調査の粒度:行 調査の尺度:変更箇所数 対象ソフトウェア:Java言語とC++言語のオープンソースソフトウェアから規模の異なるものを5つ選択 4
修正頻度(1/2) 1リビジョン当たりの変更箇所数と定義 修正頻度 = 一般に重複コードの行数と非重複コードの行数とは等しくないため,変更箇所数に影響が出る この式のままでは公平な比較ができない 全変更箇所数 全計測対象リビジョン数 5
修正頻度(2/2) 重複コードや非重複コードの修正頻度を,それぞれの行数を用いて正規化 重複コードの修正頻度 非重複コードの修正頻度 全体の修正頻度 全対象リビジョン数 重複コードの変更箇所数 ソースコードの総行数 重複コードの総行数 = × 全対象リビジョン数 非重複コードの変更箇所数 ソースコードの総行数 非重複コードの総行数 = × 全体の修正頻度カット なぜこのような式になったか詳しく 規模の異なるソフトウェア間で比較を行えるようにした 全対象リビジョン数 全変更箇所数 = 6
修正頻度の計測手法:概要 バージョン管理ツールの履歴から,変更箇所の位置を特定 重複コード検出ツールを用いて,その位置が重複コードに含まれているか否かを判定 重複コードの検出は,各リビジョンごとにすべてのソースコードに対して行う 一定期間におけるソースコードの行数と変更箇所数を計測 リビジョンr リビジョンr+1 修正 × ○ 7
修正頻度の計測手法: ソースコードの正規化(1/2) フォーマットのみの変更など,ソースコードの意味的な変更以外の変更を計測するのを防ぐため,正規化を行った 空白行,コメント,インデントの削除 中括弧のみの行を削除し,その中括弧を1つ上の行に追加
修正頻度の計測手法: ソースコードの正規化(2/2) 1: //ラインコメント 2: while(c1){ 3: 4: /* ブロックコメント */ 5: if(c2){ 6: methodA(); 7: }else{ 8: methodB(); 9: 10: methodC(); 11: } 12:} 1: while(c1){ 2: if(c2){ 3: methodA(); 4: }else{ 5: methodB(); 6: methodC();}} 正規化前 正規化後
修正頻度の計測手法: 変更箇所の検出 ソースコードの変更前と変更後とで差異のある行をdiffコマンドで検出 行番号の連続しているものは1箇所の変更として計測 1: while(c1){ 2: if(c2){ 3: methodA(); 4: }else{ 5: methodB(); 6: methodC();}} 1: while(c1){ 2: if(c3){ 3: methodB(); 4: }else{ 5: methodB(); 6: methodD();}} 変更箇所 変更箇所 変更前 変更後
修正頻度の計測例(1/3) 重複コード内 の変更箇所 非重複コード内 の変更箇所 × × × × × × 総行数:45行 重複コード:15行 対象リビジョン リビジョンr 対象リビジョン リビジョンr+1 リビジョンr+2 × × × × × × クローンの色を変えとく 総行数:45行 重複コード:15行 非重複コード:30行 総行数:43行 重複コード:12行 非重複コード:31行 11
修正頻度の計測例(2/3) リビジョンr~r+2における重複コードの修正頻度 リビジョンr~r+2における非重複コードの修正頻度 全対象リビジョン数 重複コードの変更箇所数 ソースコードの総行数 重複コードの総行数 × 3 2 15+12 45+43 = × ≒ 4.89 全対象リビジョン数 非重複コードの変更箇所数 ソースコードの総行数 非重複コードの総行数 × 3 2 30+31 45+43 = × ≒ 2.16 12
修正頻度の計測例(3/3) リビジョンr~r+2におけるソースコード全体の修正頻度 この例の場合 2.16 < 3.00 < 4.89 重複コードの修正頻度が非重複コードの修正頻度を上回った 全対象リビジョン数 全変更箇所数 6 2 = = 3.00 13
計測対象 Sourceforgeにて公開されているオープンソースソフトウェア バージョン管理システムSubversionを使用 代表的な言語であるJavaとC++を使用 様々な規模や開発期間 ソフトウェア名 言語 リビジョン数 最終リビジョンの総行数 EclEmma Java 788 15,328 FileZilla C++ 3,450 87,282 FreeCol 5,963 89,661 SQuirreL SQL Client 5,351 207,376 WinMerge 7,082 130,283 選んだ条件
計測結果:全期間の修正頻度 重複コードの修正頻度が非重複コードより高いのか調べるため,全リビジョンにおける修正頻度を計測 字が見えない 計測や考察に関して メトリクスを使ってもっと詳細に調べられないか 機能追加などとバグ修正などは区別すべきでは クローンを分類(意味のないクローンと意味のあるクローン) すべてのソフトウェアにおいて,重複コードの修正頻度の方が低い 15
考察:全期間の修正頻度 重複コードの方が非重複コードよりも修正頻度が低い傾向が見られた 開発期間の長いソフトウェアほど,その傾向が顕著だった
計測結果:時期による推移 開発時期による変化 開発初期と後期では修正頻度の傾向が違ってくるのでは? 各ソフトウェアのリビジョン数を10等分し,それぞれの期間について修正頻度を計測 例えば,1000リビジョン規模のソフトウェアなら 1~100リビジョンの修正頻度 101~200リビジョンの修正頻度 201~300リビジョンの修正頻度 901~1000リビジョンの修正頻度 ・・・ 17
計測結果:時期による推移(EclEmma)
計測結果:時期による推移(FileZilla)
計測結果:時期による推移(FreeCol)
計測結果:時期による推移(SQuirreL)
計測結果:時期による推移(WinMerge)
考察:時期による推移 EclEmmaは対象リビジョン数が少ないため,はっきりとした傾向が読み取れなかったのではないか 開発期間の長いソフトウェアでは,ほとんどの期間において重複コードの方が非重複コードよりも修正頻度が低い傾向が見られた 開発時期ごとの推移について,各ソフトウェア間に共通した特徴はみられなかった Winmergeの期間2と期間10のソースコードを調査 期間10ではテストケースに対する修正が多く,テストケースの約88%が重複コードであったために,重複コードの修正頻度が高くなっていた 開発期間の長いほど winmerge
計測結果:バージョンごとの推移 時期ごとの推移について,バージョンの区切りごとに対象期間を分割した 機械的な分割を行った場合とは違った傾向が見られるかもしれない
計測結果:バージョンごとの推移(EclEmma)
計測結果:バージョンごとの推移(FileZilla)
計測結果:バージョンごとの推移(FreeCol)
計測結果:バージョンごとの推移(SQuirreL)
計測結果:バージョンごとの推移(WinMerge)
考察:バージョンごとの推移 時期による推移とほぼ同様の傾向が見られた 開発期間の長いソフトウェアでは,すべての期間において重複コードの方が非重複コードよりも修正頻度が低かった 開発時期ごとの推移について,各ソフトウェア間に共通した特徴はみられなかった
結果の妥当性について 留意すべき点(1/2) 対象ソフトウェアの種類 修正の内容 修正に要する作業量の違い オープンソースソフトウェアのみを使用しているが,商用ソフトウェアを使用すれば異なる特徴が表れる可能性がある 一般に,商用ソフトウェアはオープンソースソフトウェアに比べて重複コードの割合が高いといわれている 修正の内容 フォーマットのみの変更など,ソースコードの意味的な変更以外の変更も計測してしまう 修正に要する作業量の違い 1箇所の修正に要する作業量はすべて等しいと仮定しているが,実際には等しくない 正しく修正コストを表しているとは限らない
結果の妥当性について 留意すべき点(2/2) 修正箇所の判別 重複コード検出ツールの種類・設定 連続した行への変更を1箇所とみなしている 複数の変更を1つの変更と判定したり,1つの変更を複数の変更と判定してしまう可能性がある 重複コード検出ツールの種類・設定 1種類の検出ツールで単一の設定のみを使用しているが,ツールの種類や設定を変えれば,異なる重複コードが検出される可能性がある
まとめ ソフトウェア保守に対する重複コードの影響を評価するための手法として,修正頻度の計測手法を提案した 提案手法を実装したツールを作成し,5種のソフトウェアに対して計測を行った 重複コードの修正頻度は非重複コードの修正頻度に比べて低い傾向にあった 今後の課題 より多くのソフトウェアに対して調査 検出された修正とバグ修正との関連を調査 結論追加 33