巨大プロジェクトにおける変数名の一貫性の検査

権藤研 合宿用資料 2019/09/17
新山

SOAPBOX

本題: 巨大なソフトウェアは深刻な問題だ

目標: ソースコード中の一貫しない変数名を指摘する

void printResult(Stream out, String result) {
  out.writeLine("result:"+result);
}

void printStat(Stream out, int stat) {
  out.writeLine("stat:"+stat);
}

void printInfo(Stream strm, String info) {
  strm.writeLine("info:"+info);  // お前、ここはoutやろ。
}

準備: 変数の「データパス」に着目する

ここでは、ある変数に代入される値が通る一連の処理 (または関数の引数および返り値が通る処理) を、 その変数の「データパス」と定義する。

データパスの例

問. 以下の例で変数 line に着目する。

private BufferedReader fp;

public String get() {
    String line = fp.readLine();
    int i = line.indexOf(' ');
    return line.substring(0, i);
}

グラフ化するとこうなる:

get() cluster_a N1 fp N2 readLine() N1->N2 #this N4 indexOf() N2->N4 #this N6 substring() N2->N6 #this N3 ' ' N3->N4 #arg0 N4->N6 #arg1 N5 0 N5->N6 #arg0 N7 return N6->N7

グラフ中の赤線部分が 変数 line のデータパスである:

これは、変数 line になにが代入され、 それがどのように使われるかを示している。

Interprocedural 化する

private BufferedReader fp;

public String get() {
    String line = fp.readLine();
    int i = line.indexOf(' ');
    return line.substring(0, i);
}

public void show() {
    String name = get();
    System.out.println(name+"!!");
}

get() 中の変数 line (の処理結果) は、 いまや show() 中では name となっていることに着目。

これをグラフ化するとこうなる:

A cluster_a get() cluster_b show() N1 fp N2 readLine() N1->N2 #this N4 indexOf() N2->N4 #this N6 substring() N2->N6 #this N3 ' ' N3->N4 #arg0 N4->N6 #arg1 N5 0 N5->N6 #arg0 N9 name N6->N9 N11 + N9->N11 L N8 System.out N12 println() N8->N12 #this N10 !! N10->N11 R N11->N12 #arg0

最終的に、 変数 line のデータパスは:

となる。 この順列が、本プログラムにおける「変数 line の使われ方」を表すことになる。

単純化のため、いまのところパスの分岐は考慮しない。

手法: 学習と予測

以上のようなデータパスを、 プログラム中のすべての変数に対して (interprocedural で) 抽出し、 変数名との相関を学習する。 ここでは「データパスを与えると、変数名を予測する」ようなモデルを学習する。

fp.readline() line #this:indexOf() #arg1:substring() assign:name

つまり、以下のようなデータパスが出てきたら:

ここでの ??? = line ではないか、 と予測するということである。もしここで line 以外の名前が使われていたら、 その変数名は (この使われ方に対しては) 一貫していない、ということになる。

以上の技術を、巨大な Java コードベースに対して行えば (これがチョー大変!!) 完了。

抽象的な記述

  1. すべての変数 v ∈ V に対して、 v.feature, v.name を収集。
  2. 特定の変数 v1 に対し、 「v1 を除いたすべての v ∈ V (v ≠ v1)」に対して G(v.feature) = v.name を予測する関数 G を学習する。
  3. G(v1.feature) を求め、 それが v1.name と一致すれば一貫性あり。

結果

本研究の貢献

「コード中の変数名を予測・提案する」という研究は以前からある [1] が、 本研究が新しいのは:

である。
  1. Raychev, Veselin and Vechev, Martin and Krause, Andreas, Predicting Program Properties from "Big Code", 2015.

Yusuke Shinyama