社団法人 電子情報通信学会
THE INSTITUTE OF ELECTRONICS,
INFORMATION AND COMMUNICATION ENGINEERS

信学技報
TECHNICAL REPORT OF IEICE.

ソースコードの “自然さ” を用いたリファクタリング評価手法の検討
有馬諒†

肥後 芳樹†

楠本 真二†† 大阪大学大学院情報科学研究科〒 565-0871 大阪府吹田市山田丘 1-5
E-mail: †{r-arima,higo,kusumoto}@ist.osaka-u.ac.jp
あらまし

リファクタリングとはソフトウェアの外部的振る舞いを保ちながら内部構造を改善する作業と定義されており，ソフトウェアの保守性を向上させるために重要な作業である．しかし，Extract method と Inline method のように対立するリファクタリング手法も存在するため，どのようなリファクタリングを行うかは開発者の経験や勘に基づいて評価される場合が多い．そこで本研究では，開発者の経験や勘によらない定量的なリファクタリングの評価として，ソースコードの “自然さ” を用いる手法を提案する．自然さとは自然言語処理の手法である言語モデル
を用いて，ソースコードがどの程度自然かを数値で表したものである．本研究では提案手法の評価のために，実際のソースコードに対して行われたリファクタリングに対して本手法を適用した．その結果，28 個のリファクタリン
グのうち，19 個のリファクタリングにおいて良いリファクタリングであると評価された．そのため，開発者によって行われたリファクタリングと，提案手法によって良いと評価されたリファクタリングが対応していると考えられ，提案手法がリファクタリングの評価に有効であることを確認した．
キーワード

自然さ，リファクタリング

1. ま え が き

ソッドに分解された処理を 1 つのメソッドに統合するリファ
クタリングである．必要以上に細かく分割されたメソッドを

近年，ソフトウェアの大規模化，複雑化によってソフトウェ

統合することで可読性が向上するといわれている．このようア保守の作業量は増加しており，ソフトウェアの保守性を保に Extract Method リファクタリングと Inline Method リファ

つためにもソースコードの品質は重要である．しかし，機能

クタリングは互いに対立したリファクタリングであり，どちらの追加や変更，バグ修正などによって，ソースコードには変更を適用するかはメソッドの規模や処理内容などから開発者がを加えられ続けるため，ソースコードの品質は徐々に低下し判断しなければならない．このような状況において，リファていく [1]．このような品質の低下を抑えるために，リファククタリングの評価を何らかの方法で数値化しどちらの状態がタリングという作業が行われる．リファクタリングとは，ソよりよいか比較できるようになれば，リファクタリングを行

フトウェアの外部的な振る舞いを変えずに内部構造を改善すう開発者の支援になると著者らは考える．

る作業である．リファクタリングによって，ソースコードのそこで本研究では，“自然さ” を用いてリファクタリングを

品質を向上させることができる．Fowler らは，リファクタリ

評価する手法を提案する．自然さとは，自然言語処理の手法

ングすべきソースコードの状態とそのリファクタリング方法

である言語モデルを用いて求められる指標であり，単語列がについてまとめている [2]．しかし，ソースコード中のどの部ある言語としてどれだけもっともらしいかを数値で表したも分にどのようなリファクタリングを適用するかは，開発者ののである．近年，自然さをソースコードに応用する研究が盛経験や勘によるものが大きく，リファクタリングを行うこと

んに行われており，コード補完 [3] や，バグ検出 [4] などで成果を難しくしている．

が報告されている．提案手法ではリファクタリングを数値に

開発者の経験や勘が必要なリファクタリングの例として，

よって評価することができるため，複数のリファクタリング

Extract Method と Inline Method がある．Extract Method リの候補が存在する場合，提案手法を用いてどのリファクタリ

ファクタリングとは，ソースコード中の処理をメソッドとしングが最も良いかを比較することができる．

て切り出すリファクタリングである．このリファクタリング

提案手法の評価のために，実際のソースコードに対して行

によって，重複した処理を再利用できること，意味のある処

われたリファクタリングに対して提案手法を適用した．その理の単位を 1 つのメソッドとしてまとめて名前をつけること

結果，28 個のリファクタリングのうち，19 個のリファクタリ

でソースコードの可読性が向上することなどの利点があげらングにおいて良いリファクタリングであると判定された．それる．また Inline Method リファクタリングとは，複数のメのため多くのリファクタリングにおいて，開発者によって行—1—

