オブジェクト指向型言語での

ソースコードに対して
適用可能な編集手順を探索する
リファクタリング支援手法の提案
譜久島亮,吉田則裕,松下誠,井上克郎
大阪大学
大学院情報科学研究科
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
1
発表の概要




リファクタリングとは
メンバの移動
リファクタリング支援機能の問題点
編集手順を探索するリファクタリング支援手法
 探索の例
 提案手法の処理概要
 ケーススタディ
 まとめと今後の課題
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
2
リファクタリング
 リファクタリングの定義
 外部から見たプログラムの振る舞いを変えずにプログラムの
内部の構造を改善する作業[1]
 リファクタリングの目的
 欠陥の発見を容易にする
 プログラムの可読性を上げる
 機能追加をしやすくする
 典型的なリファクタリングがまとめられている[1]
 メソッドの抽出
 フィールドの移動
 メソッドの移動
開発者が頻繁に行う
リファクタリング[2]
[1] M. Fowler : Refactoring: improving the design of existing code, Addison Wesley (1999).
[2] G. C. Murphy, M. Kersten and L. Findlater: “How Are Java Software Developers Using the
Eclipse IDE?’’, IEEE Softw.,23, 4, pp. 76-83(2006)
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
3
メンバ(フィールド,メソッド)の移動
 動機
 適切なクラスにメンバを移動し
クラスの機能を明確にする
 他のリファクタリングにも利用
 クラスの抽出
 クラスのインライン化
処理内容がClassAに
に不適切なメソッド
ClassA{
….
method( ){
….
}
}
移動されたメソッド
ClassB{
method( ){
} ….
}
}
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
4
メンバの移動に必要な検討の目的
 移動するメンバと関連があるメンバの移動
 関連があるメンバも移動しクラスの機能をより明確にする
 移動先クラスと移動元クラス間の参照方法の変更の検討
 メンバの移動後もメンバ間で参照関係を保つことで振る舞い
を保存する
移動先クラス
移動元クラス
class Rental{
public void
print(Customer c);
関連するメンバ
public int
public void print( );
count(Customer c);
移動するメンバ
public int count( );
}
・・・
内部
}
内部
内部
内部
・・・
・・・
・・・
c.mList[i].
mList.length( );
mList[i].getName( ); c.mList.length( );
getName( );
class Customer{
public List mList ;
・・・
・・・
・・・
・・・
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
5
メンバの移動により参照切れが起こる場合
 privateメンバの移動
 privateメンバを参照しているメンバの移動
プログラムの振る舞いの保存のために
参照切れを解消するメンバの移動や参照方法の検討が必要である
被参照メンバ
class A{
private Type memberA ;
memberB;
}
class B{
参照メンバ
}
(a) メンバの移動前
ソースコード
class A{
private Type memberA ;
}
class B{
memberB;
}
class A{
memberB;
}
class B{
private Type memberA ;
}
(b) memberBをBへ移動 (c) memberAをBへ移動
したソースコード
したソースコード
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
6
参照切れを解決する編集例(1/2)
class Customer {
private List mList;
Rental rental;
public void print( );
public int count( );
}
移動
class
Rental { 移動
}
class Rental {
}public int count(Customer c);
}
class Customer { 被参照メンバの
カプセル化
Rental rental;
private List mList;
public void print( );
public List getMovie( );
public void setMovie(List m);
}
class Rental {
public int count(Customer c);
}
(a) メンバの移動後の
参照切れを含むソースコード
(b) 被参照メンバの
カプセル化を行ったソースコード
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
7
参照切れを解決する編集例(2/2)
class Customer {
private List mList;
Rental rental;
public void print( );
移動
}
class Rental {
public int count(Customer c);
}
(a) メンバの移動後の
参照切れを含むソースコード
class Customer {
Rental rental;
フィールドの移動
}
メソッドの移動
class Rental {
private List mList;
public void print( );
public int count( );
}
(b) メンバの移動を
行ったソースコード
ソースコードや開発者の意図より編集手順が複数存在する
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
8
リファクタリング支援機能
 統合開発環境Eclipseではリファクタリング支援機能が
