CKメトリクスに基づくリファクタリングの 効果予測手法の提案と実装

Slides:



Advertisements
Similar presentations
シーケンス図の生成のための実行履歴圧縮手法
Advertisements

背景 ソフトウェアの大規模化・複雑化 生産性と品質の向上 ↓ オブジェクト指向分析設計の適用 開発ツールの投入.
JavaによるCAI学習ソフトウェアの開発
情報伝播によるオブジェクト指向プログラム理解支援の提案
リファクタリングのための 変更波及解析を利用した テスト支援ツールの提案
ソースコードに対する適用可能な修正手順を 可視化するリファクタリング支援手法の提案
CKメトリクスを用いてリファクタリングの 効果を予測する手法の提案
プログラム実行履歴を用いたトランザクションファンクション抽出手法
プログラム実行時情報を用いたトランザクションファンクション抽出手法
メトリクス計測 プラグインプラットフォームMASUの開発
ソースコードの変更履歴における メトリクス値の変化を用いた ソフトウェアの特性分析
静的情報と動的情報を用いた プログラムスライス計算法
オブジェクト指向プログラムのための 動的結合メトリクスの評価
ソードコードの編集に基づいた コードクローンの分類とその分析システム
暗黙的に型付けされる構造体の Java言語への導入
リファクタリング中に生じる コンパイルエラーの自動解消手法
オブジェクト指向プログラムにおける エイリアス解析手法の提案と実現
シーケンス図を用いて実行履歴を可視化するデバッグ環境の試作
ソフトウェアを取り巻く環境の変化がメトリクスに及ぼす影響について
重複コードと非重複コードにおける 修正頻度の比較
Javaプログラムの変更を支援する 影響波及解析システム
プログラム動作理解支援を目的とした オブジェクトの振舞いの同値分割手法
ソフトウェア設計検証 研究室の紹介 知能情報学部 准教授 新田直也.
動的データ依存関係解析を用いた Javaプログラムスライス手法
ソースコードの特徴量を用いた機械学習による メソッド抽出リファクタリング推薦手法
ソースコードの静的特性を用いた Javaプログラム間類似度測定ツールの試作
UMLモデルを対象とした リファクタリング候補検出の試み
Javaバイトコードの 動的依存解析情報を用いた スライシングシステムの実現
コードクローン検出に基づくデザイン パターン適用支援手法の提案と実現
プログラム理解におけるThin sliceの 統計的調査による有用性評価
バイトコードを単位とするJavaスライスシステムの試作
コードスメルの深刻度がリファクタリングの実施に与える影響の実証的研究
○ 後藤 祥1,吉田 則裕2 ,井岡 正和1 ,井上 克郎1 1大阪大学 2奈良先端科学技術大学院大学
ソフトウェア保守のための コードクローン情報検索ツール
コードクローン分類の詳細化に基づく 集約パターンの提案と評価
コーディングパターンの あいまい検索の提案と実装
JAVAバイトコードにおける データ依存解析手法の提案と実装
JavaScriptを含んだHTML文書に対する データフロー解析を用いた構文検証手法の提案
コードクローン間の依存関係に基づく リファクタリング支援環境の実装
オブジェクトの協調動作を用いた オブジェクト指向プログラム実行履歴分割手法
類似した振舞いのオブジェクトの グループ化による クラス動作シナリオの可視化
プログラムスライスを用いた凝集度メトリクスに基づく 類似メソッド集約候補の順位付け手法
設計情報の再利用を目的とした UML図の自動推薦ツール
保守請負時を対象とした 労力見積のためのメトリクスの提案
コードクローン間の依存関係に基づく リファクタリング支援手法の提案と実現
アスペクト指向言語のための視点に応じた編集を可能にするツール
プログラムの差分記述を 容易に行うための レイヤー機構付きIDEの提案
クローン検出ツールを用いた ソフトウェアシステムの類似度調査
オープンソースソフトウェアに対する コーディングパターン分析の適用
メソッドの同時更新履歴を用いたクラスの機能別分類法
開発作業の形式化に基づく プロセス評価 松下誠 大阪大学.
コードクローン間の依存関係に基づく リファクタリング支援手法の提案と実現
UMLモデルを対象とした リファクタリング候補検出手法の提案と実現
欠陥検出を目的とした類似コード検索法 吉田則裕,石尾隆,松下誠,井上克郎 大阪大学 大学院情報科学研究科
ソフトウェア理解支援を目的とした 辞書の作成法
オブジェクト指向開発における フォールト発生早期予測手法の 一提案
エイリアス関係を考慮した Javaプログラム用静的スライシングツール
複雑度メトリクスを用いた JAVAプログラム品質特性の実験的評価
プログラムの一時停止時に 将来の実行情報を提供するデバッガ
コードクローン解析に基づく デザインパターン適用候補の検出手法
回帰テストにおける実行系列の差分の効率的な検出手法
メソッド抽出リファクタリングが 行われるメソッドの特徴調査
木構造の比較に基づく メソッド呼び出し履歴の変化の可視化手法
オブジェクト指向言語における セキュリティ解析アルゴリズムの提案と実現
識別子の読解を目的とした名詞辞書の作成方法の一試案
オブジェクト指向メトリクスを用いた 開発支援に関する研究 --- VC++とMFCを用いた開発を対象として ---
プログラム理解のための 付加注釈 DocumentTag の提案
オブジェクト生成の観測に基づく プログラム実行の要約の抽出
コードクローンを対象とした リファクタリングの有効性に関する調査
Presentation transcript:

CKメトリクスに基づくリファクタリングの 効果予測手法の提案と実装 大阪大学 大学院情報科学研究科 ○松本義弘 肥後芳樹 楠本真二 井上克郎

研究の背景 将来的なソフトウェアの保守コストの削減を目的に,リファクタリング[1]と呼ばれる技術が研究されている. リファクタリングとは? ソフトウェアの外部的振る舞いを保ったまま,内部の構造を改善する技術 リファクタリングの効果は? ソフトウェアの保守性が向上する リファクタリングを実施するプロセスで,その効果を予測したいという要求がある まず,研究の背景ですが,将来的なソフトウェアの保守コストの削減を目的に,リファクタリングと呼ばれる技術が研究されています. リファクタリングとは,ソフトウェアの外部的振る舞いを保ったまま,内部の構造を改善する技術のことであり,リファクタリングを適用することで,ソフトウェアの保守性が向上すると言われています. また,リファクタリングを実施するプロセスで,その効果を予測したいという要求があります. 次に,一般的に用いられているリファクタリングのプロセスを紹介します. [1] M. Fowler, Refactoring: improving the design of existing code, Addison Wesley, 1999.

研究対象と目的 一般的に使われるリファクタリングプロセス[2] Step 1: どこにリファクタリングを適用すべきか決定する Step1で,どこにリファクタリングを適用するか,Step2でどのようなリファクタリングを適用すべきかを決定します. Step3で,決定したリファクタリングの効果を予測し,Step4では,実際にプログラムを修正します. 最後のStep5では,修正したプログラムが正しく動作するかのテストを行います. 本研究では,Step3リファクタリングの効果予測を支援することを目的とします. [2] T Mens and T. Tourwé. A survey of software refactoring. IEEE Trans. Softw. Eng., 30(2):126–139, 2004.

関連研究 リファクタリング位置特定/選択手法 リファクタリングの効果計測手法 構造的な欠陥(低凝集・高結合のクラスなど)を発見し,それに対して効果的なリファクタリングを提供[3] リファクタリングの効果計測手法 高結合を解消するリファクタリングを,独自に定義した結合度メトリクスに基づいて定量的に評価する[4] 関連研究としましては,リファクタリングの位置特定手法と選択手法があります. 具体的には,低凝集・高結合といった構造的な欠陥をもつクラスを発見し,それに対して効果的なリファクタリングを提案しています. また,リファクタリングの効果を計測する手法としましては, 高結合を解消するリファクタリングを独自に定義した結合度メトリクスに基づいて定量的に評価するものがあります. [3]秦野, 乃村, 谷口, 牛島. ソフトウェアメトリクスを利用したリファクタリングの自動化支援機構. 情報処理学会論文誌,44(6):1548–1557, Jun 2003. [4]Y. Kataoka. T. Imai, H.Andou and T. Fukaya, A quantitative evaluation of maintainability enhancement by refactoring., In ICSM ’02, p. 576-585, 2002.