モデル推定用
ソースコードコーパス

Phase 1 言語モデル生成

言語モデル

トークン列

Step 2
モデル推定

Step 1
字句解析

Phase 2 スコア計算

計測対象
ソースコードトークン列
Step 1
字句解析

自然さ

スコア

Step 2
自然さ計測

Step 3
スコア計算

図 1 提案手法の概要

われたリファクタリングと，提案手法によって良いと評価さ従って，単語列 S = w1 w2 · · · wm の自然さ N (S) は以下のよ

れたリファクタリングが対応していると考えられる．

うになる．

以降，2 章では本研究の背景として言語モデルと自然さについて述べる．3 章では提案手法について述べる．4 章では提案

N (S) = log P (w1 ) +について述べる．

言語モデルや自然さは自然言語処理において，機械翻訳や音声認識などで用いられている．
2. 2

2. 背
2. 1

景

Hindle らは，自然言語処理の手法である言語モデルをソー言語モデルと自然さ

確率モデルである．言語モデルを用いることで，単語列の “ 自然さ” を数値で表すことができる．単語列 S = w1 w2 · · · wmが与えられたときその生成確率は，各単語の条件付確率の積効であることを示した [3]．
Allamanis らは，言語モデルを用いて最適な識別子名の推薦する手法を提案した [5]．
Ray らは，バグを含むソースコードと自然さについて調査を行った [4]．この研究では，ソースコードにおいて，バグをを用いて次のように表される．
P (S) = P (w1 )ソースコードにおける自然さ

スコードに適用し，言語モデルがソースコードに対しても有言語モデルとは単語列に対してその生成確率を割り当てるm∏log P (wi |wi−n+1 , · · · , wi−1 ) (5)i=2

手法の評価のために行った実験について述べる．5 章では妥当性の脅威について述べ，最後に 6 章ではまとめと今後の課題

m∑

含む行は自然さが低い傾向があることを示し，またバグ修正
P (wi |w1 , · · · , wi−1 )(1)によって自然さが向上する傾向があることを示した．これらの事実から自然さをバグ検出に応用する手法を提案した．

i=2

ここで P (wi |w1 , · · · , wi−1 ) は，単語列 w1 , · · · , wi−1 の次の単語が wi である確率である．P (wi |w1 , · · · , wi−1 ) は，単語列
w1 , · · · , wi−1 の組み合わせが膨大になるため，直接求めるこ

本研究では，ソースコードの自然さをリファクタリングの評価に用いる手法を提案する．

3. 提 案 手 法とは現実的ではない．そこで，以下のように直前の n − 1 個の単語から次の単語の確率を求める n − gram 言語モデルを考本研究では，ソースコードの自然さを用いてリファクタリ
ングを評価する手法を提案する．提案手法に用いるアイデア

える．

は以下のとおりである．開発者は，複雑で理解しづらく可読P (wi |w1 , · · · , tw−1 ) ≃ P (wi |wi−n+1 , · · · , wi−1 )(2)性の低いソースコードが，単純で理解しやすく可読性の高い

P (wi |wi−n+1 , · · · , wi−1 ) はコーパス中の単語列の頻度から，最ソースコードとなるようにリファクタリングを行う．自然な尤推定によって以下のように求められる．

ソースコードというのは，学習に用いたソースコードと似たP (wi |wi−n+1 , · · · , wi−1 ) =C(wi−n+1 , · · · , wi−1 , wi )C(wi−n+1 , · · · , wi−1 )書き方であるソースコードであり，学習に用いたソースコー(3)

こ こ で C(wi−n+1 , · · · , wi−1 ) は コ ー パ ス 中 で 単 語 列
wi−n+1 , · · · , wi−1 が出現した回数を表す．
P (wi |wi−n+1 , · · · , wi−1 ) は，非常に小さな値となることが多いためそのままでは扱いづらい．そこで，本研究では単語 wiの自然さ N (wi ) を，以下のように単語の確率の対数とする．
N (wi ) = log P (wi |wi−n+1 , · · · , wi−1 )(4)

