ソフトウェア工学研究の日々

ソフトウェア工学の学術研究を紹介しています。ソフトウェア開発に関する調査と実験が大好きです。

開発者が行ったソースコード修正作業を学習し代行するボット

当研究室の D1 上田 裕己 君の「開発者が行ったソースコード修正作業を学習し代行するボット」というプロジェクトが、2019年度未踏IT人材発掘・育成事業に採択されました。

 www.ipa.go.jp

このプロジェクトは、彼自身が当研究室の修士論文等で研究してきた技術を基盤に、1年間で応用的なソフトウェアを世の中にリリースすることを目指しています。

研究内容をよく知っている教員でも実際どのぐらいのものが作れるか予想がつかないところですので、研究面での関連情報を提供しながら、今後の展開を見守りたいと思います。

 

Heijo: コード実行可視化によるJava/Androidアプリケーションのリアルタイムプロファイラ

2月に本ブログで紹介した論文が、ソフトウェア科学会論文誌「コンピュータソフトウェア」36巻2号に掲載されましたので、リンクを張っておきます。

Heijo: 動的なコード実行可視化によるJava/Androidアプリケーションのリアルタイムプロファイラ

論文の PDF は、論文誌の冊子体が紙として出される都合上、白黒となっています。カラーでどのように見えるかは、下記記事のものをご参照ください。

ishiotks.hatenablog.com

ソフトウェア工学国際会議 ICSE 2019 に参加しました

5月25日から31日にかけて、ソフトウェア工学国際会議(ICSE 2019)とその関連イベントが開催されました。

私たち奈良先端ソフトウェア工学研究室からは、ICSE本会議でフルペーパー 1件、ジャーナルファースト発表 1件、併設イベントであるプログラミングに関する視線トラッキングに関するワークショップ(EMIP)で発表 1件、プログラム理解に関する国際会議(ICPC)で大阪大学と共同研究のツールデモ発表 1件、合計4件の研究を発表しました。

本会議の様子については、D2の幾谷君による現地レポート記事があるので、そちらをご覧ください。

qiita.com非常に多様な論文が発表されていましたので、ソフトウェア工学に関わっている皆様には、ICSE 2019 勉強会でもその内容を確認していただければと思います。現在7月18日の開催で調整中ですので、予定を確保しつつ公式のアナウンスをお待ちください。

 

コードレビューは活発に活動している人ほど引き受けてくれる

今月末に開催されるソフトウェア工学の国際会議 ICSE にて、Journal-First Track という「論文誌に採択されたが国際会議では未発表」という原稿について、私たちの研究室から1件発表があります。

arxiv.org

 この論文は、オープンソースソフトウェアプロジェクトで行われているコードレビュー活動を調査し、「誰に依頼すると、引き受けてもらえるのか」を機械学習で予測する方法を考えた論文です。データセットには、Android, LibreOffice, OpenStack, Qt プロジェクトに投稿されたパッチ 230,090 個を使っています。

 この論文では、コードレビューは誰でも引き受けてくれるわけではなく、16%から66%のパッチで、レビューのお願いに反応してくれないレビュアーが 1人以上いることを報告しています。引き受けてくれないことがあるからと多数の人に依頼を出すのは迷惑ですから、レビューを引き受けてくれそうな人に依頼を出すというのが課題になります。

 この「レビューに参加してくれそうな人」を予測するとき、レビュアーの "Human Factor" を含めると精度が向上する、というのが論文の報告です。Human Factor といっても色々ありますが、強く効くのは「レビューを引き受けてきた割合」と「これまでに書いたパッチの数」です。そのほか、これまでに書いてきたレビューの数や、レビューとして記述するコメントの量、現在実施中のレビューの数などが予測に寄与する要素となっています。

 この結果は、いつもコードレビューを引き受けてくれる、まじめにレビューを書いてくれる人ほど、これからも引き受けてくれる可能性が高いということを示しています。これだけ聞くと当たり前のようにも思える話ですが、従来研究ではパッチの内容に関係した知識を持っていそうなレビュアーを推薦することだけが考えられていたので、その人たちの過去の行動まで加味したほうがよいことを示した、というのがこの論文の貢献になります。

 この結果をレビュアーの自動推薦に単純に組み込むと、「引き受けてくれる可能性が高い人」を推薦しやすくなるという点では有益ですが、やりすぎると、現在頑張っている人たちにさらに依頼が集中しすぎて、破綻する可能性があります。作業負荷を能力や態度に合わせて公平に分配できるようになるには、まだまだ先は長そうです。

 

