コーディングにおける 細粒度作業履歴を用いた 手戻り支援ツールの検討

Slides:



Advertisements
Similar presentations
プラグイン作成講座 Control System Studio 3.0 Takashi Nakamoto
Advertisements

Trac と Eclipse の 便利な機能. プロジェクト管理システム: Trac 0. はじめに バージョン管理システム: Subversion 統合開発環境: Eclipse ・ Wiki による情報 管理 ・進捗状況の管理 ・プログラムの作 成 ・リポジトリに データを集める.
API 呼び出し列の差分を利用した Android アプリケーション比較ツールの 試作 井上研究室 神田 哲也.
1 情報基礎 A 第 9 週 プログラミング入門 VBA の基本文法 1 準備・変数・データの入出力 徳山 豪・全 眞嬉 東北大学情報科学研究科 システム情報科学専攻 情報システム評価学分野.
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University 保守支援を目的とした コードクローン情報検索ツール.
OWL-Sを用いたWebアプリケーションの検査と生成
Web アプリをユーザー毎に カスタマイズ可能にする AOP フレームワーク
シーケンス図の生成のための実行履歴圧縮手法
3次元nクイーン問題の 解に関する研究 論理工学研究室 伊藤精一
情報理工学部 情報システム工学科 ラシキアゼミ 3年 H 井奈波 和也
WordPressの基礎.
デジタルポートフォリオ作成支援ツール PictFolio 使用マニュアル
コントロールパネル ◎コントロール パネル: コンピュータのさまざまな機能を設定するための画面
JavaによるCAI学習ソフトウェアの開発
ソースコードの編集内容を入力とした ソフトウェア部品の自動検索
情報伝播によるオブジェクト指向プログラム理解支援の提案
アクセス修飾子過剰性の変遷に着目したJavaプログラム部品の分析
Web上で管理・利用できる 面接予約データベースシステムの構築
ユースケース図2-4~ FM11012 中島拓也.
リファクタリングのための 変更波及解析を利用した テスト支援ツールの提案
かぞえチャオ!でコードレビュー 2013/10/20 Ciao-ware.
川口真司 松下誠 井上克郎 大阪大学大学院情報科学研究科
Java ソフトウェア部品検索システム SPARS-J のための リポジトリ自動更新機能の実現
ソースコードに対する適用可能な修正手順を 可視化するリファクタリング支援手法の提案
ソースコードの変更履歴における メトリクス値の変化を用いた ソフトウェアの特性分析
コードクローンに含まれるメソッド呼び出しの 変更度合の分析
コードクローンに含まれるメソッド呼び出しの 変更度合の調査
ソードコードの編集に基づいた コードクローンの分類とその分析システム
関数の変更履歴と呼出し関係に基づいた開発履歴理解支援システムの実現
暗黙的に型付けされる構造体の Java言語への導入
リファクタリング中に生じる コンパイルエラーの自動解消手法
動的依存グラフの3-gramを用いた 実行トレースの比較手法
シーケンス図を用いて実行履歴を可視化するデバッグ環境の試作
クローンセットに対する主要編集者の分析法の提案と調査
三浦元喜 北陸先端科学技術大学院大学 知識科学研究科 2007/9/7
環境リスクマネジメントに関する 検索システム
リファクタリング支援のための コードクローンに含まれる識別子の対応関係分析
ソースコードの特徴量を用いた機械学習による メソッド抽出リファクタリング推薦手法
オープンソース開発支援のための リビジョン情報と電子メールの検索システム
コードクローンの動作を比較するためのコードクローン周辺コードの解析
Parallel Setsによるライブラリの 組み合わせと利用状況の可視化
プログラム理解におけるThin sliceの 統計的調査による有用性評価
バイトコードを単位とするJavaスライスシステムの試作
○ 後藤 祥1,吉田 則裕2 ,井岡 正和1 ,井上 克郎1 1大阪大学 2奈良先端科学技術大学院大学
ソフトウェア保守のための コードクローン情報検索ツール
コードクローンの理解支援を目的としたコードクローン周辺コードの解析
dcNavi: デバッグ方法をアドバイス する関心事指向リポジトリナビゲータ
プログラムの織り込み関係を可視化するアウトラインビューの提案と実装
コーディングパターンの あいまい検索の提案と実装
JAVAバイトコードにおける データ依存解析手法の提案と実装
同期処理のモジュール化を 可能にする アスペクト指向言語
設計情報の再利用を目的とした UML図の自動推薦ツール
vc-2. Visual Studio C++ のデバッガー (Visual Studio C++ の実用知識を学ぶシリーズ)
保守請負時を対象とした 労力見積のためのメトリクスの提案
dcNavi:デバッグ支援のための グラフベース推薦システム
アスペクト指向言語のための視点に応じた編集を可能にするツール
プログラムの差分記述を 容易に行うための レイヤー機構付きIDEの提案
クローン検出ツールを用いた ソフトウェアシステムの類似度調査
オープンソースソフトウェアに対する コーディングパターン分析の適用
開発作業の形式化に基づく プロセス評価 松下誠 大阪大学.
ソースコードの編集状況に応じた ソフトウェア部品の自動推薦システム
統合開発環境のための プログラミング言語拡張 フレームワーク
ソフトウェア理解支援を目的とした 辞書の作成法
エイリアス関係を考慮した Javaプログラム用静的スライシングツール
プログラムの一時停止時に 将来の実行情報を提供するデバッガ
コードクローン解析に基づく デザインパターン適用候補の検出手法
関数の変更履歴と呼び出し関係に 基づいた開発履歴理解支援システム
プログラム理解のための 付加注釈 DocumentTag の提案
オブジェクト生成の観測に基づく プログラム実行の要約の抽出
Presentation transcript:

コーディングにおける 細粒度作業履歴を用いた 手戻り支援ツールの検討 ○梅川晃一†, 井垣宏†, 吉田則裕‡, 井上克郎† †大阪大学大学院情報科学研究科 ‡奈良先端科学技術大学院大学 情報科学研究科 所属情報追加.あと発表者の名前の前に○をつける 2018/11/7

コーディングにおける手戻り 修正によって正常に動かなくなったプログラムを過去の状態へ戻す 手戻り public long getMembersLOC (String editor, Date sta, Date end) { Date s_date = null; Date e_date = null; ・ long loc = 0; query.constrain(DropboxLog.class); query.descend(“modified”).constrain(sta).greater(); query.descend(“modified”).constrain(end).smaller(); ObjectSet<DropboxLog> res = query.execute(); return getMemsLOCList(group, e_date, s_date); } public long getMembersLOC (String editor) { ・ long loc = 0; query.constrain(DropboxLog.class); ObjectSet<DropboxLog> res = query.execute(); return getMemsLOCList(group); } まず、コーディングにおける手戻りとは何かについて説明したいと思います。 ここにグラフを表示するプログラムがあります。 このプログラムある機能を追加しようとした時に、 プログラムが正常に動作しなくなってしまいました。 この時、バグの発生箇所がわかれば修正するんですが、 それがわからない場合に変更を削除することで正常に動作する状態へ戻す場合があります。 このようにコードを過去の正常に動作していた状態へ戻すことを手戻りと言います。 手戻りは手動で行われることもありますが、それを支援するツールも存在します。 正常に動く状態があった 修正(機能追加)後、動かなくなった バグがどこにあるかわからない場合に正常に動作する時点へ戻す 一般的にVCSやIDEでの手戻りが行われている 手戻り 2018/11/7

既存の手戻り支援ツール(1/2) バージョン管理システム(VCS) ファイルの変更履歴を管理するツール Subversion,Git等 VCS public long getMembersLOC (String editor, Date sta, Date end) { Date s_date = null; Date e_date = null; ・ long loc = 0; query.constrain(DropboxLog.class); ObjectSet<DropboxLog> res = query.execute(); return getMemsLOCList(group); } public long getMembersLOC (String editor, Date sta, Date end) { Date s_date = null; Date e_date = null; ・ long loc = 0; query.constrain(DropboxLog.class); query.descend(“modified”).constrain(sta).greater(); query.descend(“modified”).constrain(end).smaller(); ObjectSet<DropboxLog> res = query.execute(); return getMemsLOCList(group, e_date, s_date); } public long getMembersLOC (String editor) {             ・ ・ long loc = 0; query.constrain(DropboxLog.class); ObjectSet<DropboxLog> res = query.execute(); return getMemsLOCList(group); } 履歴A 5/1 12:00 Comment: グラフ作成 グラフ作成 引数、変数初期化処理追加 期間指定機能追加 履歴B 5/1 14:00 Comment:引数、変数初期化処理追加 そのツールの一つにバージョン管理システムがあります。 バージョン管理システムはファイルの変更履歴を管理するためのツールです。 開発が進み、プロジェクトの状態を保存したいとき このようにファイルの状態とコメントを履歴としてVCSへ登録することが可能です。 履歴C 5/2 10:00 Comment:期間指定機能追加 コミット 2018/11/7