ドの可読性が高いならば，自然なソースコードというのは可読性の高いソースコードとなる．このことから，リファクタ
リングと自然さの関係について以下の仮説をたてた．
学習に用いたソースコードが単純で理解しやすく可読性の高いソースコードであれば，開発者がリファクタリングを行うことによって自然さの低い行が減少する．
本研究ではこの仮説をもとに，自然さを用いてリファクタリ
ングを評価する手法を提案する．提案手法の概要を図 1 に示
—2—List<Integer> list = getParameterList();(1) 識別子をそのまま1つのトークンとする
List< Integer > list

= getParameterList( ) ;(2) 識別子を単語ごとに分割する
list< integer > list

public void add(String left, String right){
int leftValue = 0;
for(int i = 0; i < left.length(); i++){leftValue *= 16;
leftValue += 'A' <= left.charAt(i) && left.charAt(i) <='F' ? left.charAt(i) - 'A' + 10 : left.charAt(i) - '0';}= get parameter list ( ) ;(3) 識別子を種類ごとに正規化する<Type> < <Type>> <Var> = <Method>( ) ;図 2 字句解析の実行例

自然さ

-4.4
-8.7
-6.6
-73.6
-0.8

int rightValue = 0;
for(int i = 0; i < right.length(); i++){rightValue *= 16;
rightValue += 'A' <= right.charAt(i) && right.charAt(i) <='F' ? right.charAt(i) - 'A' + 10: right.charAt(i) - '0';
}

-3.6
-8.4
-6.6
-73.8

System.out.println(leftValue + " " +-7.9

rightValue);

-0.8

}
0

図4

リファクタリング対象ソースコード−5

public void add(String left, String right){
int leftValue = convertHex(left);
int rightValue = convertHex(right);
System.out.println(leftValue + " " + rightValue);}Line naturalness

−10
−15
−20
−25
−30
−35
0

20

40

60

80

100

Percentile

public int convertHex(String str){
int value = 0;
for(int i = 0; i < str.length(); i++){value *= 16;value += 'A' <= str.charAt(i) && str.charAt(i) <= 'F' ?
str.charAt(i) - 'A' + 10: str.charAt(i) - '0';}
return value;}

図 3 スコア計算の例

す．提案手法の入力は，言語モデル推定用ソースコードコー
パスと，計測対象ソースコードであり，出力は計測対象ソース
コードのスコアである．このスコアはより自然なソースコー
ドであるほど減少するため，リファクタリングによって提案
手法のスコアが減少するならば，良いリファクタリングであると評価することができる．
提案手法は以下の 2 つの Phase からなる．
Phase 1

言語モデル生成Phase 2

スコア計算

以降，各 Phase について説明する．
3. 1

図5

public int convertHex(String str){
int value = 0;
for(int i = 0; i < str.length(); i++){value *= 16;char c = str.charAt(i);if('A' <= c && c <= 'F'){
value += c - 'A' + 10;}else{
value += c - '0';}}
return value;
}

図6

-9.3
-7.8
-8.1

-5.3
-5.8
-9.1
-60.6
-0.8
-3.5

メソッド切り出し後のソースコード

public void add(String left, String right){
int leftValue = convertHex(left);
int rightValue = convertHex(right);
System.out.println(leftValue + " " + rightValue);}

言語モデル生成

自然さ

自然さ
-9.3
-7.8
-8.1

-5.3
-5.8
-9.1
-6.8
-7.5
-12.3
-1.5
-11.8
-0.8
-0.8
-3.2

一時変数の導入後のソースコード

Phase 1 では学習用ソースコードコーパスから，言語モデルを構築する．この Phase は以下の 2 つの Step からなる．
Step 1

字句解析

Step 2

モデル推定

Step 1 では，ソースコードを解析し，トークンの並びに分解する．本研究ではソースコードのうち，メソッドの本体部分のみを用いた．その際問題となるのは，識別子名の扱いである．
ソースコード中のクラス名やメソッド名，変数名などの識別子
名は開発者が自由に決めることができ，多くの場合複数の英単語を組み合わせて 1 つの識別子名とする．そのため，ソース
コード中に含まれる識別子名の種類が膨大になり，うまくモデルを推定できない可能性がある [6]．また，似た単語から構成される識別子も全く別の識別子としてみなしてしまうとい
う問題もある．そこで，以下の 3 つの戦略で識別子名を扱う．
（ 1 ） 識別子をそのまま 1 つのトークンとする．
（ 2 ） 識別子を単語ごとに分割する．
（ 3 ） 識別子を種類ごとに正規化する．