キャメルケースはスネークケースよりも読みやすい説

プログラムの識別子として複数の英単語をつなげるとき、単語区切りを大文字にしてつなげる CamelCase と、アンダースコアを使ってつなげる sanke_case の2つが良く使われています。この2つのどちらが読みやすいのか実験をした人がいる、というのが意外と知られていない気がしたので、ちょっと紹介しておきます。

To camelcase or under_score - IEEE Conference Publication (著者が配布している版はこちら)

この論文は被験者実験を行っています。 "extend alias table" のようなフレーズの後に、それを識別子に変換したもの(キャメルケースの場合 "extendAliasTable" )と単語のうち1つを偽物に入れ替えたもの(この例の場合 expandAliasTable, extendAlistTable, extendAliasTitle)を表示して、その中から正解を選ぶというタスクにおいて、被験者が目的のフレーズに当たる識別子を正確に、早く認識できるかを調査しています。

基本は統計的に有意な差が出るかどうかの判定をしていて、結果は以下の通りでした。

  • 認識の正確さはキャメルケースのほうが高い(オッズ比 1.515)。
  • キャメルケースのほうが認識に少し時間がかかる(13.5%、実時間にして0.42秒)。
  • レーニングが正確さに影響するかは分からない(帰無仮説が棄却できない)。
  • レーニングで認識にかかる時間は短くなる。

この論文では2つを比べるという都合上、キャメルケースのほうが良いという結論になっています。ただし、この実験設定はけっこう意地悪でもあって、似たような識別子がたくさん並ぶ状況ならば省略表記のほうが読みやすいという指摘もあります。関連研究のところにそういうこともしっかり書いてあるので、論文の著者らもキャメルケースを本気で押そうと思っているわけではなさそうです。

認識時間にほとんど差がなく、トレーニングで認識にかかる時間が短くなるということから、使い慣れたほうを使うほうが早いという常識的な話とも言えてしまいますが、この論文は「読みやすさ」というあいまいな指標を正確さと時間に分解して計測するという実験の作り方として参考になりますし、この研究から視線計測に基づく視認性の調査などにも続いていますから、ソフトウェア工学の中でもプログラム理解という分野を学ぶ上では良い材料であると思います。

 [2019/4/17 追記] この記事を書いた後に気づいたのですが、プログラム理解に関する国際会議(ICPC 2019)の開催情報によると、この論文がちょうど10年前に発表された論文の中から最も影響の大きかった論文(Most Influential Paper)に選ばれたようです。

 

スマートフォンを支えるオープンソースソフトウェア

IPSJ-ONE にて、「ソフトウェアの生態系を探る」というタイトルで登壇してきました。

ipsj-one.org

この発表では時間の都合上、まったく言及することができませんでしたが、「ソフトウェアの生態系(Software Ecosystem)」と総称されるオープンソースソフトウェア群は日常生活に非常に密接にかかわっています。

私たちにとって身近で、かつ、オープンソースソフトウェアを活用している筆頭と言えそうなのが Android プロジェクトです。Android SDKソースコードをダウンロードしてくると、2019年2月時点で、external ディレクトリに300個ぐらいのソフトウェアが並びます。この中には、たとえば以下のようなものが入っています。

  • 1979年に発表された Basic Linear Algebra Subprograms に由来するベクトルや行列を扱うライブラリ。OpenCV なんかも同じ仲間と言ってよいかもしれません。
  • 1984年頃からインターネットの発展に伴って登場してくる、TCP/IP ネットワーク系のツール(ppp, tcpdumpなど)。
  • 1989年頃から登場し始めた giflib, libjpegなどの画像処理系ライブラリ。
  • 1995年頃から登場した zlib, bzip2 などのデータ圧縮・展開ライブラリ群。libpng のように zlib に依存した画像処理なんかも登場します。
  • 1998年頃から揃ってくる動画、音声、XML などの各種データフォーマットを扱うライブラリ。
  • 2003年頃から登場してきた、LLVMApache Ant、JUnit などの開発環境、テスト自動化系のツール群。

スマートフォンが音声や映像、通信を扱うことを考えると入っていておかしくないものばかりですが、有名ツール、プロジェクトがけっこう入っています。約半分は Android が発表される以前のもの(Copyright を見ると 2008年以前)となっていて、実績を積んできたソフトウェアたちが今も活躍しています。COBOL のプログラムが今も企業のビジネスを支えていたり、昔のゲームソフトが今も遊ばれているのと同じように、「必要なソフトウェア」は、しっかり長生きしています。