既存の手戻り支援ツール(1/2) バージョン管理システム(VCS) ファイルの変更履歴を管理するツール Subversion,Git等 VCS VCS public long getMembersLOC (String editor, Date sta, Date end) { Date s_date = null; Date e_date = null; ・ long loc = 0; query.constrain(DropboxLog.class); query.descend(“modified”).constrain(sta).greater(); query.descend(“modified”).constrain(end).smaller(); ObjectSet<DropboxLog> res = query.execute(); return getMemsLOCList(group, e_date, s_date); } public long getMembersLOC (String editor, Date sta, Date end) { Date s_date = null; Date e_date = null; ・ long loc = 0; query.constrain(DropboxLog.class);    query.descend(“modified”).constrain(sta).greater(); query.descend(“modified”).constrain(end).smaller(); ObjectSet<DropboxLog> res = query.execute(); return getMemsLOCList(group , e_date, s_date); } public long getMembersLOC (String editor) {             ・ ・ long loc = 0; query.constrain(DropboxLog.class); ObjectSet<DropboxLog> res = query.execute(); return getMemsLOCList(group); } 履歴A 5/1 12:00 Comment: グラフ作成 履歴B 5/1 14:00 Comment:引数、変数初期化処理追加 履歴B 5/1 14:00 Comment:引数、変数初期化処理追加 履歴B 5/1 14:00 Comment:引数、変数初期化処理追加 また、手戻りを行う際は、コメントを参考にして履歴を選択します。 そして、このように保存した履歴を選択することで ファイルを選択した履歴に相当する状態へ戻すことが可能です。 履歴C 5/2 10:00 Comment:期間指定機能追加 2018/11/7