字句解析の例を図 2 に示す．
Step 2 では，字句解析に得られたトークン列から，言語モデ
ルを推定する．本手法では，2 種類の言語モデル推定器を用いた．1 つ目は KenLM [7] である．これはスムーシングに，自然言語処理において高い性能を示している modified Kneser-Ney
smoothing [8] を用いた n-gram 言語モデルである．
2 つ目は Tu らの研究 [9] によって用いられた言語モデルである．ソースコードではローカル変数など局所的に頻度が高まるトークンが存在することが知られており，この特徴を考慮するためにキャッシュの仕組みを導入した n-gram 言語モデ
ルである．
3. 2

自然さ計測

Phese 2 では，Phese 1 で構築した言語モデルを用いて計測
対象ソースコードの自然さを計算し，この自然さをもとにスコアを計算する．この Phese は以下の 3 つの Step からなる．
Step 1

字句解析—3—

Step 2

自然さ計測

少するようにリファクタリングを行う」が成り立ち，開発者にStep 3

スコア計算

よって行われたリファクタリングと，提案手法によって良い

Step 1 では，Phase 1 と同様に計測対象ソースコードの字句と評価されたリファクタリングが一致しているかを確認した．

解析を行う．ここでは，Phase 1 の際の戦略と同じものを用い

4. 1

実験方法

る必要がある．Step 2 では，Step 1 で得られたトークン列に

学習用ソースコードコーパスには，Higo らによって作成

対して，Phase 1 で生成した言語モデルを用いて行ごとの自然されたデータセット [10] を用いた．これは Apache Software

さを計測する．Step 3 では，計測した自然さをもとに，以下Foundation（注 1）の Java プロジェクトから作成されたデータセッのようにスコアを計算する．

トである．データセットの概要を表 1 に示す．

1 ∑score =
max(0, threshold − N (Li ))M

リファクタリングの評価対象には，JUnit4（注2）を用いた．こ

M

(6)

i=0

れは Java 用の単体テスト自動化フレームワークであり，JUnit4
自体も Java によって実装されている．JUnit4 は GitHub に

ここで，M は計測対象ソースコードの行数，threshold は閾

よって管理されており，GitHub を用いた開発者相互による値，N (Li ) は i 番目の行の自然さを表す．本研究では，閾値にソースコードレビューによってソースコードの品質が担保さ

学習用ソースコードコーパスにおける自然さの分布の中央値れている．

を用いる．このスコアが低いほど自然なソースコードである．

本研究では JUnit4 リポジトリから，リファクタリングのみ

このスコア計算の意味を図 3 を用いて説明する．図 3 は，各が行われたコミットを抽出し，それを評価対象として用いた．

行の自然さを低い順に並び替え，x 軸 0 から 100 の間にプロッ

まず，コミットメッセージにリファクタリングに関連があるとトしたグラフである．中央値を破線としたとき提案手法のス思われるキーワードを含むコミットを抽出した．本実験ではコアはこの破線より下の部分の面積であり，面積が小さいほキーワードとして refactor，clean を用いた．次に抽出されたど自然なソースコードとなる．

コミットを目視で確認し，変更内容がリファクタリングのみ

こうして得られたスコアをリファクタリングの前後で比較であり，処理の内容を変えないコミットのみを抽出した．こしスコアが減少しているならば，このリファクタリングは良うして抽出した 28 コミットを評価対象として用いた．対象リ

いリファクタリングであると提案手法は評価する．

ポジトリのメトリクスを表 2 に示す．

3. 3

適 用 例

抽出した各コミットについて，変更前のソースコードと，変リファクタリングによるスコアの変化の例を図 4 のソース

更後のソースコードのそれぞれに対して提案手法を適用し，そコードを用いて示す．図において，add メソッドは 16 進数でれぞれのスコアを求めた．このときスコア計算に必要な閾値表された 2 つの文字列の加算結果を出力するメソッドである．

は，学習用ソースコードコーパスに対して交差検定を行って学習用ソースコードコーパスにおける自然さの中央値が −5.7

行ごとの自然さの分布を求め，その中央値を用いた．こうしであったため，このソースコードのスコアは 145.6 であった．

て求めたスコアが変更の前後で増加しているか，減少していまず，16 進数文字列を数値に変換する処理が重複している

るかを確認した．

