CSセミナー1

重複コードと非重複コードにおける
修正頻度の比較
大阪大学大学院情報科学研究科
佐野 由希子,肥後 芳樹,楠本 真二
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
3
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つ上
の行に追加
8
修正頻度の計測手法:
ソースコードの正規化(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();}}
正規化後
9
修正頻度の計測手法:
変更箇所の検出
• ソースコードの変更前と変更後とで差異のあ
る行を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();}}
変更後
10
修正頻度の計測例(1/3)
重複コード内
の変更箇所
リビジョンr
×
×
非重複コード内
の変更箇所
リビジョンr+1
リビジョンr+2
×
×
×
対象リビジョン
総行数:45行
重複コード:15行
非重複コード:30行
×
対象リビジョン
総行数:43行
重複コード:12行
非重複コード:31行
11
修正頻度の計測例(2/3)
• リビジョンr~r+2における重複コードの修正
頻度
重複コードの変更箇所数
ソースコードの総行数
× 重複コードの総行数
全対象リビジョン数
3
45+43
≒ 4.89
= 2 ×
15+12
• リビジョンr~r+2における非重複コードの修
正頻度
非重複コードの変更箇所数
ソースコードの総行数
× 非重複コードの総行数
全対象リビジョン数
3
45+43
=
2 × 30+31 ≒ 2.16
12
修正頻度の計測例(3/3)
• リビジョンr~r+2におけるソースコード全体の
修正頻度
全変更箇所数
全対象リビジョン数
6
= 2 = 3.00
• この例の場合
– 2.16 < 3.00 < 4.89
– 重複コードの修正頻度が非重複コードの修正頻
度を上回った
13
計測対象
• Sourceforgeにて公開されているオープンソースソフト
ウェア
• バージョン管理システムSubversionを使用
• 代表的な言語であるJavaとC++を使用
• 様々な規模や開発期間
ソフトウェア名
言語 リビジョン数
最終リビジョンの総行数
EclEmma
Java
788
15,328
FileZilla
FreeCol
C++
Java
3,450
5,963
87,282
89,661
SQuirreL SQL Client Java
WinMerge
C++
5,351
7,082
207,376
130,283
14
計測結果:全期間の修正頻度
• 重複コードの修正頻度が非重複コ
ードより高いのか調べるため,全リ
ビジョンにおける修正頻度を計測
すべてのソフトウェアにおいて,重複コードの修正頻度の方が低い
15
考察:全期間の修正頻度
• 重複コードの方が非重複コードよりも修正頻
度が低い傾向が見られた
• 開発期間の長いソフトウェアほど,その傾向
が顕著だった
16
計測結果:時期による推移
• 開発時期による変化
– 開発初期と後期では修正頻度の傾向が違ってく
るのでは?
– 各ソフトウェアのリビジョン数を10等分し,それぞ
れの期間について修正頻度を計測
– 例えば,1000リビジョン規模のソフトウェアなら
• 1~100リビジョンの修正頻度
• 101~200リビジョンの修正頻度
• 201~300リビジョンの修正頻度
・
・
・
• 901~1000リビジョンの修正頻度
17
計測結果:時期による推移(EclEmma)
18
計測結果:時期による推移(FileZilla)
19
計測結果:時期による推移(FreeCol)
20
計測結果:時期による推移(SQuirreL)
21
計測結果:時期による推移(WinMerge)
22
考察:時期による推移
• EclEmmaは対象リビジョン数が少ないため,はっ
きりとした傾向が読み取れなかったのではないか
• 開発期間の長いソフトウェアでは,ほとんどの期間
において重複コードの方が非重複コードよりも修正
頻度が低い傾向が見られた
• 開発時期ごとの推移について,各ソフトウェア間に
共通した特徴はみられなかった
• Winmergeの期間2と期間10のソースコードを調査
– 期間10ではテストケースに対する修正が多く,テストケ
ースの約88%が重複コードであったために,重複コード
の修正頻度が高くなっていた
23
計測結果:バージョンごとの推移
• 時期ごとの推移について,バージョンの区切
りごとに対象期間を分割した
– 機械的な分割を行った場合とは違った傾向が見
られるかもしれない
24
計測結果:バージョンごとの推移(EclEmma)
25
計測結果:バージョンごとの推移(FileZilla)
26
計測結果:バージョンごとの推移(FreeCol)
27
計測結果:バージョンごとの推移(SQuirreL)
28
計測結果:バージョンごとの推移(WinMerge)
29
考察:バージョンごとの推移
• 時期による推移とほぼ同様の傾向が見られ
た
– 開発期間の長いソフトウェアでは,すべての期間
において重複コードの方が非重複コードよりも修
正頻度が低かった
– 開発時期ごとの推移について,各ソフトウェア間
に共通した特徴はみられなかった
30
結果の妥当性について
留意すべき点(1/2)
• 対象ソフトウェアの種類
– オープンソースソフトウェアのみを使用しているが,
商用ソフトウェアを使用すれば異なる特徴が表れる
可能性がある
• 一般に,商用ソフトウェアはオープンソースソフトウェアに比
べて重複コードの割合が高いといわれている
• 修正の内容
– フォーマットのみの変更など,ソースコードの意味的
な変更以外の変更も計測してしまう
• 修正に要する作業量の違い
– 1箇所の修正に要する作業量はすべて等しいと仮定
しているが,実際には等しくない
• 正しく修正コストを表しているとは限らない
31
結果の妥当性について
留意すべき点(2/2)
• 修正箇所の判別
– 連続した行への変更を1箇所とみなしている
• 複数の変更を1つの変更と判定したり,1つの変更を複
数の変更と判定してしまう可能性がある
• 重複コード検出ツールの種類・設定
– 1種類の検出ツールで単一の設定のみを使用し
ているが,ツールの種類や設定を変えれば,異な
る重複コードが検出される可能性がある
32
まとめ
• ソフトウェア保守に対する重複コードの影響を評
価するための手法として,修正頻度の計測手法
を提案した
• 提案手法を実装したツールを作成し,5種のソフ
トウェアに対して計測を行った
• 重複コードの修正頻度は非重複コードの修正頻
度に比べて低い傾向にあった
• 今後の課題
– より多くのソフトウェアに対して調査
– 検出された修正とバグ修正との関連を調査
33