提供されている
 メソッドの移動 → 選択されたメソッドの他クラスへの移
動を支援
 親クラスの抽出 → 選択されたソースコードの親クラス
の作成を支援
既存のリファクタリング支援機能にはリファクタリングに伴なう
複数の編集手順を提示できるものが確認できない


目的のソースコードを得るための編集手順が選択が困難である
編集の適用や取消を繰り返すことにより編集作業に時間がかかる
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
9
参照切れが発生するメンバの移動例
ソースコードの遷移
Eclipseでのメンバの移動の例
カプセル化
元に戻す
class Customer { 移動
private List mList ;
Rental rental;
public void setMovie(List
移動
m) { int count( ){
public
…mList = m;
} mList.length( );
}public List getMovie() {
return mList;
}
public
void print( ) {
public
… void print( ){
…getMovie(
).getName(
mList[i].getName(
); ); );
rental.mList[i].getName(
}}
}
class Rental {
private List mList;
public int
count(Customer
count( ){
c){
….
c.getMovie
mList.length(
c.mList.length(
); );
}
.length( );
}}
メソッドを
移動
元に
戻す
カプセル化
フィールド
を移動
問題点
 手戻りにより作業時間がかかる
 目的とするソースコードが得にくい
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
10
研究の目的について
リファクタリングを行う際に
適用可能な編集手順を探索する


リファクタリング完了までの編集手順
編集手順を適用したソースコード
編集の取り消しを防ぎ、作業時間が短縮
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
11
提案手法
適用可能な編集手順の探索結果の例
「メソッドの移動」リファクタリングの編集手順探索の例
Customer.
countを
Rentalへ移動
Customer.mList
の修飾子を
publicに変更
Rental.mList
の修飾子を
publicに変更
Customer.mList
をRentalへ移動
Customer.mList
のカプセル化
Customer.print
をBへ移動
Rental.mList
のカプセル化
コンパイル可能なソースコード
コンパイルエラーを含むソースコード
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
12
適用可能な編集ステップ
参照切れコンパイルエラーを解決する編集ステップ
修飾子の変更
メンバの移動
被参照メンバの修飾子 移動先クラスへメンバを
を変更する
移動する
private Type value ;
public Type value ;
class A{
private Type value ;
…
};
class B{
フィールドのカプセル化
フィールドが所属するクラ
スにgetterメソッドとsetter
メソッドを作成する
class A{
private Type value ;
public void
set(Type t) {
this.value = t;
}
public Type get( ) {
return value;
}
};
}
コンパイルエラーが存在するソースコードに適用
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
13
提案手法の処理概要
1. 編集ステップ導出のために以下の情報を取得
 移動元クラスと移動先クラス
 被参照メンバとその所属クラス
 参照メンバとその所属クラス
2. 参照切れを解決する編集ステップを導出
 被参照メンバの修飾子の変更
 移動先クラスへのメンバの移動
 被参照メンバのカプセル化
3. 参照切れを含むソースコードに各編集ステップを適用
4. 編集ステップを適用したソースコードで参照切れを含む
ソースコードについて1~3の処理を行う
5. ソースコードと適用した編集ステップを木構造で構築
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
14
編集ステップ導出のための情報取得
 適用したメンバの移動より情報を取得
 移動元クラス
 移動先クラス
被参照メンバ
class A{
private Type memberA ;
memberB;
}
class B{
 参照切れより情報を取得
 被参照メンバとその所属クラス
 参照メンバとその所属クラス
参照メンバ
メンバの移動
}
移動元クラス
移動元クラス
A
移動先クラス
B
被参照メンバ
memberA
被参照メンバの所属クラス
A
参照メンバ
memberB
参照メンバの所属クラス
B
class A{
private Type memberA ;
}
移動先クラス
class B{
memberB;
}
A.memberAは不可視
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
15
提案手法の処理概要
1. 編集ステップ導出のために以下の情報を取得
 移動元クラスと移動先クラス
 被参照メンバとその所属クラス
 参照メンバとその所属クラス