ため，この処理をメソッドとして切り出すリファクタリング

4. 2を行った．この結果を図 5 に示す．このソースコードのスコ実験結果を，表 3 に示す．最も性能の良い言語モデルと識アは 66.6 であり，リファクタリングによって元のソースコー

別子処理の組み合わせでの場合で，28 個のリファクタリング

ドよりもスコアが減少した．

のうち 19 個で提案手法によるスコアが減少した．この結果か

結果さらに，16 進数の各桁を処理する行は，1 つの行で多くの処ら，多くのリファクタリングで開発者によって行われたリファ理を行っているため，この行を分解するリファクタリングを

クタリングと，提案手法によって良いと評価されたリファクタ

行った．この結果を図 6 に示す．このソースコードのスコア

リングが対応しているといえる．変化なしとなった 3 つのリは 27.3 であり，図 5 のソースコードよりもさらに自然なソー

ファクタリングは，フィールド変数の修飾子の変更やメソッ

スコードとなったといえる．
表 2 JUnit リポジトリの詳細

4. 評 価 実 験

期間2000/12/03 - 2017/10/16

本章では，提案手法の評価のために行った実験について述べ最新コミットでのファイル数449

る．この実験では，オープンソースソフトウェアにおいて実際

最新コミットでの LOC

43161に行われたリファクタリングに対して提案手法を適用するこ

全コミット数

2195とで，提案手法で用いた仮説「開発者は，自然さの低い行が減キーワードを含むコミット数354

目視確認による
表 1 データセットの概要
プロジェクト数
ファイル数
LOC

リファクタリングコミット数

28

84
66,724
11,545,556（注 1）：http://www.apache.org/（注 2）：https://github.com/junit-team/junit4—4—+ private Collection<T> getFilteredChildrenWithoutIgnores(+
final RunNotifier notifier) {+final Collection<T> filteredChildren= getFilteredChildren();+Collection<T> filteredChildrenCopy= new ArrayList<T>(filteredChildren);++for (T child : filteredChildren) {+if (isIgnoredMethod(child)) {+Description childDescription= describeChild(child);+
notifier.fireTestIgnored(childDescription);+
filteredChildrenCopy.remove(child);
+
}
+
+
}
+
+
return Collections+.unmodifiableCollection(filteredChildrenCopy);
+
+ }

12

Number of commits

10
8
6
4
2
0
−4

−3

−2

−1
0
1
Change in the score

2

3

4

自然さ
-60.1

-55.3

-47.6
-43.7
-29.2
-29.6
-31.4
-14.1
-6.2
-20.6
-24.5

図 7 リファクタリングによるスコアの変化量(a) 切り出されたメソッド