研究の概要 関連研究の問題 研究目的 リファクタリングは,高結合・低凝集なクラスだけが対象ではない 「計算処理を行うクラスに画面描画の機能の一部が実装されているので適切なクラスに移動したい」 このようなケースにおいても,リファクタリングを評価する必要がある リファクタリング適用支援ツールを使っても,ソースコードの修正はコストがかかる ソースコードを修正する前に,ソフトウェア保守に与える効果を知るべき 研究目的 ソースコードを修正する前に,リファクタリングが保守性に与える効果を予測する手法を提案・実装し,有用性を評価する これらの関連研究の問題としましては,リファクタリングは,高結合・低凝集なクラスだけが対象ではないということが挙げられます. 例えば, 「計算処理を行うクラスに画面描画の機能の一部が実装されているので適切なクラスに移動したい」というケースがあります. このようなケースにおいても,リファクタリングを評価する必要があります. また,リファクタリング適用支援ツールを使っても,ソースコードの修正はコストがかかるため,ソースコード修正前にソフトウェア 保守に与える効果を知るべきだと考えています. そこで,本研究の目的は,ソースコードを修正する前に,リファクタリングが保守性に与える効果を予測する手法を提案・実装し, 有用性を評価することです. 次にソフトウェアの保守性に関連する研究を紹介します.

ソフトウェアの保守性 「機能仕様の変更や追加に対する修正のしやすさ」を表す ソフトウェアの保守性を評価するためにソフトウェア複雑度メトリクスが用いられている[4]. メトリクスが高く複雑であればあるほど修正のコストがかかり,保守が困難であると評価されている 代表的なソフトウェア複雑度メトリクスとして,CKメトリクスがあげられる 次にソフトウェアの保守性に関して簡単に紹介します. ソフトウェアの保守性とは, 「機能仕様の変更や追加に対する修正のしやすさ」を表します. また,ソフトウェアの保守性を評価するために,ソフトウェア複雑度メトリクスが用いられます. ソフトウェア複雑度メトリクスが高く複雑であればあるほど修正のコストがかかり,保守が困難であると評価されています. 代表的なソフトウェアメトリクスとして,CKメトリクスがあげられます. [4] 神谷年洋, オブジェクト指向メトリクスを用いた開発支援法に関する研究, PhD thesis, 大阪大学大学院基礎工学研究科, 2001.

※これらのメトリクスは,値が高いほどクラスが複雑であることを表す CKメトリクス CKメトリクスは以下の3つの観点からクラスの複雑さを評価する 継承 DIT (Depth of inheritance tree) NOC (Number of children) 結合 RFC(Response for a class) CBO(Coupling between object-class) クラスの 内部複雑度 WMC(Weighted methods per class) LCOM(Lack of cohesion in method) CKメトリクスは以下3つの観点から継承,結合,内部的な複雑さ,から,クラスの複雑さを評価します. 最初の2つ,DITとNOCはクラスの継承に関する複雑さを計測します. DIT(Depth…)は計測対象のクラスの継承木内の深さを数えます. NOC(Number…)は計測対象のクラスから直接導出されているクラスの数を数えます. 次の2つ,RFCとCBOはクラス間の結合に関する複雑さを計測します. RFC(Response…)はあるクラスが呼び出すメソッドの数を数えます. CBO(Coupling…)はクラスがメソッドまたは変数によって他のクラスを参照している数を数えます. 最後の2つ,WMCとLCOMはクラスの内部的な複雑度を計測します. WMC(Weighed…)はクラスのメソッドの複雑さを合計したものです. メソッドの複雑度の算出方法に関しては,いくつか方法が提案されていますが,本発表ではサイクロマチック数を用いることにしました. LCOM(Lack…)はクラスのメソッドについての凝集度の欠如を計測します. ※これらのメトリクスは,値が高いほどクラスが複雑であることを表す 本研究では,CK メトリクスを用いてリファクタリングがソフトウェア保守に与える効果を予測する手法を提案する