2. 参照切れを解決する編集ステップを導出
 被参照メンバの修飾子の変更
 移動先クラスへのメンバの移動
 被参照メンバのカプセル化
3. 参照切れを含むソースコードに各編集ステップを適用
4. 編集ステップを適用したソースコードで参照切れを含む
ソースコードについて1~3の処理を行う
5. ソースコードと適用した編集ステップを木構造で構築
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
16
編集ステップの導出(1/3)
 被参照メンバの修飾子の変更
被参照メンバ
移動元クラス
A
移動先クラス
B
被参照メンバ
memberA
被参照メンバの所属クラス
A
参照メンバ
memberB
参照メンバの所属クラス
B
編集ステップ
class A{
private Type memberA ;
}
class B{
memberB;
}
class A{
public Type memberA ;
}
class B{
memberB;
}
memberAの修飾子をpublicに変更
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
17
編集ステップの導出(2/3)
 移動元クラスから移動先クラスへメンバの移動
移動元クラス
移動元クラス
A
移動先クラス
B
被参照メンバ
memberA
被参照メンバの所属クラス
A
参照メンバ
memberB
参照メンバの所属クラス
B
class A{
private Type memberA ;
}
class B{ 移動先クラス
memberB;
}
class A{
}
class B{
private Type memberA ;
memberB;
}
編集ステップ
移動元クラスであるAに所属している
memberAを移動先クラスであるBへ移動
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
18
編集ステップの導出(3/3)
 被参照メンバのカプセル化
(被参照メンバがフィールドの場合)
被参照メンバ
memberA
被参照メンバの所属クラス
A
参照メンバ
memberB
参照メンバの所属クラス
B
移動元クラス
A
移動先クラス
B
編集ステップ
memberAのgetter,setterを
Aに追加
被参照メンバ
class A{
private Type memberA ;
}
class B{
memberB;
}
class A{
private Type memberA ;
public void set(Type type){
memberA = type;
}
public Type get( ){
return memberA;
}
}
class B{
memberB;
}
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
19
提案手法の処理概要
1. 編集ステップ導出のために以下の情報を取得
 移動元クラスと移動先クラス
 被参照メンバとその所属クラス
 参照メンバとその所属クラス
2. 参照切れを解決する編集ステップを導出
 被参照メンバの修飾子の変更
 移動先クラスへのメンバの移動
 被参照メンバのカプセル化
3. 参照切れを含むソースコードに各編集ステップを適用
4. 編集ステップを適用したソースコードの参照切れが解決さ
れるまで1~3の処理を行う
5. ソースコードと適用した編集ステップを木構造で構築
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
20
編集ステップの適用と繰り返し処理
メンバの移動
ソースコード
情報の抽出
取得
参照切れを含
むソースコード
編集ステップ
の適用
参照切れの情報
適用済
編集ステップ
導出
履歴の取得
編集ステップを適
用したソースコード
適用可能な
編集ステップ
履歴の保持
編集ステップ
ソースコード
構築
編集ステップを有効辺
ソースコードを頂点とする木
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
21
ケーススタディの概要
 右の例に対して提案手法を適用
 Customer.count,Customer.print
はprivateフィールド
Customer.mListを参照
 Customer.countをRentalへ移動す