プロジェクトの由来は手作業で調べているので、勘違い等もあるかもしれませんが、これらのソフトウェアの Copyright には MicrosoftIntelApple、複数の大学の名前も入っていて、コミュニティ全体で協力して信頼できる基本部品を整えるという最近の時流がよく分かる事例になっていると思います。気になる方は、ソースコードをダウンロードして Copyright という文字列を検索してみてください。

 

コードレビューでは1000回以上繰り返されている修正もある

コードレビューでは同じような修正を何度も繰り返しているしているように見えるという知見は、 if 文に関する下記の研究で判明していました。

ishiotks.hatenablog.com

この研究の続きとして、コードレビューで行われた任意の修正のうち、何度も繰り返されているものだけを取り出すパターンマイニング手法を定義し、さらに調査してみました。2019年2月に開催されたソフトウェアクローンに関するワークショップ(IWSC 2019)にて、以下のタイトルで発表しています。

Mining Source Code Improvement Patterns from Similar Code Review Works

この研究では、過去の研究と同様に、投稿されたパッチの最初の版と、レビューが完了してソースコードに取り込まれた最後の版の差分を分析しています。レビューによる差分として、たとえば以下のような情報が取得できます。

- i = dic["key"]
+ i = dic.get("key")

この研究では、この差分内容自体から、「よくある修正」のマイニングを試みています。具体的な方法としては、以下に示すように、コードレビュー差分情報を含めたトークンの系列を生成しています。

i = dic

- [

+ .get(

"key"

- ]

+ )

行の先頭に "-" が付いたものがレビューで削除されたトークン、"+" の付いたものが追加されたトークンです。i=dic、"key" という行については変更されていないことを示しています。

パッチをそれぞれこのような系列に変換した後、数値は NUMBER に置き換えるなど少し正規化操作もかけてから、系列データマイニング(Sequential Pattern Mining)のアルゴリズムを実行します。これによって、よく行われている修正と、その前後にいつも出現しているトークンを抽出しました。マイニングのアルゴリズムには、動作原理が分かりやすく、そこそこの性能を持つ PrefixSpan を使いました。

OpenStack プロジェクト群の 616,723 個の変更に対してマイニングをかけた結果から得られたパターンには色々含まれていました(詳しくは論文の Table 1参照)。たとえば、以下のパターンは、1,149個の変更に出現していました。

self.assertEqual

+ NUMBER ,

- , NUMBER

 これは、self.assertEqual(_, NUMBER) が self.assertEqual(NUMBER, _) に置き換わっているらしいことを示したパターンになっています。assertEqual の第1引数に期待された値、第2引数に実際のプログラムから計算された値を入れるので、それを守っていなかったテストコードを修正してきたことがうかがえます。このパターンを含めて、出現頻度の高いパターン群 5個について StackOverflow に対応する質問が見つかりましたので、「一度は解説を読んだことがないと分からない」というタイプの知識が、開発者にうまく広まっていない可能性があると考えています。

修正パターンのうち、修正回数が 5,000回を超えていたものは2つでした。その1つは単体テストTestCase クラスに関する関数呼び出しを置き換えるものです。

self.

+ stub_out

- stubs . Set

)

この置き換えの理由については、以下のように API ドキュメントに記載されています(レビューが行われた時期とドキュメントに書かれた時期のどちらが早いのかまでは、残念ながら分かっていません)。

stub_out(old, new)

  This should be used instead of self.stubs.Set (which is based on mox) going forward.

  The nova.test Module — nova 13.1.2 documentation

こちらはプロジェクト固有の事情によるところがありそうで、先ほどのテストの書き方よりも、さらにマイナーな知識になっていることが、この修正回数に反映されているように思います。

開発者が新しいルール(たとえば使うべきでない機能)を定義し周知できればそれで良かった可能性もありますが、なるべく手間を発生させないために、このような新しいルールの出現を自動で検知し、開発者にうまく伝える仕組みというのも、研究室で今後の課題として考えていく予定です。

( 2019年3月5日追記)本論文は、IWSC2019 において参加者の投票によって People's Choice Award に選ばれました。受賞に関するページにて、ワークショップで使用した発表スライドを公開しています。