提案手法の概要 System プログラム解析 解析情報α CK Metricsα 解析情報β CK Metricsβ STEP1 Program 解析情報α CK Metricsα STEP1 リファクタリングの箇所/リファクタリングパターン STEP2 リファクタリング箇所とパターンを取得 リファクタリング前後のメトリクスの変化率の計算 STEP4 解析情報β STEP3 次に提案手法の概要について説明します. まず,ユーザはシステムにプログラムを入力として与え,システムは与えられたプログラムを解析します. そして,システムは解析情報を取得し,その解析情報からCKMetricsを計測します. 次に,ユーザはリファクタリングしたい箇所とリファクタリングパターンを与えます. そして,システムは取得したリファクタリング箇所とパターンを解析情報に反映させます. 最後に,修正された解析情報からCKメトリクスを計測し,リファクタリング前後のメトリクスの変化率をユーザにフィードバックするといった流れになっています. 次に,このSTEP1から4に関して,詳しく説明していきます. CK Metricsβ

STEP1:対象プログラムの解析 対象プログラムの解析を行い,CKメトリクスを計測する. CKメトリクス計測 解析情報 ソフトウェアを構成する全クラス 解析情報  ・クラス間の参照関係  ・メソッド間の参照関係  ・メソッドとフィールドの参照関係  ・メソッド内の分岐・繰り返しの数  など D B A F E まず,STEP1では,対象プログラムの解析を行い,CKメトリクスの計測を行います. 解析して得られる情報としましては, ・クラス間の参照関係 ・メソッド間の参照関係 ・メソッドとフィールドの参照関係 ・メソッド内の分岐と繰り返しの数 などが挙げられます. これらの情報を元に,CKメトリクスの計測を行います. C G CKメトリクス計測

STEP2:リファクタリング箇所とリファクタリングパターンの入力 リファクタリングしたい箇所(フィールド,メソッド,クラス)を指定し,適用したいリファクタリングパターンを与える 実装しているリファクタリングパターン フィールドの移動 フィールドの引き上げ フィールドの引き下げ メソッドの移動 メソッドの引き上げ メソッドの引き下げ クラスの抽出 スーパークラスの抽出 サブクラスの抽出 次にSTEP2ですが,ユーザはリファクタリングしたい箇所,フィールド,メソッド,クラスを指定し,適用したいリファクタリングパターンをシステムに与えます. 本研究で実装しているリファクタリングパターンはこの9つで,構造的な変化を伴うリファクタリングパターンの一部を実装しています.

STEP3:解析情報の修正(1) STEP2を元に解析情報を修正する 例:クラスAのメソッドa1()をクラスBへ移動 (1)リファクタリングの影響を受けるクラスを検出する (2)ユーザ非依存部分の修正 (3)ユーザ依存部分の修正 D B クラス メソッド Fan-in A a1() B b1() C c1() D d1() a2() ・・・ d1( ) call a1( ) b1( ) STEP2で入力された情報をもとに,解析情報を修正します. ここで,クラスAのメソッドa1()をクラスBへ移動するという例を用いて説明します. メソッドa1()は,メソッドb1,c1,d1から参照されているとすると,メソッドb1,c1,d1が属するクラスB,C,Dが影響を受けるクラスとなります. call a1( ) A a1( ) a2( ) C call a1( ) c1( )

STEP3:解析情報の修正(2) STEP2を元に解析情報を修正する 例:クラスAのメソッドa1をクラスBへ移動 (1)リファクタリングの影響を受けるクラスを検出する (2)ユーザ非依存部分の修正 (3)ユーザ依存部分の修正 A B C a2( ) D call a1( ) d1( ) a1() b1() c1( ) A B C a1( ) a2( ) D call a1( ) d1( ) b1( ) c1( ) クラス メソッド A a2() メソッドb1() Offset 命令 10 (ClassA)instA.a1() a1() ~ 次に,解析情報の修正を行います. 解析情報の修正は,ユーザ非依存部分とユーザ依存部分の2段階に分けられます. ユーザ非依存部分の修正は,システムが機械的に変換できるものに限られます. 例えば,メソッドa1()はクラスAに属しているという情報をクラスBへ移動すること, また,メソッドb1()がクラスAを参照していたのをクラスB自身の参照に変換するといった処理です. クラス メソッド B b1() (ClassB)a1() ~ a1()

