オブジェクト指向プログラミング言語に対応した コードクローン検出技法の提案と実験

Slides:



Advertisements
Similar presentations
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University 保守支援を目的とした コードクローン情報検索ツール.
Advertisements

背景 ソフトウェアの大規模化・複雑化 生産性と品質の向上 ↓ オブジェクト指向分析設計の適用 開発ツールの投入.
区間グラフにおける区間表現からMPQ-treeを効率よく構成するアルゴリズム
XHTML構文検証手法における スクリプト要素の静的解析アルゴリズム
AGMアルゴリズムを用いた ギャップを含むコードクローン情報の生成
情報伝播によるオブジェクト指向プログラム理解支援の提案
剽窃 他人の作品や論文を盗んで,自分のものとして発表すること. プログラムが剽窃される事例もある. Aさんのプログラム Xさんのプログラム
研究の背景 コードクローン ソースコード中に存在する一致または類似したコード片
プログラム変更支援を目的とした コードクローン情報付加手法の提案と実装
大規模収集データに基づいた ソフトウェアエンジニアリング
大規模開発データの収集と エンピリカルソフトウェア工学
川口真司 松下誠 井上克郎 大阪大学大学院情報科学研究科
プログラム実行履歴を用いたトランザクションファンクション抽出手法
コードクローン検出技術と その利用法 神谷年洋‡, 植田泰士†, 肥後芳樹†, 楠本真二†, 井上克郎†
ソースコードの変更履歴における メトリクス値の変化を用いた ソフトウェアの特性分析
コードクローン分析ツールGeminiを用いたコードクローン分析手順
コードクローンの分布情報を用いた特徴抽出手法の提案
ギャップを含むコードクローンの フィルタリング手法の提案
コードクローンに含まれるメソッド呼び出しの 変更度合の分析
コードクローンに含まれるメソッド呼び出しの 変更度合の調査
識別子の共起関係に基づく類似コード検索法の提案と 欠陥検出への適用
ソードコードの編集に基づいた コードクローンの分類とその分析システム
ネットワーク共生環境を築く情報技術の創出 テーマ4:高信頼性・高安全性を有するネットワーク共生環境の構築技術の創出
動的依存グラフの3-gramを用いた 実行トレースの比較手法
オブジェクト指向プログラムにおける エイリアス解析手法の提案と実現
オブジェクト指向メトリクスを用いた 開発支援法に関する研究
利用関係に基づく類似度を用いたJavaコンポーネント分類ツールの作成
ソフトウェア制作論 平成30年10月3日.
Javaプログラムの変更を支援する 影響波及解析システム
クローン検出ツールを用いた ソースコード分析ツールの試作
コードクローン検出ツールを用いた ソースコード分析システムの試作と プログラミング演習への適用
リファクタリング支援のための コードクローンに含まれる識別子の対応関係分析
動的データ依存関係解析を用いた Javaプログラムスライス手法
ソースコードの特徴量を用いた機械学習による メソッド抽出リファクタリング推薦手法
コードクローンの動作を比較するためのコードクローン周辺コードの解析
コードクローンに対する一貫性のない変更に起因する欠陥の検出
柔軟に変更可能な字句解析機構を持つ コードクローン検出ツールの開発
ソースコード縮退による ソースコード理解 神谷年洋 科学技術振興事業団 さきがけ研究21 オブジェクト指向シンポジウム2003.
UMLモデルを対象とした リファクタリング候補検出の試み
プログラム実行履歴を用いたコードクローン検出手法
Javaバイトコードの 動的依存解析情報を用いた スライシングシステムの実現
コードクローン検出に基づくデザイン パターン適用支援手法の提案と実現
プログラム理解におけるThin sliceの 統計的調査による有用性評価
バイトコードを単位とするJavaスライスシステムの試作
コードクローン編集者数に着目した開発履歴の分析
多様なプログラミング言語に対応可能な コードクローン検出ツール CCFinderSW
○ 後藤 祥1,吉田 則裕2 ,井岡 正和1 ,井上 克郎1 1大阪大学 2奈良先端科学技術大学院大学
ソフトウェア保守のための コードクローン情報検索ツール
コードクローンの理解支援を目的としたコードクローン周辺コードの解析
コンパイラ 2011年10月20日
Javaバーチャルマシンを利用した 動的依存関係解析手法の提案
コーディングパターンの あいまい検索の提案と実装
JAVAバイトコードにおける データ依存解析手法の提案と実装
第7回OACISシンポジウム 大阪大学におけるソフトウェア工学研究と産学連携活動
大阪大学 大学院情報科学研究科 コンピュータサイエンス専攻 井上研究室
保守請負時を対象とした 労力見積のためのメトリクスの提案
クローン検出ツールを用いた ソフトウェアシステムの類似度調査
オープンソースソフトウェアに対する コーディングパターン分析の適用
統合開発環境のための プログラミング言語拡張 フレームワーク
欠陥検出を目的とした類似コード検索法 吉田則裕,石尾隆,松下誠,井上克郎 大阪大学 大学院情報科学研究科
容易に使用可能な grep風コードクローン検索ツール
ソフトウェア理解支援を目的とした 辞書の作成法
エイリアス関係を考慮した Javaプログラム用静的スライシングツール
コンパイラ 2012年10月11日
コードクローン解析に基づく デザインパターン適用候補の検出手法
オブジェクト指向言語における セキュリティ解析アルゴリズムの提案と実現
識別子の読解を目的とした名詞辞書の作成方法の一試案
オブジェクト指向メトリクスを用いた 開発支援に関する研究 --- VC++とMFCを用いた開発を対象として ---
コードクローンを対象とした リファクタリングの有効性に関する調査
Presentation transcript:

オブジェクト指向プログラミング言語に対応した コードクローン検出技法の提案と実験 神谷年洋† 楠本真二†  井上克郎†‡ †大阪大学大学院基礎工学研究科 ‡奈良先端科学技術大学院大学情報科学研究科

研究の背景 ソフトウェア保守 ソフトウェア保守 開発済みのソフトウェアを何らかの理由によって,変更・修正する作業. 修正のための保守 研究の背景 ソフトウェア保守  ソフトウェア保守 開発済みのソフトウェアを何らかの理由によって,変更・修正する作業. 修正のための保守 フィールドバグの修正 改訂のための保守 環境変化に対する機能追加・変更(バージョンアップ) 予防のための保守 将来トラブルにつながりそうな箇所に対する対応

コードクローン ソースコード中に類似したコード片があるとき、それらをコードクローンと呼ぶ

クローンが引き起こす問題 クローンはソフトウェア保守を困難にする クローンにフォールトが存在する場合、すべてのクローンについて修正を行わなければならない 機能追加も同様 設計品質の劣化 [1] 大規模なソースコードからクローンを効率よく検出する方法が必要 [1]G. V. Subramaniam, “Object Model Resurrection - An Object Oriented Maintenance Activity”, Proc. 22nd IEEE Int'l Conf. Softw. Eng.(ICSE), pp. 324-333, Jun. 2000.

既存のクローン検出手法 Bakerの手法[2] 行単位でソースコードを比較してクローンを検出する →基本的に入力ソースファイルの記述言語を問わない Baxterらの手法[3] C言語のソースファイルを入力,構文解析して,解析木(の部分木)を比較する [2] B. S. Baker: “On finding Duplication and Near-Duplication in Large Software System,” Proc. Second IEEE Working Conf. Reverse Eng., pp. 86-95, Tronto, Canada (Jul., 1995). [3] I. D. Baxter, A. Yahin, L. Moura, M. Sant’Anna, and L. Bier: “Clone Detection Using Abstract Syntax Trees,” Proc. of ICSM ’98, pp. 368-377, Bethesda, Maryland (Nov., 1998).

既存の手法の問題点 オブジェクト指向プログラミング言語への対応 オブジェクト指向プログラミング言語では,クラスのスコープルール,名前空間,汎用型などにより,複雑な名前が用いられる クローンを選択する手法 テーブルの初期化など,検出しても意味がないクローンがある

提案するクローン検出手法 ソースコードを字句解析してトークンの列に直してからクローン検出を行う 文法知識に基づいたコード変形 クラススコープや名前空間による複雑な名前の正規化を行う 初期化テーブルを取り除く モジュールの区切りを認識する 言語依存部分を取り替えることで,さまざまなプログラミング言語に対応