既存の手戻り支援ツール(2/2) IDEの自動保存機能 ローカル・ヒストリー[1] 自動的に履歴を保存 改訂時刻を選択し、手戻りを実行 public long getMembersLOC     (String editer) { List aList = getMemsAddList(group); List cList = getMemsChgList(group); public long getMembersLOC     (String editor, Date sta, Date end) { Date s_date = List aList = getMemsAddList(group); List cList = getMemsChgList(group); public long getMembersLOC     (String editor, Date sta, Date end) { Date s_date = null; Date e_date = null; List aList = getMemsAddList(group); List cList = getMemsChgList(group); public long getMembersLOC     (String editor, Date sta, Date end) { Date s_date = null; Date e_date = null; List aList = getMemsAddList(group); List cList = getMemsChgList(group); public long getMembersLOC     (String editor, Date sta, Date end) { List aList = getMemsAddList(group); List cList = getMemsChgList(group); ファイル保存 復元 また、IDEによるソースコードの自動保存機能も存在します。 その一つとしてEclipseに標準で搭載されているローカルヒストリーがあります。 この機能は、ユーザーが任意のタイミングで作業履歴を保存していたバージョン管理システムと違い ファイルの保存に連動して自動的にソースコードの変更履歴を保存します。 そして、バージョン管理システムと同様に、履歴の一つを選択することで ソースコードを過去の状態に戻すことが可能です。 これらのツールを手戻りに用いるにあたって、 私たちはいくつかの問題があると考えました。 選択 [1]長瀬嘉秀ら, “Eclipse クックブック”, O'Reilly Japan, 2004 2018/11/7

手戻りにおける課題(1/2) バージョン管理システム(VCS) 手戻り先が少なく、粒度が粗い VCS VCS public long getMembersLOC (String editer) {             ・ ・ long loc = 0; query.constrain(DropboxLog.class); ObjectSet<DropboxLog> res = query.execute(); return getMemsLOCList(group); } public long getMembersLOC (String editer, Date sta, Date end) { Date s_date = null; Date e_date = null; ・ long loc = 0; query.constrain(DropboxLog.class); query.descend(“modified”).constrain(sta).greater(); query.descend(“modified”).constrain(end).smaller(); ObjectSet<DropboxLog> res = query.execute(); return getMemsLOCList(group, e_date, s_date); } public long getMembersLOC (String editer, Date sta, Date end) { Date s_date = null; Date e_date = null; ・ long loc = 0; query.constrain(DropboxLog.class); ObjectSet<DropboxLog> res = query.execute(); return getMemsLOCList(group); } public long getMembersLOC (String editer, Date sta, Date end) { Date s_date = null; Date e_date = null; ・ long loc = 0; query.constrain(DropboxLog.class); query.descend(“modified”).constrain(sta).greater(); query.descend(“modified”).constrain(end).smaller(); ObjectSet<DropboxLog> res = query.execute(); return getMemsLOCList(group, e_date, s_date); } public long getMembersLOC (String editer, Date sta, Date end) { Date s_date = null; Date e_date = null; ・ long loc = 0; query.constrain(DropboxLog.class); query.descend(“modified”).constrain(sta).greater(); query.descend(“modified”).constrain(end).smaller(); ObjectSet<DropboxLog> res = query.execute(); return getMemsLOCList(group, e_date, s_date); } 履歴A 5/1 12:00 Comment: グラフ作成 履歴A 5/1 12:00 Comment: グラフ作成 履歴B 5/1 14:00 Comment:引数、変数初期化処理追加 履歴B 5/1 14:00 Comment:引数、変数初期化処理追加 履歴B 5/1 14:00 Comment:引数、変数初期化処理追加 説明 エラー発生→現状は履歴Cなので履歴を順に辿って手戻りした→履歴Bの状態へ手戻りしたら3行削除でエラー解消→仮に一番下の行がエラーの原因だった場合理想的な手戻りを提示→上の2行を削除するのは無駄な手戻り バージョン管理システムに履歴を保存する場合、 タイミングは開発者の任意である上、 一般的にある程度の区切りがついた時に保存するという使い方がされるため 各履歴は正常に動作する可能性が高い。 だが、履歴の保存が手動であることや利用方法から 手戻り先が少なく作業履歴の粒度が荒くなってしまいます。 例えば、このソースコードの赤い場所がバグの発生原因です。 バグが発生したがバグの発生箇所がわからないため、バージョン管理システムを用いて手戻りを行う場合 履歴Bを選択し、その結果これらのコードが巻き戻ることになります。 この時、この2行のようにバグに関係ないにも関わらず手戻りが行われてしまうコードが発生します。 このようにバージョン管理システムでは過剰な手戻りが発生する可能性があります。 履歴C 5/2 10:00 Comment:期間指定機能追加 履歴C 5/2 10:00 Comment:期間指定機能追加 過剰な 手戻り 2018/11/7

手戻りにおける課題(2/2) IDEの自動保存機能 ローカル・ヒストリー[1] 履歴が細粒度 正常に動作するかを確認しながら手戻りができない query.descend(“modified”).constrain(end).smalle ObjectSet<DropboxLog> res = query.execute(); ・ return getMemsLOCList(group, e_date, s_date); コードの構成要素が分断された作業履歴が保存される return getMemsLOCList(group, e_date, s_date); 復元 動作確認 選択 一方で、IDEによるソースコードの自動保存機能は、 バージョン管理システムに比べて作業履歴の保存頻度が高いため 履歴が細粒度であり 手戻り地点がバグに近い箇所にある可能性が高くなります。 しかし、細粒度であるためにコードの構成要素が分断された作業履歴が保存されるという課題があります。 仮に、ローカルヒストリーがバグの付近に手戻り地点を記録していたとして、 変数が分断されたような状態に手戻りを行ってしまうと そのまま動作確認をしようとしても当然エラーとなってしまうため自分でさらに編集する必要が生じます。 このようにコードの構成要素が分断された作業履歴が保存されてしまうため 円滑な動作確認を妨げることになります。 コンパイルが通らない状態 戻った場所が正しいのか評価が難しい 要素の分断が行われる [1]長瀬嘉秀ら, “Eclipse クックブック”, O'Reilly Japan, 2004 2018/11/7

目的 手戻りを行う際に有用な作業履歴の構築 課題 目的 VCS 手戻り先が少なく、粒度が粗い コーディング中の任意の時点へ戻ることが出来る粒度の履歴を提供する IDEによる保存機能 コードの構成要素が分断された作業履歴が保存される 手戻りを行った場合にプログラムの構成要素を分断しない 手戻りを行う際に有用な作業履歴の構築 これらの課題を踏まえて、私達の研究は手戻りを行う際に有用な作業履歴の構築を目的とします。 この、手戻りを行う際に有用な作業履歴がどういうものかというと、 この目的の欄に2つ書いてあることが具体的な内容です。 2018/11/7

目的 課題 目的 VCS 手戻り先が少なく、粒度が粗い コーディング中の任意の時点へ戻ることが出来る粒度の履歴を提供する IDEによる保存機能 コードの構成要素が分断された作業履歴が保存される 手戻りを行った場合にプログラムの構成要素を分断しない public long getMembersLOC (String editer, Date sta, Date end) { Date s_date = null; Date e_date = null; ・ (String editer, Date sta, Date end) { まず、目的の一つ目、コーディング作業中の任意の状態へ戻ることができる、 というのがどういうことかというと。 このコードで言えば、3行目記述前に戻る 2行目記述前に戻る、1行目記述前に戻るというように このようにコーディング途中の履歴が細かく記録されていることを言います。 Date s_date = null; Date e_date = null; 2018/11/7

目的 課題 目的 VCS 手戻り先が少なく、粒度が粗い コーディング中の任意の時点へ戻ることが出来る粒度の履歴を提供する IDEによる保存機能 コードの構成要素が分断された作業履歴が保存される 手戻りを行った場合にプログラムの構成要素を分断しない public long getMembersLOC (String editer, Date sta, Date end) { Date s_date = null; Date e_date = null; ・ public long getMembersLOC (String editer, Date sta, Date end) { Date s_date = null; Date e_date = null; ・ (String editer, Date sta, Date end) { また、手戻りを行った場合にプログラムの構成要素を分断しない、とはどういうことかというと このように変数の途中や行、文の途中への手戻りが行われないことを言います。 Date s_date = null; Date s_date = null; Date e_date = null; Date e_date = null; 2018/11/7

アプローチ Step1: IDE による細粒度作業履歴の自動収集 Step2: 細粒度作業履歴の再構築による細粒度リポジトリの作成 そのためのアプローチを2段階に分けて説明します。 Step1は、IDEによるコーディング作業における細粒度履歴の自動収集 Step2はStep1で収集した細粒度作業履歴の再構築による細粒度リポジトリの作成です。 細粒度作業履歴の再構築は更に分割と合成の2つの段階に分けられます。 行単位で任意の時点へ手戻りが可能な 作業履歴の構築 2018/11/7

全体の流れ Step1: 細粒度作業履歴の自動収集 履歴A 履歴B int i = 0; while( 履歴C 細粒度作業履歴 while(i<10) {       i++; } 履歴A 履歴B int i = 0; while( 履歴C 全体の流れは次のようになります。 まずStep1の細粒度作業履歴の自動収集。 これはIDE上で行われたファイルに対する編集履歴をを短いスパンで収集するものです。 このStepで収集された履歴を細粒度作業履歴と呼びます。 細粒度履歴は短いスパンで履歴を収集してはいますが、 コーディング作業中の任意の場所への手戻りができるほどの粒度ではありませんし、 ご覧のとおり行の途中で履歴として保存されています。 細粒度作業履歴 IDEにより短いスパンで保存したコードの編集履歴 2018/11/7

全体の流れ Step2: 細粒度作業履歴の再構築 履歴A1 履歴A 履歴A2+B+C1 履歴B 履歴C2 履歴C 履歴C3 細粒度リポジトリ int i = 0; while(i<10) {       i++; } 履歴A1 履歴A 履歴A2+B+C1 履歴B 履歴C2 int i = 0; +while(i < 10) { 履歴C そこでStep2で細粒度作業履歴を再構築します。 この再構築は細粒度作業履歴を開発中の任意の状態へ戻ることが可能な履歴として作り変えることを目的としており、 再構築した結果を格納したリポジトリを細粒度リポジトリと呼びます。 細粒度リポジトリによって提供される履歴を用いることで、 ソースコードの構成要素が分断されていない任意の作業途中の状態へ戻ることが可能です。 以降、各ステップの具体的な処理について説明していきます。 履歴C3 細粒度リポジトリ 開発中の任意の状態へ戻ることが可能な履歴で構成されたリポジトリ 2018/11/7

全体の流れ Step2: Step1: 細粒度作業履歴の再構築 細粒度作業履歴の自動収集 履歴A1 履歴A 履歴A2+B+C1 履歴B int i = 0; while(i<10) {       i++; } 履歴A1 履歴A 履歴A2+B+C1 履歴B 履歴C2 履歴C そこでStep2で細粒度作業履歴を再構築します。 この再構築は細粒度作業履歴を開発中の任意の状態へ戻ることが可能な履歴として作り変えることを目的としており、 再構築した結果を格納したリポジトリを細粒度リポジトリと呼びます。 細粒度リポジトリによって提供される履歴を用いることで、 ソースコードの構成要素が分断されていない任意の作業途中の状態へ戻ることが可能です。 以降、各ステップの具体的な処理について説明していきます。 履歴C3 2018/11/7

Step1:細粒度作業履歴の自動収集 時間経過、ファイル保存に連動した履歴の保存 細粒度作業履歴 履歴A int i = 0; while( 5秒 経過 ファイル未保存状態で一定時間経過 int i = 0; while(i<10 int i = 0; while( int i = 0; while(i<10) {       i++; } 履歴B int i = 0; while(i < 10 Ctrl+S まず、Step1の細粒度作業履歴の自動収集について説明します。 このステップでは まずコーディング作業中に保存せず一定時間、 例えば5秒経過時点などに自動的にコーディングの履歴を保存します。 この一定時間はユーザーが自由に設定可能となっています。 この後また5秒が経過し、履歴が保存され 最後にプログラムが完成し、ファイルが保存された時、保存の動作に連動してコーディングの履歴が保存されます。 これらの履歴はご覧のとおり、行の途中で分断されていますし 任意の場所へて戻りが可能なほど粒度も細かくなりません。 以降、この分断されている履歴を再構築します。 次は履歴B,Cを対象に細粒度作業履歴の分割処理について説明します。 B,Cを対象に 枠で囲む等 実装しながら自動的に保存してるのが分かるようなアニメーションに エディタ領域がちょっと狭すぎるのでもう少し大きく見えるようにしてください. このStep1で,十分短い間隔で保存されるということと,この時点ではまだ分断されているというのをちゃんと主張する また,次のページに行くときにBとCを対象として,分断されている部分をどうするか説明してからp.12に移動すること 履歴C int i = 0; while(i < 10) { i++; } ファイル保存時 2018/11/7

Step2-1:細粒度作業履歴の分割 コードの構成要素単位での分割 例:行単位の分割 履歴Bへ差分を適用 差分の場所をコメント - while(i < 10 + while(i < 10) { 履歴C1 int i = 0; while(i < 10) { Positon: L2 履歴B int i = 0; while(i < 10 while(i < 10) { + i++; 履歴C2 int i = 0; while(i < 10) { i++; B,C間の差分 - while(i < 10 + while(i < 10) { + i++; + } 履歴C int i = 0; while(i < 10) { i++; } Positon: L3 次にStep2の前半、細粒度作業履歴の分割について説明します。 まず修正前である履歴Bと修正後である履歴Cの差分を取得します。 この差分をコードの構成要素単位、今回は行単位で分割します。 差分というのは削除された行と追加された行で構成されていますが、 今回は追加された行を基準に分割を行います。 その結果がこの3つです。 これらを修正前のコードに適用することで、行単位に分割された履歴が作成されます。 この時、同時に差分の場所をバージョン管理システムへのコミットコメントとして追加します。 while(i < 10) { i++; + } 履歴C3 int i = 0; while(i < 10) { i++; } 差分の取得 追加行1行ごとに 履歴Cを分割 Positon: L4 2018/11/7

Step2-2:細粒度作業履歴の合成 連続で同じ行を編集している履歴を合成する 細粒度リポジトリ Time Positon: L1                           細粒度リポジトリ Time 履歴A1 int i = 0; Positon: L1 履歴A1 int i = 0; 連続する行への変更を捜索 履歴A2 int i = 0; while( Positon: L1 Positon: L2 履歴A2+B+C1 int i = 0; while(i < 10) { 履歴A2+B+C1 int i = 0; while(i < 10) { 履歴A2+B+C1 int i = 0; while(i < 10) { 履歴B int i = 0; while(i < 10 Positon: L2 Positon: L2 最新の履歴以外を削除 最後のステップ、細粒度作業履歴の合成です。 このステップでは連続で同じ行を編集している履歴を合成します。 具体的な処理ですが、まず各履歴についてコメントを確認し連続する行への変更を探します。 その結果、同じ行への編集が連続している箇所を発見した場合、 最新のものを除き削除します。 最終的に残った履歴を格納したリポジトリが細粒度リポジトリとなります。 履歴C1 int i = 0; while(i < 10) { 履歴C2 int i = 0; while(i < 10) { i++; Positon: L2 Positon: L3 履歴C2 ~~~~~~ Positon: L3 2018/11/7

実装 細粒度作業履歴 細粒度作業履歴再構築: Javaプログラム 履歴A 細粒度リポジトリ 履歴B 履歴C 履歴A1 履歴A1 int i = 0; while(i<10) {       i++; } 細粒度作業履歴再構築: Javaプログラム 履歴A 細粒度リポジトリ 履歴B 履歴C 履歴A1 履歴A1 履歴A2+B+C1 履歴A2 次に実装について説明します。 まずStep1はEclipseプラグイン、Save dirty Editor Pluginを拡張したプラグインとして開発しました。 Save dirty Editor Pluginとはファイルが編集され保存されていないとき、一定時間ごとにファイルのSnapShotを保存するプラグインです。 また履歴の保存のためのバージョン管理システムとしてGitを利用しました。 このプラグインはJarファイルをEclipseに導入するだけで動作を開始するため、開発者は事前の準備なしで細粒度作業履歴を収集可能です。 履歴B 履歴C2 自動保存機能:EclipseプラグインSave dirty Editor Plugin[1]を拡張 保存先:Git 履歴C1 履歴C3 履歴C2 履歴C3 [1] Save dirty Editor Plugin, http://savedirtyeditor.sourceforge.net/ 2018/11/7

実装 細粒度作業履歴 細粒度作業履歴再構築: Javaプログラム 履歴A 細粒度リポジトリ 履歴B 履歴C 履歴A1 履歴A1 int i = 0; while(i<10) {       i++; } 細粒度作業履歴再構築: Javaプログラム 履歴A 細粒度リポジトリ 履歴B 履歴C 履歴A1 履歴A1 履歴A2+B+C1 履歴A2 Step2の細粒度作業履歴を再構築するプログラムは Step1とは独立した単独のJavaプログラムとして実装しました。 Step1のプラグインで収集した任意の細粒度作業履歴を入力とし 対応する細粒度リポジトリを指定フォルダに出力します。 細粒度リポジトリを確認したい時には随時プログラムを実行し細粒度リポジトリを構築します。 リポジトリの閲覧や履歴のファイルへの適用は現状、Git公式のツールを利用するようになっています、。 履歴B 履歴C2 自動保存機能:EclipseプラグインSave dirty Editor Plugin[1]を拡張 保存先:Git 履歴C1 履歴C3 履歴C2 履歴C3 [1] Save dirty Editor Plugin, http://savedirtyeditor.sourceforge.net/ 2018/11/7

利用方法 2018/11/7 ここで、利用方法についての単純な動画をご覧頂きたいと思います。 Eclipse上でプログラムを開発します。 この時点で既に裏ではプラグインが動作しており、 一定期間ごとに細粒度作業履歴を保存しています。 未保存時の履歴収集までの時間は5秒に設定しています。 コードが書き終わったら、Step2のJarを実行します。 結果、例と同様に1行単位での差分で構築された細粒度作業履歴が構築されます。 次に細粒度作業履歴と、分割後の細粒度作業履歴、そして細粒度リポジトリを見て頂きます。 細粒度作業履歴はこのように複数行にまたがっていたり、行の途中で保存されています。 分割後の履歴はこのように全て行単位の差分となっていますが、変わらず行の途中で保存されています。 そして、細粒度リポジトリ。 全て行単位、その上行の途中で保存されたものもありません。 2018/11/7

考察 コーディングに対し、細粒度作業履歴を収集できた 細粒度作業履歴を指定したコードの構成要素単位(行単位)で再構成することができた 得られた細粒度リポジトリによって、行単位でコーディング中の任意の時点への手戻りが可能になると考えられる 考察としては、今回作成したツールによって 指定したコードの構成要素単位、今回は行単位でリポジトリを再構築することが出来ました。 今後の展望としてはまず、 コンパイル可能なコードのみで構築したリポジトリの構築を行うことが出来るようにしたいと考えています。 今回の再構築ではこれらの履歴のうち履歴BとCはWhile文が閉じていないためコンパイルができません。 そのためこの履歴を用いてて戻りしてもすぐに実行できません。 そのためこのようなコンパイルできない履歴を含まないリポジトリを含むようなリポジトリを構築できるようにしたいと考えています。 2018/11/7

今後の展望 コンパイル可能なコードのみで 構成したリポジトリの構築 履歴A int i = 0; 履歴B int i = 0;  構成したリポジトリの構築 履歴A int i = 0; 履歴B int i = 0; while(i < 10) { 元コード int i = 0; while(i < 10) { i++; } 履歴C2 int i = 0; while(i < 10) { i++; 履歴D int i = 0; while(i < 10) { i++; } 2018/11/7

今後の展望 コードの一部のみの手戻り VCS VCS 既存の手戻り支援ツール 履歴Bの変更のみを削除したい 履歴B,Cの変更が削除されて public long getMembersLOC (String editer, Date sta, Date end) { Date s_date = null; Date e_date = null; ・ long loc = 0; query.constrain(DropboxLog.class); query.descend(“modified”).constrain(sta).greater(); query.descend(“modified”).constrain(end).smaller(); ObjectSet<DropboxLog> res = query.execute(); return getMemsLOCList(group, e_date, s_date); } public long getMembersLOC (String editor, Date sta, Date end) { Date s_date = null; Date e_date = null; ・ long loc = 0; query.constrain(DropboxLog.class); query.descend(“modified”).constrain(sta).greater(); query.descend(“modified”).constrain(end).smaller(); ObjectSet<DropboxLog> res = query.execute(); return getMemsLOCList(group, e_date, s_date); } 履歴A 5/1 12:00 Comment: グラフ作成 履歴B 5/1 14:00 Comment:引数、変数初期化処理追加 履歴B,Cの変更が削除されて 履歴Aの変更のみが残る 履歴C 5/2 10:00 Comment:期間指定機能追加 2018/11/7

履歴Bの変更のみが削除され、履歴A,Cの変更が残る 今後の展望 コードの一部のみの手戻り 提案手法 履歴Bの変更のみを削除したい VCS VCS public long getMembersLOC (String editor, Date sta, Date end) { Date s_date = null; Date e_date = null; ・ long loc = 0; query.constrain(DropboxLog.class); query.descend(“modified”).constrain(sta).greater(); query.descend(“modified”).constrain(end).smaller(); ObjectSet<DropboxLog> res = query.execute(); return getMemsLOCList(group, e_date, s_date); } public long getMembersLOC (String editor, Date sta, Date end) { Date s_date = null; Date e_date = null; ・ long loc = 0; query.constrain(DropboxLog.class); query.descend(“modified”).constrain(sta).greater(); query.descend(“modified”).constrain(end).smaller(); ObjectSet<DropboxLog> res = query.execute(); return getMemsLOCList(group, e_date, s_date); } 履歴A 5/1 12:00 Comment: グラフ作成 履歴B 5/1 14:00 Comment:引数、変数初期化処理追加 履歴Bの変更のみが削除され、履歴A,Cの変更が残る 履歴C 5/2 10:00 Comment:期間指定機能追加 2018/11/7

まとめと今後の課題 まとめ 今後の課題 コーディング過程の細粒度作業履歴の収集手法 指定したコードの構成要素単位で構成された履歴をもつ細粒度リポジトリを構築する手法 今後の課題 バグの発見と解消のための手戻りを支援する仕組みの構築 実際の開発にツールを適用し、手戻り支援に関して評価 部分的な手戻り 自動で分割合成 PDG(バグ捜索、コンパイル通るののみ) 実際の開発に適用し、手戻り 実際にバグが存在する可能性が高い箇所への手戻りを支援する仕組みを 2018/11/7