STEP3:解析情報の修正(3) STEP2を元に解析情報を修正する どのインスタンスに対して呼び出すのか? 例:クラスAのメソッドA1をクラスBへ移動 (1)リファクタリングの影響を受けるクラスを検出する (2)ユーザ非依存部分の修正 (3)ユーザ依存部分の修正 メソッドd1() Offset 命令 20 (ClassA)instA.a1() D B call a1( ) d1( ) a1() b1() ~ 次に,ユーザ依存部分の修正です. メソッドd1()は,元々クラスAを参照していましたが,a1()を移動したため,クラスBに参照先を変更する必要があります. そこで,メソッドd1()内では,メソッドa1()をクラスBのどのインスタンスに対して呼び出すのかを決定しなければなりません. その際,ユーザに入力を求め,得た情報を元にどのインスタンスに対して呼び出すのかを決定します. A (ClassB)???.a1() call a1( ) a2( ) C ~ c1( ) どのインスタンスに対して呼び出すのか?

WMCの変化率= SUMWMC(A’, B’, D’, F’)- SUMWMC(A, B, D, F) SUMWMC(A, B, D, F) STEP4:CKメトリクスの計算 修正後の解析情報を元にCKメトリクスを計測 CKメトリクスの変化があったクラスに対し,メトリクスの変化率を計算 ソフトウェアを構成するクラス群 変化があったクラスのCKメトリクス WMC A’ CBO ・・・ xx DIT B’ D’ F’ 合計 D’ A B F A’ B’ F’ D B A F 変化率 xx xx ・・・ xx E STEP4では,修正後の解析情報を元にCKメトリクスの計測を行います. そして,CKメトリクスの変化があったクラスに対し,メトリクスの変化率を計算します. ここで,クラスA,B,D,Fがメトリクスの変化のあったクラスとし,それぞれのメトリクスの変化率を求めます. WMCの変化率は(リファクタリング後のクラスABDFのWMCの合計)-(リファクタリング前のクラスABDFのWMCの合計)をリファクタリング前のクラスABDFのWMCの合計で割ったものです. WMCの変化率= SUMWMC(A’, B’, D’, F’)- SUMWMC(A, B, D, F) SUMWMC(A, B, D, F) C G

提案手法の実装 提案手法の有用性を確認するために手法の実装,適用実験を行う 実装 適用実験の対象 開発言語:Java 実験対象:Java 構成 プログラム解析部(Class Construction Kit[6]) CKメトリクス計算部(ckjm[7]) 結果出力部 適用実験の対象 Feature Location Visualizer[8](以下,FLV) クラス数:37 行数:4815行 次に,提案手法の有用性を確認するために手法の実装および適用実験を行います. 実装するにあたって,開発言語はJava,また実験対象とするソフトウェアもJavaとしました. また,システムは, ・プログラム解析部 ・CKメトリクス計算部 ・結果出力部 の3つから構成されており,プログラム解析部は”Class Construction Kit”,CKメトリクス計算部は”ckjm”というオープンソースプログラムをベースに開発しました. 実験対象のプログラムとしましては,”Feature Location Visualizer”というソフトウェアを用いました. そのプログラムの規模は,クラス数37,総行数4815行です. [6]Class Construction Kit, http://bcel.sourceforge.net/cck.html [7]ckjm. http://www.spinellis.gr/sw/ckjm/ [8]檜皮祐希,松下誠,井上克郎,更新履歴情報と静的情報を用いて同一機能を実装しているクラス群を抽出する手法の提案,電子情報通信学会技術研究報告, SS2006-67, Vol.106, No.427, pp.13-18, 2006.