自然さ+ private List getAnnotatedFieldsByParameter() {+return getTestClass().getAnnotatedFields(Parameter.class); -50.5+ }protected Statement childrenInvoker(final RunNotifier notifier) { 自然さfinal Collection<T> filteredChildren= getFilteredChildren();-61.6
Collection<T> filteredChildrenCopy=-56.0
new ArrayList<T>(filteredChildren);for (T child : filteredChildren) {-48.2
if (isIgnoredMethod(child)) {-44.2
Description childDescription= describeChild(child);-29.4
notifier.fireTestIgnored(childDescription);-29.9
filteredChildrenCopy.remove(child);
-31.8
}
-14.3
}
-6.2
final Collection<T> filteredChildrenWithoutIgnores=Collections -23.7.unmodifiableCollection(filteredChildrenCopy);-24.7+
final Collection<T> filteredChildrenWithoutIgnores=-65.2
getFilteredChildrenWithoutIgnores(notifier);+ private boolean fieldsAreAnnotated() {+return !getAnnotatedFieldsByParameter().isEmpty();
+ }

-44.2

(a) 切り出されたメソッド
自然さ@Override
protected void validateConstructor(List<Throwable> errors) {validateOnlyOneConstructor(errors);-19.2
List<FrameworkField> annotatedFieldsByParameter =-84.4
getTestClass().getAnnotatedFields(Parameter.class);
if (annotatedFieldsByParameter.size() > 0) {-62.3+
if (fieldsAreAnnotated()) {-32.1
validateZeroArgConstructor(errors);-2.9}}@Override
protected void validateFields(List<Throwable> errors) {super.validateFields(errors);
List<FrameworkField> annotatedFieldsByParameter =getTestClass().getAnnotatedFields(Parameter.class);
if (annotatedFieldsByParameter.size() > 0) {+if (fieldsAreAnnotated()) {+List<FrameworkField> annotatedFieldsByParameter =getAnnotatedFieldsByParameter();

-37.1
-90.8

if (filteredChildrenWithoutIgnores.isEmpty()) {return new EmptyStatement();
}

-53.0
-29.0
-12.8

return new Statement() {@Override
public void evaluate() {runChildren(notifier, filteredChildrenWithoutIgnores);
}
};

-31.2

-31.2
-14.4

}

-60.3
-36.7
-56.7

(b) メソッド呼び出しへの変更

図 9 スコアが増加した例(b) メソッド呼び出しへの変更

ストグラムで表したものを図 7 に示す．このヒストグラムか

図 8 スコアが減少した例

らも，リファクタリングによってスコアが減少する傾向があ
ドの移動など，提案手法のようなメソッド本体のみを考慮する手法では評価できないリファクタリングである．

ることがわかる．
スコアが減少した例として，2012/8/20 15:47 のコミット

最も性能の良い言語モデルと識別子処理の組み合わせの 1#0215c66 を図 8 に示す．このコミットでは Extract Method

つである，Cache モデルと識別子そのままの場合におけるすリファクタリングが行われており，図 8(a) に示す 2 つのメソッ

べてのコミットでの結果を表 4 に示す．✓ はスコアが減少し，ドが切り出されている．このとき，行の自然さ-50.3 は交差検提案手法がよいリファクタリングと評価したコミットである．

定による分布中では下位 14%に相当し，-44.2 は下位 18%に相また，このときのリファクタリング前後でのスコアの差をヒ当する．切り出した 2 つのメソッドを使用するように変更された部分を図 8(b) に示す．この変更では，自然さの低かった
行がメソッド呼び出しに変更されることで自然さが向上して

表3 実験結果
言語モデル

識別子

増加 変化なし

減少

いることがわかる．このように，自然さが低く繰り返し出現

KenLM

そのまま

9

3

16

する行をメソッドとしてまとめることで自然さの低い行が削

KenLM

分割

9

3

16

減されたためスコアが減少したと考えられる．

KenLM

正規化

8

3

17

そのまま

スコアが増加した例として，2013/10/21 01:58 のコミット

Cache

6

3

19

Cache

分割

6

3

19

#2240984 を図 9 に示す．このコミットにおいても Extract

Cache

正規化

8

3

17

Method リファクタリングが行われており，図 9(a) に示す
getFilteredChildrenWithoutIgnores メソッドが切り出され—5—ている．切り出したメソッドを使用するように変更された部

れておらず，プロジェクトによる偏りが存在する可能性があ分を図 9(b) に示す．この変更では，Extract Method リファク

る．また，リファクタリングが行われたかどうかは目視によっ

タリングによって新たなメソッドが追加されたものの，ソースて判別しているため誤りが含まれる可能性がある．

コード中に存在する行自体はほぼ変わっておらず，新たなメ
ソッド呼び出しが追加された分だけスコアが増加した．提案

6. あ と が き

手法は n-gram によって行単位の自然さを計測しているため，

本研究ではリファクタリング支援手法開発の第一歩として，各行が自然か，そうでないかは判定できるが，それら行の並び

ソースコードの自然さを用いたリファクタリングの評価手法が自然かそうでないかはほぼ考慮することができない．そのを提案した．提案手法の評価実験では，オープンソースプロ

ため図 9 のようなリファクタリングを評価することは難しい．

ジェクトに対して行われた 28 個のリファクタリングのうち，19 個のリファクタリングにおいて良いリファクタリングであ5. 妥当性の脅威
5. 1

ると評価された．そのため開発者によって行われたリファク

学習用ソースコードの品質

タリングと，提案手法によって良いと評価されたリファクタ

言語モデルを用いた自然さは，出現頻度が高いパターンであるほどより自然になるため，学習用ソースコードに保守性のリングが対応していると考えられ，提案手法がリファクタリ
ングの評価に有効であることを確認した．

低いソースコードが多く含まれている場合，品質の低いソー

今後の課題としてソースコードの特徴をより反映し，高精

スコードに対して自然であると出力してしまう可能性がある．

度なリファクタリング評価手法を開発することがあげられる．

しかし今回学習用コーパスに用いたソースコードは，Apache

自然言語処理の分野では，Deep Learning による技術が大き

Software Foundation によって管理されているオープンソース

く進歩しており，これらの技術を取り入れる方法を検討してプロジェクトであるため，品質は十分であると考えられる．

いる．

5. 2

評価用データ

謝辞

評価実験では 1 つのプロジェクトの 28 コミットしか評価さ本研究は，日本学術振興会科学研究費補助金基盤研

究（S）（課題番号：JP25220003）の助成を得て行われた．
文

表 4 すべてのコミットでの結果．✓ は良いリファクタリングと評価[1]

されたコミットである．
コミット ID リファクタリングの内容

スコアの変化評価[2]#23793cd

Extract class

0.46#a7c4d03

Extract class

-1.76

✓

#7a2b046

Extract class

-0.62

✓

#fd1ef3c

Extract method

-0.21

✓

#dbe7711

Extract method

-0.49

✓

#2240984

Extract method

0.07#862f41c

Extract method

0.91

[4]

#5976b1d

Extract method

-0.15

✓

#0215c66

Extract method

-2.78

✓

#24cbcbc

Extract method

-2.19

✓

#467dd07

Extract method

-0.26

✓

#e48f6d4

Extract method

-1.09

✓

#fe5d86e

Inline method

-1.01

✓

#6838ac0

Inline method

0.49#0030e51

Inline method

1.02#ce9bc58

Move method

0.00#f1f4fe2

Move method

-0.72

[3]

✓

#4c1758d

アルゴリズム変更-0.38✓#66bfb24

アルゴリズム変更-1.14✓#df016dc

アルゴリズム変更-0.24✓#17a2f11

不要な処理の除去-1.15✓#9a0aec8

不要な継承の除去

0.00#a30e87b

変数に final を付与

0.00#db8d580

コードクローンの除去

-0.49

[5]

[6]

[7]

[8]

[9]

✓

#e77e1c4

既存メソッドの再利用

-0.23

✓

#759061a

Strategy パターンの導入

-0.04

✓

#7f2569f

Pull up method-0.46#d064212

Rename method and class

-0.50

✓

[10]

献

S.G. Eick, T.L. Graves, A.F. Karr, J.S. Marron, and A.
Mockus, “Does code decay? assessing the evidence fromchange management data,” IEEE Transactions on Software
Engineering, vol.27, no.1, pp.1–12, 2001.
M. Fowler, K. Beck, J. Brant, W. Opdyke, and D.
Roberts, Refactoring: Improving the Design of Existing
Code, Addison-Wesley Professional, 1999.
A. Hindle, E.T. Barr, Z. Su, M. Gabel, and P. Devanbu, “On
the Naturalness of Software,” Proceedings of the 34th International Conference on Software Engineering, pp.837–847,
2012.
B. Ray, V. Hellendoorn, S. Godhane, Z. Tu, A. Bacchelli,and P. Devanbu, “On the “Naturalness” of Buggy Code,”
Proceedings of the 38th International Conference on Software Engineering, pp.428–439, 2016.
M. Allamanis, E.T. Barr, C. Bird, and C. Sutton, “Learning Natural Coding Conventions,” Proceedings of the 22nd
ACM SIGSOFT International Symposium on Foundations ofSoftware Engineering, pp.281–293, 2014.
V. Hellendoorn and P. Devanbu, “Are deep neural networks
the best choice for modeling source code?,” Proceedings ofthe 2017 11th Joint Meeting on Foundations of Software Engineering, pp.763–773, 2017.
K. Heafield, “KenLM: faster and smaller language model
queries,” Proceedings of Sixth Workshop on Statistical Machine Translation, pp.187–197, 2011.
S.F. Chen and J. Goodman, “An empirical study of smoothing techniques for language modeling,” Computer Speech &Language, vol.13, no.4, pp.359–394, 1999.
Z. Tu, Z. Su, and P. Devanbu, “On the Localness of Software,” Proceedings of the 22nd ACM SIGSOFT International Symposium on Foundations of Software Engineering,pp.269–280, 2014.
Y. Higo and S. Kusumoto, “How should we measure functional sameness from program source code? an exploratory
study on java methods,” Proceedings of the 22nd ACM SIGSOFT International Symposium on Foundations of Software
Engineering, pp.294–305, 2014.

—6—