る
被参照メンバ
Customer.mList
被参照メンバの所属クラス
Customer
参照メンバ
Rental.count
参照メンバの所属クラス
Rental
移動元クラス
Customer
移動先クラス
Rental
class Customer {
class Customer {
private List mList ;
private List mList ;
public void print( ) {
public int count( ){
…
…
mList[i].getName( );
mList.length( );
…
…
}
}
}
public void print( ) {
class Rental{
…
public int
mList[i].getName( );
count(Customer C){
…
…
}
メソッドの移動
c.mList.length(
);
}
…
class Rental{
}
}
}
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
22
編集ステップの導出(修飾子の変更)
被参照メンバ
Customer.mList
編集ステップ
Customer.mListの修飾子をpublicに変更
Customer.mList
の修飾子を
publicに変更
Customer.
countを
Rentalへ移動
class Customer {
privateList
public
ListmList
mList;;
public void print( ) {
…
mList[i].getName( );
…
}
}
class Rental{
public int
count(Customer C){
…
c.mList.length( );
…
}
}
編集手順とソースコードを保持
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
23
編集ステップの導出(メンバの移動)
被参照メンバ
Customer.mList
被参照メンバの所属クラス
Customer
移動元クラス
Customer
移動先クラス
Rental
編集ステップ
Customer.mListをRentalへ移動
Customer.
countを
Rentalへ移動
Customer.mList
の修飾子を
publicに変更
Customer.mList
をRentalへ移動
編集手順とソースコードを保持
class Customer {
class Customer {
private List mList ;
private List mList ;
public void print( ) {
public void print( ) {
…
…
mList[i].getName( );
mList[i].getName( );
…
…
}
}
}
}
class Rental{
class Rental{
private List mList ;
public int
public int
count(Customer c){
count(Customer c){
…
…
c.mList.length( );
c.mList.length( );
…
…
}
}
}
}
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
24
編集ステップの導出(カプセル化)
被参照メンバ
Customer.mList
被参照メンバの所属クラス
Customer
編集ステップ
Customer.mListのgetter,setterを追加
Customer.mList
の修飾子を
Customer. publicに変更
countを
Customer.mList
Rentalへ移動
をRentalへ移動
Customer.mList
のカプセル化
編集手順とソースコードを保持
class Customer {
class List
Customer
private
mList ;{
private
mList ;
public
voidList
setMovie(List
m){
public
mList void
= m; print( ) {
…
}
mList[i].getName(
public
List getMovie( ){ );
… mList;
return
} }
}
public
void print( ) {
class Rental{).getName( );
…getMovie(
…}public int
count(Customer c){
}
class …
Rental{
c.mList.length(
);
public
int
…
count(Customer
c){
}
…c.getMovie( ).length( );
} }
…
}
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
25
編集ステップ導出・適用の繰り返し処理
 編集ステップを適用したソースコードで参照切れコンパイルエ
ラーを含むソースコードについて繰り返し編集ステップの導出・
適用を繰り返す
Customer.
countを
Rentalへ移動
Customer.mList
の修飾子を
publicに変更
Rental.mList
の修飾子を
publicに変更
Customer.mList
をRentalへ移動
Customer.mList
のカプセル化
Customer.print
をBへ移動
Rental.mList
のカプセル化
ソースコードから以下を得ることができた
Customer.countを移動した際の適用可能な編集手順
コンパイル可能なソースコード
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
26
ケーススタディの考察
 適用可能な編集手順とコンパイル可能なソースコードを
得ることができた
 開発者が参照切れを解決する編集作業を行わなくてす
むので有用と言える
 開発者が複数のソースコードから目的のソースコードを
選択するためのユーザーインターフェースが必要である
 提案手法で探索した編集手順は「メンバの移動」リファ
クタリングの編集手順の部分的な編集手順である
 参照切れを解決する編集手順のみを探索している
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
27
まとめと今後の課題
 まとめ
 参照切れが発生するメンバの移動に伴なう適用可能な編集
手順の探索を行った
• 適用可能な編集手順とコンパイル可能なソースコードを得るこ
とができた
 今後の課題
 開発者にコンパイル可能な複数のソースコードの差異を示し、
目的のソースコードの選択を支援するようなインターフェース
が必要
 探索できる編集手順を増やす
• 移動するメンバと参照関係のあるpublicメンバの移動など
 提案手法の評価
• 提案手法を用いた場合と用いなかった場合のリファクタリング
作業時間の測定
SIGSS
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
28