適用実験の概要 問題点 改善案 そのフィールドとメソッドを以下のいずれかのクラスに移動する GUIの処理と無関係なComponentList(CL)クラスにGUIの処理の一部が実装されている FLGVV CP BP GVP CL setExtractPanel() setStartClass() ExtractPanel ep; GUI 改善案 そのフィールドとメソッドを以下のいずれかのクラスに移動する case1: FeatureLocationGraphVisualizationViewer(FLGVV)クラス case2: BirdPanel(BP)クラス case3: ComponentPanel(CP)クラス case4: GraphViewPanel(GVP)クラス 適用実験の概要ですが, 適用実験の対象ソフトウェアの中で, GUIの処理と無関係なComponentListクラスにGUIの処理の一部が実装されているという問題がありました. 具体的には,ExtractPanel型の変数とそれを参照するsetExtractPanelメソッドとsetStartClassメソッドがありました. 改善案としましては,このフィールドとメソッドをGUIの処理を行う FLGVVクラス,BPクラス,CPクラス,GVPクラスのいずれかに移動するという案が挙がりました. そこで,これらのクラスへ移動する4つのケースに対してリファクタリングの効果を予測するという実験を行いました.

適用実験の結果(1) 「フィールド,メソッドの移動」は,継承の変化を伴わないのでNOC,DITは変化しない LCOMは,getter/setterは省いて計測する仕様を採用したため,値に変化がなかった. WMC,CBO,RFCは変化が見られた. WMC:変化なし CBO:減少 RFC:微量な変化 適用実験の結果です. この表は,case1のリファクタリング後のメトリクス値とその値の増減値を括弧の中に載せています. また,各項目の青は,メトリクスが減少し複雑度が改善したもの,赤はメトリクスが増加し悪化したものを表します. さらに,WMCの合計と変化率を緑で色づけしているのは,各クラスのメトリクスに変化が見られたのですが, 合計は変化しなかったということを表しています. 今回適用した,「フィールド,メソッドの移動」は,継承の変化を伴わないのでNOC,DITは変化しませんでした. また,LCOMは,getter/setterは省いて計測する仕様を採用したため,値に変化がなかった. WMC,CBO,RFCは変化が見られた. WMCは,合計に変化がなく,CBOは減少,RFCは微量に増加するという結果が得られました.

適用実験の結果(2) 変化率をクラス数で正規化し,case1~4を比較. case1 case2,3,4 WMCは変化なし RFCは微量な変化 case1 リファクタリング後のCBOの値は減少し,一番良い結果が得られた. case2,3,4 リファクタリング後のCBOは増加してしまった. 次に,case1-4で,メトリクスの変化率をクラス数で正規化し,それぞれ比較を行いました. この結果から,すべてのcaseにおいて,WMCは変化がなく,RFCは微量な変化という結果が得られました. また,case1においては,リファクタリング後のCBOの値は減少し,他のリファクタリングよりも良い結果が得られました. case2,3,4においては,リファクタリング後のCBOの値は増加してしまうという結果が得られました.

考察 開発者の主観でリファクタリングを行うと,case2,3,4のようにソフトウェアが構造的に悪化する危険があるため,本手法を用いて比較することは重要 本手法では,リファクタリング前後のメトリクスの値だけでリファクタリングを評価しているが,より正確に評価するためには,ソースコード修正にかかるコストやテストにかかるコストも考慮するべき 最後に考察ですが, 開発者の主観でリファクタリングを行うとcase2,3,4の場合を適用してしまう可能性があり,ソフトウェアが構造的に悪化する危険があるため本手法を用いて比較することは重要であると考えています. しかし,本手法では,リファクタリング前後のメトリクスの値だけでリファクタリングを評価していますが,より正確に評価するためには,ソースコードの修正にかかるコストやテストにかかるコストも考慮するべきだと考えています.

まとめ まとめ 今後の課題 リファクタリングがソフトウェア保守に与える効果を予測する手法を提案した. その手法の適用実験を行い,有用性を評価した. 複数のリファクタリング候補を与え,それらの評価の比較を行った. 今後の課題 「クラスのインライン化」など,構造的な変化を伴う未実装なリファクタリングに関しても実装したい ソースコード修正にかかるコスト,テストにかかるコストを考慮し,手法を改良したい 最後にまとめです. (スライドに書いてることを言う)