クローン検出手順 (1)ソースコードを入力し,トークンの列にする (2)変形ルールにより,トークン列を変形する (3)パラメータ置換を行う (4)マッチングアルゴリズムによりクローンを検出する (5)クローンの位置(ファイル,行)を出力する

例題コード 1. static void foo() throws RESyntaxException { 2. String a[] = new String [] { "123,400", "abc", "orange 100" }; 3. org.apache.regexp.RE pat = new org.apache.regexp.RE("[0-9,]+"); 4. int sum = 0; 5. for (int i = 0; i < a.length; ++i) 6. if (pat.match(a[i])) 7. sum += Sample.parseNumber(pat.getParen(0)); 8. System.out.println("sum = " + sum); 9. } 10. static void goo(String [] a) throws RESyntaxException { 11. RE exp = new RE("[0-9,]+"); 12. int sum = 0; 13. for (int i = 0; i < a.length; ++i) 14. if (exp.match(a[i])) 15. sum += parseNumber(exp.getParen(0)); 16. System.out.println("sum = " + sum); 17. }

ステップ(1):ソースコードを入力し,トークンの列にする

ステップ(2):変形ルールにより,トークン列を変形する

ステップ(3):パラメータ置換を行う

ステップ(4): マッチングアルゴリズムにより,クローンを検出

ステップ(4): マッチングアルゴリズムにより,クローンを検出

ステップ(5):クローンの位置を出力する 1. static void foo() throws RESyntaxException { 2. String a[] = new String [] { "123,400", "abc", "orange 100" }; 3. org.apache.regexp.RE pat = new org.apache.regexp.RE("[0-9,]+"); 4. int sum = 0; 5. for (int i = 0; i < a.length; ++i) 6. if (pat.match(a[i])) 7. sum += Sample.parseNumber(pat.getParen(0)); 8. System.out.println("sum = " + sum); 9. } 10. static void goo(String [] a) throws RESyntaxException { 11. RE exp = new RE("[0-9,]+"); 12. int sum = 0; 13. for (int i = 0; i < a.length; ++i) 14. if (exp.match(a[i])) 15. sum += parseNumber(exp.getParen(0)); 16. System.out.println("sum = " + sum); 17. }

変形ルールを用いない場合 4-6行目と 13-15行目, 8-10行目と 17-19行目 1. static void foo() throws RESyntaxException { 2. String a[] = new String [] { "123,400", "abc", "orange 100" }; 3. org.apache.regexp.RE pat = new org.apache.regexp.RE("[0-9,]+"); 4. int sum = 0; 5. for (int i = 0; i < a.length; ++i) { 6. if (pat.match(a[i])) 7. sum += Sample.parseNumber(pat.getParen(0)); 8. } 9. System.out.println("sum = " + sum); 10. } 11. static void goo(String [] a) throws RESyntaxException { 12. RE exp = new RE("[0-9,]+"); 13. int sum = 0; 14. for (int i = 0; i < a.length; ++i) { 15. if (exp.match(a[i])) 16. sum += parseNumber(exp.getParen(0)); 17. } 18. System.out.println("sum = " + sum); 19. } 変形ルールを用いなかった場合には,行3と行12,行7と行16が異なった行であると判定されるため,検出されるクローンはいずれも3行以下のクローンになります.

Java向けの変形ルール RJ1:パッケージ名除去 ( PackageName ‘.’ )+ ClassName → ClassName RJ2:Callee挿入 NDotOrNew NClassName ‘(‘ → NDotOrNew CalleeIdentifier ‘.’ NClassName ‘(‘ RJ3:テーブル初期化除去 '=' '{' InitalizationList, '}' → '=' '{' UniqueIdentifier '}‘ ']' '{' InitalizationList, '}' → ']' '{' UniqueIdentifier '}’ RJ4:モジュールの分離 トップレベルの定義や宣言の終わりにUniqueIdentifier を挿入する RJ5:可視性キーワードの除去 protected, public,synchronizedなどのキーワードを取り除く RJ6:コンパウンド・ブロックの処理 if (…), else, while (…) の直後が単文なら{}を補う

クローン検出ツール CCFinder 提案したコードクローン検出手法を実装した 言語依存部分と非依存部分を分離することにより、複数のプログラミング言語に対応 言語非依存部分(C++,7000行) マッチングアルゴリズム,分割,出力のフォーマット,… 言語依存部分(C++, 5000行) 言語に対応した変形ルール(Java,C/C++,COBOL,etc) 動作環境 Windows95/98/NT/2000 UNIX(一部)

最適化 Suffix-treeによるO(n)のマッチングアルゴリズム 入力ソースファイルの大きさをnとして 「文の最初のトークンだけがクローンの開始位置となることができる」制約によりメモリ使用量を削減 大規模なソースファイルには分割して処理を行う etc

適用例#1 JDKのライブラリ JDK(Java Development Kit) 1.2.2(サンプルとデモプログラムを除く) 入力ファイルは1648個,約50万行 ツールの実行には,Pentium III 650MHzおよび1GBのRAMを持つPCで約3分を要した

JDKのクローン散布図 両軸はソースファイルを辞書順に並べたもの 20行以上のクローンを図示 多くのクローンが密集している(A) 最長のクローン(B) B A

クローンが密集している部分(A) src/javax/swing/plaf/multi/*.javaの29のファイル いくつかはクラス名を除いてまったく同じクラスの定義を含んでいた コード生成ツールによって生成された 31| */ 32| public class MultiButtonUI extends ButtonUI { 33|   160| public static ComponentUI createUI(JComponent a) { 161| ComponentUI mui = new MultiButtonUI(); 162| return MultiLookAndFeel.createUIs(mui, 163| ((MultiButtonUI) mui).uis, 164| a); 165| }

最長のクローン(B) 最長のクローン(349行) src/java/util/Arrays.javaの18の“sort”メソッド シグネチャ(引数の型と数)が異なる アルゴリズムは同一

変形ルールの評価 変形/置換なしでは発見されるクローンは半減する 次に,変形ルールの効果を定量的に評価するため, 変形ルールを用いた場合と,用いない場合で,検出されるクローンを比較しました. 下のグラフは,JDKのライブラリから検出したクローンの長さのヒストグラムです. 水色の棒は変形ルールを適用した場合, 赤色の棒は変形ルールを適用しない場合です. 適用しない場合には,検出されるクローンが半減することが分かります. また,変形ルールを適用した場合には80前後の長さであると判定されるクローンが 適用しない場合にはより短くなってしまうことも分かります.

適用例#2 FreeBSD, Linux, NetBSDの比較 3つのOSの比較 FreeBSD 4.0 (C 220万行) Linux 2.4.0 (C 240万行) NetBSD 1.5 (C 260万行) FreeBSDとNetBSDは同じソースコードから,Linuxは異なるソースコード 実行には108分を要した

FreeBSD, Linux, NetBSDのクローン散布図

FreeBSDとLinuxのクローン ドライバ部分に多くのクローン「ファイル」が存在する 共通のソースから分岐したソースファイル 名前が付け替えられたソースファイル あるソースファイルを複数のファイルに分割している →

まとめ 主な結果 オブジェクト指向プログラミング言語向けのコードクローン検出手法を提案した 提案する手法を幾つかのコードに適用し,コードクローンの検出を確認した 今後の課題 構文によるクローン選別 クローン除去

システム構成 4種類の変形部 Java C++ COBOL プレーンテキスト ソースファイル 字句解析部 変形部 検出部 整形部 クローン トークン列 変形部 変形されたトークン列 変形されたトークン列から変形前のトークン列へのマッピング 検出部 トークン列上でのクローン 整形部 クローン

マッチングの計算量 単純な方法(前述した、行列を作る方法;O(n2))では,多くのメモリが必要となる. 例: 100万行のソースコード、1行平均3トークンと仮定すると 行列の大きさは3x106行x3x106列=9x1012セル(9兆、9T)

Suffix-treeによるマッチングアルゴリズム 以下の条件を満たす木 (1)木の葉は部分文字列の開始位置 (2)根から葉までラベルをたどると部分文字列になる (3)ひとつの節点から出る辺のラベルはすべて異なる文字で始まる →共通のパス=クローン

クローン検出のその他の応用 DNA配列 GENEバンク→類推→ソースコードバンク? 自然言語のテキストからクローン検出 …とにかくストリングで表現できるものであれば何でも

コードクローンの除去、予防 クローン除去 クローンをまとめるマクロを生成するツールを用いる[1, 2] クローン予防 モジュールと機能の対照表を作ってレビューする[6]

クローンによるソースコード評価 クローンをまとめることにより削減できるソースコードの割合[1] 機能が重複して実装されている割合、回数[6] クローンの分布 クローンが多く含まれるモジュール? クローンクラス(同値類)の広がり フォールトとクローンの統計的な関係?

pb x pa A B p x y x+y

大学の演習(1) Pascal風言語で書かれたコードをCASLに変換するコンパイラ C言語で開発 教科書,指導書を参考にして作成 課題1:構文チェッカ, 課題2:意味チェッカ, 課題3:コンパイラ,の順に作成 課題2と課題3では直前の課題で作成したプログラムを拡張 27人分のソースコード(P1~P27)を利用 次に、実験の概要について説明します。 データはある年度の情報科学演習Dにおいて作成されたプログラムを収集 しました。 この演習では、Pascal風言語で書かれたコードをCASLに変換するコンパイラをC言語で開発します。 教科書、指導書を参考にして作成していき、課題1では構文チェッカを,課題2では意味チェッカを課題3ではコンパイラの順に作成していきます。 課題2では課題1の課題3では課題2で作成されたプログラムを拡張していきます。 27人のソースコードをP1」からP27として入力データとします。 そしてDupSに適用し一致するコード片を検出した後、結果を分析します。

大学の演習(2) P1, P2, P3, P4, P5 P1 P2 P3 P4 P5

大学の演習(3) 一致割合の集計 プログラム内一致 =(プログラム内で一致する箇所 に含まれる総行数) ÷(プログラムの総行数) プログラム内一致  =(プログラム内で一致する箇所    に含まれる総行数)  ÷(プログラムの総行数) プログラム間一致  =(プログラム間で一致する箇所    に含まれる総行数)  ÷(プログラムの総行数) 拡張時に変更されない割合 =(課題2のプログラムにおいて、    課題3のプログラムと一致    する箇所に含まれる総行数)   ÷(課題2プログラムの総行数)  DupSの出力結果についてまとめます。 表の見方ですが、まず<縦に>27個のプログラムが並びます。そして次がプログラム内一致の割合、次にプログラム間一致の割合、そして課題2で作成された意味チェッカーが課題3への拡張時に利用される割合となります。 プログラム内一致、プログラム間、拡張時に利用される割合とは、こちらで定義してありますが、P14を例に直感的に説明していきますと、P14において内部で重複する割合が15%となり、他のプログラムと一致する割合が11%でなり、課題2で作成したプログラムが、課題3で60%利用されていると見ていきます。 大まかな目安としてだしてある平均とくらべると、平均よりP14の方が課題2の利用率が高いことが分かります。 一致割合の集計

大学の演習(4) 拡張時における利用割合による分析 関数単位の利用のされ方による分類 拡張時の利用度が高いP17(71%)と低いP5(39%)について調査 P17では課題2で作成したプログラムを関数単位でうまく利用している      → 課題2における設計がしっかりしていたと評価できる P5では何らかの理由で大幅な作り変えが行われた                  → 原因を調査し対処方法を指導に盛り込む 課題2から課題3に拡張する時際の、利用度が高いP17と利用度の低いP5 について調べた結果です。 P17とP5について、その課題2のプログラムの関数について、そのまま利用された関数、修正されて利用された関数、全く再利用されていない関数にわけて集計し円グラフにしました。 P17では64%の関数がそのまま課題3で使用されました。 これより、P17では課題2で作成したプログラムを関数単位でうまく利用していることが言え、課題2における設計がしっかりしていたと評価できます。 またP22では、69%の関数が利用されず、何らかの理由で作り変えが行われたと思われ、原因を調査し対処方法を指導に盛り込む事が考えられます。