ソフトウェア・シンポジウム 2021 in 大分 (オンライン開催)

Arduino プロジェクトにおける Example Sketch の再利用分析
寺村 英之
京都工芸繊維大学
h-teramura@se.is.kit.ac.jp

崔 恩瀞
京都工芸繊維大学
echoi@kit.ac.jp

吉田 則裕
名古屋大学
yoshida@ertl.jp

近藤 将成
九州大学
kondo@ait.kyushu-u.ac.jp

水野 修
京都工芸繊維大学
o-mizuno@kit.ac.jp

要旨

プロジェクト内でのコードクローンの調査結果に基づいて開発者は，よく使われている部分のライブラリ化や機ソフトウェア開発を効率的に行うためのソースコード

能が似ているモジュールの統合にその情報を使うことがの再利用はコードクローンを作り込む原因となる．コー

できる．また Imoize ら [3] は再利用のメトリクスによっ

ドクローンの存在はソフトウェアの品質に影響を与えうて Reuse Library の評価を行えることを指摘している．

るため，これらの調査が必要である．例えば組み込みシ

Reuse Library とは再利用可能なソースコードを管理し，開発者によるソースコードの再利用を補助するシステム
である．

ステムの開発に用いられる Arduino にはコード再利用の仕組みがあり，再利用の調査ができると便利であると考えられる．しかし我々の知る限りでは Arduino におけるArduino はプロトタイピングや組み込みシステムの開発などに利用されている身近な電子工作プラットフ
ォームの 1 つである．開発者が開発するソフトウェア
はスケッチと呼ばれる．スケッチは Arduino ボードをPC に接続して Arduino IDE(Integrated Development
Environment) から 1 クリックでアップロードするだけで動作させることができ，LED ランプなどの電子回路をその場で動作させながら開発できる．

ソフトウェアプロジェクトであるスケッチの再利用に関する調査は行われていない．本研究はスケッチでの再利用調査をするために Arduino に特化したコードクローン
検出手法を提案し，実際にスケッチから再利用と考えられるコードクローンを検出した．

1. 緒言
ソフトウェア開発では既存のソフトウェアのソース
コードからその一部を再利用することがある．Sojer とHenkel がオープンソースソフトウェア開発者へのイン
タビューと既存の研究をもとに調査した結果，開発者は新たな機能の実装時に平均して 30%の割合でソースコー
ドを再利用していることがわかった [1]．既存のソース
コードの再利用によってコードクローンが生成される．
コードクローンとは，ソースコード中に存在する互いに一致または類似したコード片を指す [2]．ソフトウェア
中に存在するコードクローンを調べることでソフトウェ
ア開発において有用な情報を得ることができる．例えば

112

Arduino はライブラリというソースコードの再利用を容易にする仕組みを備えている．ライブラリにはサンプルコードである Example Sketch が付属する．開発
者は Example Sketch の一部を自身のプロジェクトに再利用することがあるので，コードクローンが発生する．
Arduino は組み込みシステムの開発に用いられることがあり，その際は発生するコードクローンを把握することが重要である．例えば開発者がソフトウェア中のコードクローンについての情報を把握できれば，コードクロー
ンに関係する問題が発生した場合に迅速に対応できる．
また，Arduino プロジェクトからコードクローンを検出することで，ソースコードの再利用を見つけられれば，開発における Example Sketch などの役割を議論できる．

SEA

ソフトウェア・シンポジウム 2021 in 大分 (オンライン開催)

しかし，我々の調査した限りでは Arduino スケッチにコンパイルし Arduino ボードにアップロードするとボーおけるソースコードの再利用の調査についての研究は存

ド上で動作させられる．

在しない．

開発者は必要に応じてライブラリを自分のスケッチでそこで本研究では Arduino におけるソフトウェア開使うことができる．ライブラリのヘッダファイルをスケッ

発でのコードの再利用の調査を目的として既存のコード

チのソースコードでインクルードするとその機能を使う

クローン検出ツールを組み合わせた調査方法の検討と再ことができる．

利用調査をした．特に Arduino における再利用の仕組み

Arduino ライブラリはその使い方を説明するためのExample Sketch を含むことがある．多くのライブラリ
でそれが提供する機能や対応しているハードウェアの種類ごとに分類されたスケッチが用意されている．これらはIDE から簡単に一覧表示でき，またボードにアップロードできる．このようなスケッチをライブラリの Example
Sketch と呼ぶ．

の 1 つであるライブラリの Example Sketch からのコードの再利用に注目した．この研究における研究設問を以下に示す．

RQ1 Arduino における Example Sketch からのコードの再利用を既存の方法を応用して検出するにはどうすればよいか．

Example Sketch はライブラリの利用時に頻繁に使う
コードをしばしば含んでおりそこからの再利用はスケッ

RQ2 再利用されているコードの特徴はなにか．

チの開発においてよく行われる．例えば Ethernet ライブ
ラリの WebClient という Example Sketch には Ethernet

この研究の貢献は次の 2 つである．

シールドの初期化処理と LAN への接続処理が含まれて• Arduino スケッチにおける Example Sketch からのコードの再利用を既存のコードクローン検出ツールを応用して検出した．

いる．Ethernet シールドを使いたい開発者はこの部分をコピーして自分のスケッチで簡単にシールドを使い始めることができる．

• 検出されたコードクローンの内，再利用と考えられるものの特徴について議論した．

2.2. コードクローン検出ツール CCFinderSW

最後にこの論文の章構成について簡潔に述べる．第 2

本節では，コードクローンの定義とこの研究で利用し章ではこの研究の関心の対象である Arduino とソース

たコードクローン検出ツールである CCFinderSW[4] にコードの分析に利用するコードクローン検出ツールにつついて説明する．

いて説明する．第 3 章では既存のコードクローン検出

コードクローンとは，ソースコード中に存在する互いツールを応用して Arduino スケッチにおけるソースコーに一致または類似したコード片を指す [2]．CCFinderSW

ドの再利用を検出する方法を提案する．続いて第 4 章では意味的ではなく，構文的に類似しているコード片をコー

その手法を用いた再利用の検出結果を示す．その後第 5ドクローンとして検出する．例えばある配列に連続して章で研究設問に答えるための議論をする．最後に第 6 章

値を保存する部分があるとする（リスト 1）．これに対で妥当性への脅威について述べ，第 7 章でこの研究の結してあるアドレスにあるバッファに対してデータを格納論と貢献についてまとめる．

する部分を考える（リスト 2）．ここでリスト 1 の 2〜5行目とリスト 2 の 2〜5 行目はどちらも配列への値の格

2. 背景

納だからコードクローンである．このように完全一致す
るコード片だけでなく相違があるものもある種のコード
クローンとして考える．コードクローンはどれだけの相2.1. Arduino における Example Sketch

違を許すかによって 4 つのタイプに分類されている [5]．
次に提案手法で利用したコードクローン検出手法でArduino のスケッチは一般的な IDE でいうプロジェク
トと対応する．スケッチには唯一のスケッチファイルと任意の数の C あるいは C++ソースコードやヘッダファ
イルが含まれる．作成したスケッチは Arduino IDE である CCFinderSW について説明する．CCFinderSW は
トークンベースのコードクローン検出ツールの一つである．トークンベースとはソースコードの比較にプログ

113

SEA

ソフトウェア・シンポジウム 2021 in 大分 (オンライン開催)

さらに，スケッチの開発者が自分のスケッチを分析す
1
2
3
4
5

リスト 1. 配列にデータを保存するコード片

ることで利用していたライブラリや再利用した Example

int array[4];array[0] = 0;
array[1] = 1;
array[2] = 2;
array[3] = 3;

Sketch を知ることができる．これによりどのライブラリを使っていたか記録されていなかった場合にその情報を復元できる可能性がある．また，スケッチ内の Example
Sketch からの再利用部分を管理することにも役立つ．
このように一般的なソフトウェアでの再利用分析の利点だけでなく，Arduino における開発特有の利点もある．

リスト 2. バッファにデータを格納するコード片
1
2
3
4
5

int create_packet(char * buffer) {buffer[0] = 0x20;
buffer[1] = 0x3F;
buffer[2] = 0x00;
buffer[3] = 0xFF;

3. 提案手法
3.1. コードクローン検出

ラミング言語のトークンを単位として用いるという意

Example Sketch のコードからの再利用はコードクロー味である．CCFinderSW がコードクローンを検出するンとして検出できる．例えばある Example Sketch のコー仕組みを説明する．まず入力されたソースコードからコドの一部がスケッチにコピーされているとする．このときメントを除去し，予め与えられた文法定義に基づいて入その Example Sketch とスケッチとの間のコードクロー

力ソースコードをトークンに分割する．次にトークン列

ンは該当再利用箇所を含む可能性がある．また，スケッに含まれる英数字列を対応するプログラミング言語の予チがある Example Sketch をもとにして作られている場

約語リストを元に予約語と識別子に分ける．その後，比合はその Example Sketch とのコードクローンとなる．

較したいソースコードのトークン列同士で比較を行い一したがって両者の間のコードクローンを検出しその結果致している部分をコードクローンとして検出する．つまを調べることで Example Sketch から再利用されたコー

り識別子や数値はその値にかかわらず同じものとして扱ドを知ることができる．

われるのでソースコード内の変数名や定数が異なってい既存の研究では様々なコードクローン検出ツールが提てもソースコードのトークン列が似ているならばコード案されている [6][7]．本研究でコードクローン検出ツー

クローンとして検出する．CCFinderSW は Java 言語でルを選択する上で重要な要素は 2 つある．1 つは C++

書かれたコマンドラインツールとして実装されている1 ．

言語に対応していること，もう 1 つは関数単位，あるCCFinderSW でコードクローンを検出するには，対象のソースコードをディレクトリに集めて実行するだけで良い．また結果の出力フォーマットが決まっているので処理結果を機械的に処理することもできる．

いはそれよりも細かい粒度でコードクローンを検出できることである．スケッチの主要なソースコードであるス
ケッチファイルとそれに付随するソースコードはすべて

Arduino 言語で書かれている．そして Arduino 言語は
C++言語をもとにしているので検出手法が C++言語に対応していることが重要となる．また，Example Sketch
からの再利用ではファイル単位よりも小さなクローンが多く発生すると考えることができる．なぜならば開発者
は Example Sketch を再利用した結果それとほとんど同じスケッチを作成する可能性が非常に低いからである．

2.3. Arduino プロジェクトでの再利用分析の必要性
本節では，Arduino プロジェクトでの Example Sketchの再利用分析の必要性について述べる．
まず，実世界にあるスケッチについてどの Example

Sketch が頻繁に再利用されているのかを知ることで Example Sketch がスケッチ開発にどれほど影響を与えているか調べられる．例えば似た機能を実装している複数のスケッチに対して調査することである機能を実現する
ことに関連したライブラリの機能を知ることができる．

従って，本研究では C++言語のサポートがあり，かつ細かい粒度でクローン箇所を検出できる CCFinderSW
をコードクローン検出ツールとして選択した．

2.2 節で説明した通り，CCFinderSW でソースコード
間のコードクローンを見つけるためには対象となるソー
スコードをすべて CCFinderSW の入力として与える必1 https://github.com/YuichiSemura/CCFinderSW

114

SEA

ソフトウェア・シンポジウム 2021 in 大分 (オンライン開催)

要がある．したがって，スケッチと Example Sketch とのファイルについてその中でインクルードされているヘッ間のコードクローンを見つけるにはそれらのソースコー

ダファイルの集合を作る．その後 Example Sketch のヘッドをすべて入力すれば良い．しかし，これだけでは 1 つ

ダ集合と対応するライブラリのヘッダファイル集合の積のスケッチに対してかなり時間がかかってしまう．実際，をとり，その Example Sketch の特徴ヘッダファイル集

検出の最初の試みとして後述するスケッチ big aquatan

合とする．スケッチから Example Sketch を絞り込むにと様々な Example Sketch とを入力とし，研究室の計算は次のようにする．まず，スケッチのスケッチファイル

機で CCFinderSW を実行したところ 3 日以上経ってもでインクルードされているヘッダファイルの集合を作る．

2

その後すべての Example Sketch の特徴ヘッダファイル

検出が完了しなかった ．
この処理に時間がかかるのは入力の大きさに原因があ集合についてそれがスケッチのヘッダファイル集合に含ると考えられた．まず，ライブラリの種類は IDE からデまれているか確かめる．そのとき，もし含まれているな

フォルト設定で検索できるものだけでも 3,560 ほどある．

らば対応する Example Sketch を分析対象に入れる．特それぞれのリリースされたバージョンも合わせれば全体

徴ヘッダファイル集合はスケッチから利用できるライブ

で約 16,000 種類になる．あるスケッチで使われるライブ

ラリのヘッダファイルのうち Example Sketch で使われラリはこの数よりもかなり少ない上，実際に参照されたているヘッダファイルの集合である．そのヘッダファイ

Example Sketch も一部にとどまると考えられる．したがって，最新版ライブラリのすべての Example Sketch とbig aquatan のソースコードを入力として CCFinderSWに渡す場合，多くの Example Sketch に対する処理が無駄になる．また，CCFinderSW は入力として与えられた
ソースコードから 2 つのソースコードを選んだペアを作り，コードクローンを検出する．ところが，本研究で注目したいものは Example Sketch とスケッチの間のコー
ドクローンである．このまま入力すれば Example Sketch
同士の分析も行われてしまうのでほとんどの処理が無駄になる．そこで効率よくスケッチと Example Sketch の
コードクローンを検出を行えるように CCFinderSW への入力を作成する手法を作成した．

ルの集合がスケッチでインクルードされているということは対象の Example Sketch で使われている機能が使われている可能性が大きい．これによってスケッチで使用されようとしている機能に最も近い Example Sketch を選ぶことができる．
問題 2 はスケッチと Example Sketch のソースコード
を予めペアにして入力とすることで解決した．まず，スケッチと Example Sketch のソースコードをそれぞれ 1
つずつペアにしたすべての組み合わせを作成する．次に，それらのペアごとにディレクトリを作りそれぞれのソー
スコードを格納する．そして作成したすべてのディレク
トリを入力として CCFinderSW を実行し結果を収集す
る．これによって比較する意味のないペアを除いて分析できる．

3.2. 作成した手法の説明
3.3. 検出の条件
3.1 節では単に Example Sketch とスケッチを入力とすると，スケッチで使われていない Example Sketch についても分析が行われる（問題 1），Example Sketch 同士についても分析が行われる（問題 2）という 2 つの問題が生じることを説明した．

本節では提案手法を用いて実際に再利用検出を行った際の各種条件を述べる．
検出対象のライブラリ群として Arduino IDE のデフォ
ルトライブラリメタデータ3 にあるものを用いた．メタ

ここでは本研究で作成した手法で以上の問題をどのよ

データとライブラリのダウンロードはどちらも 2021 年 1

うに解決したかを説明する．

月 4 日から 1 月 5 日のうちに行った．ライブラリは計算問題 1 はスケッチと関係があると考えられる Example

リソースの都合上ダウンロードした時点で最新バージョ

Sketch を絞り込むことで解決した．まず，ライブラリごとにライブラリのソースコードであるヘッダファイルの集合を作る．次に，すべての Example Sketch のスケッチンのものだけを検出対象にした．CCFinderSW のバー

2 CPU は Intel Xeon Silver 4210，RAM は 128GB，作業用 SSD
は 512GB の NVMe SSD だった

3 https://downloads.arduino.cc/libraries/library_index.json

ジョンは 1.0 を用い，CCFinderSW のパラメータは表 1のように設定した．

115

SEA

ソフトウェア・シンポジウム 2021 in 大分 (オンライン開催)

表 1. CCFinderSW のパラメータ
パラメータ値

リスト 3. スケッチの big aquatan.ino の該当箇所

対象の言語 (-l)

cpp

検出対象の範囲 (-w)

2（ファイル間のみ）-antlr”ino|pde|c|h|cpp|hpp|cxx|hxx|cc”

文字コード (-charset)

auto

127
128
129
130
131
132
133
134
135
136
137

この表に記述がないものは入力ディレクトリと出力
ファイル名に関わるオプションである”-d”と”-o”を除い

138
139

てすべてデフォルト値を指定した．また，Arduino 言語のファイルも分析対象に入れるため，grammarsv4 ディ

140

Wire1.begin(PIN_SDA1, PIN_SCL1);eyes.begin(-5, 0, 0, 0);
if (apds.init()) {Serial.println(F("LAPDS-9960␣
initialization␣complete"));} else {Serial.println(F("Something␣went␣wrong␣
during␣APDS-9960␣init!"));}
if (apds.enableGestureSensor(true)) {Serial.println(F("Gesture␣sensor␣is␣now␣
running"));} else {Serial.println(F("Something␣went␣wrong␣
during␣gesture␣sensor␣init!"));}

レクトリに拡張子”ino”，”pde”のための文法定義を追加した．文法ファイルは C++言語のために予め用意されている CPP14.g4 を流用した．-antlr オプションの正規表

ケッチファイル6 の 71-88 行目および ColorSensor とい

現に拡張子 hh にあたるパターンが含まれていないがこう Example Sketch のスケッチファイル7 の 53-66 行目とれは意図的なものでない．検出試行に用いたソースコー

コードクローンとして検出された．

ド全てに対し拡張子が hh であるようなヘッダファイル

SparkFun APDS9960 RGB and Gesture Sensor ライ
ブラリは APDS-99608 センサの制御ライブラリである．
このライブラリはセンサの初期化とジェスチャ認識などの各種機能の有効化機能を実装している．big aquatan
スケッチは APDS-9960 センサを用いてハンドジェスチャを認識する機能がある． また，該当部分のメッセージ
文字列やコードの書式がよく似ており，検出された部分は再利用された部分であると言える．

は存在しなかったため再度試行しなくて良いと判断した．
検出試行は Example Sketch の絞り込みを行った場合と行わなかった場合の両方行った．

4. 検出の結果
検出の結果 Example Sketch を絞り込んだ場合は 5 ペ
ア，絞り込まなかった場合は 86 ペアのソースコードから

これらの部分は 5 個のソースコードのペアから見つか

コードクローンが検出された．この結果からさらにコーり，範囲が重なっているコードクローンを含めて全部でドが実装している機能をもとにコードクローンを分類し5 個だった．

た．それぞれの条件に分けて以下で述べる4 ．

4.2. Example Sketch を絞り込まなかった場合
4.1. Example Sketch を絞り込んだ場合
この条件で検出されたクローンは次のように分類できた．

この条件で検出されたクローンはすべて SparkFun
5

APDS9960 RGB and Gesture Sensor ライブラリ バー
ジョン 1.4.2 を使った初期化コードだった．特に 1 つの 分類 1 SparkFun APDS9960 RGB and Gesture Sensor ラ
イブラリを使った初期化コード
コードクローンはジェスチャ検出機能を有効化する部分
6 https://github.com/sparkfun/APDS-9960_RGB_and_が含まれていた．big aquatan での該当箇所（リスト 3）
Gesture_Sensor/blob/V_H1.0_L1.4.2/Libraries/Arduino/を示す．
examples/GestureTest/GestureTest.ino
7 https://github.com/sparkfun/APDS-9960_RGB_and_
Gesture_Sensor/blob/V_H1.0_L1.4.2/Libraries/Arduino/
examples/ColorSensor/ColorSensor.ino
8 https://www.broadcom.com/products/optical-sensors/
integrated-ambient-light-and-proximity-sensors/apds9960

この部分は GestureTest という Example Sketch のス
4 この結果の再現用のデータなどは次の場所にある．:

https://
github.com/ikubaku/ss2021-scripts
5 https://github.com/sparkfun/APDS-9960_RGB_and_
Gesture_Sensor/

116

SEA

ソフトウェア・シンポジウム 2021 in 大分 (オンライン開催)

時刻のアクセス部分も対応するメソッドを呼び出すだけで実現できるので特殊なものであるとは言えない．したリスト 4. スケッチの big aquatan.ino の該当箇所
653
654
655
656
657
658

DateTime now = rtc.now();char str[20];sprintf(str, "%04d-%02d-%02d␣%02d:%02d:%02d", now.year(), now.month(),now.day(), now.hour(), now.minute(),now.second());
ts = str;
return ts;

がってこの部分が再利用であるか判断できなかった．
これらの部分は 8 個のソースコードのペアから見つか
り，範囲が重なっているコードクローンを含めて全部で10 個だった．

4.2.3. 分類 3 に属するコードクローン

分類 2 リアルタイムクロックの時刻取得コード
分類 3 SNTP 関連のコード

分類 3 に属するコードクローンはさらに 2 種類に分類できた．1 つは SNTP パケットを作成するコード，もう 1

分類 4 arduino-esp32 の OTA イベント処理コード

つは SNTP サーバから受信したデータをもとに 1900 年か

分類 5 再利用ではないコード

らの経過秒数を計算するコードだった．big aquatan での該当箇所（リスト 5，6）はそれぞれ RTCDue ライブラリの RTCDue NTP WIFI with timezone という Example

4.2.1. 分類 1 に属するコードクローン

Sketch のスケッチファイル10 の 183-203 行目，log4Esp
ライブラリの AdvancedDemo という Example Sketchのスケッチファイル11 の 137-143 行目とコードクローン
として検出された．

分類 1 に属するコードクローンの数は 5 つだった．これは Example Sketch を絞り込んだ場合に検出されたものだと考えられる．なぜならこの条件で比較した Example

Sketch の中に絞り込んだ場合の Example Sketch が全て含まれている上，検出されたクローンが同じ 5 箇所だったからである．

SNTP パケットを作成する部分は識別子や周辺のコメントなどが一致しており，再利用されたコードであると言える．
一方で受信したデータを処理するコードはスケッチの4.2.2. 分類 2 に属するコードクローン

ものと Example Sketch のものの間で違いが見られた．

big aquatan のコードでは Example Sketch のコードで実装されているタイムゾーンに合わせて秒数を調整する
コードが失われている．また packetBuﬀer[43] の直後の0 ビットシフトは Example Sketch のコードには存在しなかった．それでもスケッチと Example Sketch のコー
ド片には識別子などの共通点が見られるので，共通の源流となるコードを持つなど何らかの関係があると考えられる．

分類 2 に属するコードクローンは主にリアルタイムク
ロックから取得した時刻を書式化する処理を実装していた．big aquatan での該当箇所（リスト 4）は MCP7940
ライブラリの SetAndCalibrate という Example Sketchのスケッチファイル9 の 173-180 行目とコードクローン
として検出された．
コードクローンを含む Example Sketch に対応するライブラリはすべてリアルタイムクロックの制御ライブラ

これらの部分は 55 個のソースコードのペアから見つリだった．これらの Example Sketch も多少の改変を除

かり，範囲が重なっているコードクローンを含めて全部

けば現在時刻を取得し文字列に初期化する処理を含んでで 171 個だった．このことからコードクローンとして検いた．しかし，big aquatan では sprintf 関数の行の改行出された部分は様々なライブラリの Example Sketch で

位置が now.day メソッドの呼び出し直前にある．それに再利用されていることがわかる．

対し Example Sketch では now.year や now.hour メソッ
ド呼び出しの直前で改行されていた．また書式文字列は

10 https://github.com/MarkusLange/RTCDue/blob/RTCDue_
Version_1.1/examples/RTCDue_NTP_WIFI_with_timezone/
RTCDue_NTP_WIFI_with_timezone.ino
11 https://github.com/hunsalz/log4Esp/blob/v1.0.1/
examples/AdvancedDemo/AdvancedDemo.ino

ISO8601 に基づいた日時表現とよく似ているほか，現在
9 https://github.com/Zanduino/MCP7940/blob/v1.2.0/
examples/SetAndCalibrate/SetAndCalibrate.ino

117

SEA

ソフトウェア・シンポジウム 2021 in 大分 (オンライン開催)

リスト 7. スケッチの big aquatan.ino の該当箇所

リスト 5. スケッチの ntp.cpp の SNTP パケット

162

作成部分

163
10
11
12
13
14
15
16

164

// send an NTP request to the time server at
the given address
void NTP::sendPacket() {

165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182

// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);// Initialize values needed to form NTP
request// (see URL above for details on thepackets)
packetBuffer[0] = 0b11100011; // LI,
Version, Mode
packetBuffer[1] = 0; // Stratum, or typeof clockpacketBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock
Precision// 8 bytes of zero for Root Delay & RootDispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;// all NTP fields have been given values,
now// you can send a packet requesting atimestamp:
udp.beginPacket(timeserver.c_str(), 123);//NTP requests are to port 123
udp.write(packetBuffer, NTP_PACKET_SIZE);

17
18
19
20
21
22
23
24
25
26
27
28
29
30

.onProgress([](unsigned int progress,
unsigned int total) {digitalWrite(2, (progress / (total / 100))% 2);
Serial.printf("Progress:␣%u%%\r", (progress / (total / 100)));}).onError([](ota_error_t error) {Serial.printf("Error[%u]:␣", error);if (error == OTA_AUTH_ERROR)
Serial.println("Auth␣Failed");else if (error == OTA_BEGIN_ERROR)
Serial.println("Begin␣Failed");else if (error == OTA_CONNECT_ERROR)
Serial.println("Connect␣Failed");else if (error == OTA_RECEIVE_ERROR)
Serial.println("Receive␣Failed");else if (error == OTA_END_ERROR)
Serial.println("End␣Failed");});ArduinoOTA.begin();webServer.on("/", handleStatus);
webServer.on("/reboot", handleReboot);recvDumpV3 という Example Sketch の BaseOTA.h12の 39-54 行目とコードクローンとして検出された．
OTA とはネットワーク上にあるデバイスのソフトウ
ェアのアップデートを可能にする機能である．Arduinoの場合は ArduinoOTA ライブラリでその機能を実現している．検出された部分では”ArduinoOTA”という識別子が出現するのでこの機能に関係があると考えられる．

リスト 6. スケッチの ntp.cpp の受信データ処理

しかし，ArduinoOTA ライブラリ13 の Example Sketch

部分と検出部分を比較したところ，検出された部分は Ar-

37
38
39
40
41
42
43

duinoOTA には存在しなかった．更に調査したところ検出された部分と似た部分を以下の Example Sketch が見つかった．

unsigned long secsSince1900 = 0;// convert four bytes starting at location
40 to a long integer
secsSince1900 |= (unsigned long)packetBuffer[40] << 24;
secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
secsSince1900 |= (unsigned long)packetBuffer[43] << 0;return secsSince1900 - 2208988800UL; //seconds since 1970

• arduino-esp32 の BasicOTA14• ESP8266/Arduino の BasicOTA15
これらはそれぞれ ESP32 シリーズと ESP8266 マイク
ロコントローラ向けの Arduino ソフトウェアの実装に含まれる Example Sketch である．実際，検出されたコー
12 https://github.com/crankyoldgit/IRremoteESP8266/
blob/v2.7.14/examples/IRrecvDumpV3/BaseOTA.h
13 https://github.com/jandrassy/ArduinoOTA
14 https://github.com/espressif/arduino-esp32/blob/master/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.
ino
15 https://github.com/esp8266/Arduino/blob/master/
libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino

4.2.4. 分類 4 に属するコードクローン
分類 4 に属する検出部分には OTA のエラーイベン
ト処理の実装が含まれていた．big aquatan での該当箇所（リスト 7）は IRremoteESP8266 ライブラリの IR-

118

SEA

ソフトウェア・シンポジウム 2021 in 大分 (オンライン開催)

リスト 8. スケッチの actionqueue.h の該当箇所
34
35
36
37
38
39
40
41
42
43

リスト 9. ES92016 -0.1.9 の openFrameworks/asci-

public:actionQueue(AquatanEyes *e, AquatanArms *a, Camera *h,
NeoPixels *c); //, Charger *c);void queueEyes(int l_shape, int r_shape,
int m);
void queueArms(int left, int right, inttime);
void queueArmLeft(int left, int time);void queueArmRight(int right, int time);void queueHead(int pan, int tilt);
void queueHeadPan(int pan);void queueHeadTilt(int tilt);

i/src/ofApp.h の該当箇所
13
14
15
16
17
18
19
20
21
22

void keyReleased(int key);
void mouseMoved(int x, int y );void mouseDragged(int x, int y, int button);void mousePressed(int x, int y, int button);void mouseReleased(int x, int y, int button);
void mouseEntered(int x, int y);void mouseExited(int x, int y);void windowResized(int w, int h);void dragEvent(ofDragInfo dragInfo);
void gotMessage(ofMessage msg);

ドクローンを含む Example Sketch に対応するライブラ
リはすべて ESP32 か ESP8266 を用いたシステムを前提

リスト 10. Esp32SimplePacketComs17 -0.7.0 のとしていた．したがってこれらの Example Sketch でもSwarmRobotExample/SwarmRobotExample.inoの該当箇所

コードが再利用されたと考えられる．
コードクローンを観察するとエラーメッセージやエラーコードを確認する際の比較の順番などが一致

13

しており，検出された部分は再利用されている可能性

14
15
16
17
18
19
20
21
22
23
24
25

があると考えられる．特に big aquatan の該当部分はESP8266/Arduino の BasicOTA にある部分とよく似ていた．したがって該当部分はその Example Sketch の実装を源流としている可能性がある．
これらの部分は 6 個のソースコードのペアから見つか
り，範囲が重なっているコードクローンを含めて全部で30 個だった．

// User data is written into the buffer tosend it backvoid event(float * buffer) {int numberOfFloats = 15;
buffer[0] = 10; // X Locationbuffer[1] = 0; // Y Locationbuffer[2] = 0; // Z Locationbuffer[3] = 45; // azimuth
buffer[4] = 0; // elevationbuffer[5] = 0; // tilt
buffer[6] = 100; // X size
buffer[7] = 100; // Y size
buffer[8] = 100; // Z size// Serial.println(にある異なる関数とペアとして検出された．big aquatan

4.2.5. 分類 5 に属するコードクローン

スケッチにあったこれらの関数プロトタイプ宣言やクラ分類 5 に属するコードクローンは再利用ではないと考スメソッド宣言はすべて独自の機能に関係するものだとえられるもので，さらに 2 種類に分類できた．

考えられるので再利用ではないと言える．
また，ntp.cpp に含まれる SNTP パケット作成処理の• 関数プロトタイプ宣言とクラスメソッド宣言

部分と Example Sketch で見られる様々な配列への代入• 配列への値の保存部分もコードクローンとして検出されていた．これらは処理の意味が異なっており再利用ではないと考えられる．

検出例をそれぞれリスト 8，9 とリスト 10 に示す．Ex-

これらの部分は 12 個のソースコードのペアから見つ

ample Sketch の配列への値の保存部分はすべてスケッチの SNTP パケット作成部分（リスト 5）とペアになっていた．

かり，範囲が重なっているコードクローンを含めて全部で 39 個だった．

big aquatan のソースコードに含まれる関数プロトタ
イプ宣言やクラスメソッド宣言は Example Sketch の名前

5. 議論

16 https://github.com/hideakitai/ES920

この章では前の章の結果に基づいて議論し，研究設問

17 https://github.com/madhephaestus/に回答する．

Esp32SimplePacketComs

119

SEA

ソフトウェア・シンポジウム 2021 in 大分 (オンライン開催)

書き込まれるブートローダや入出力など基本的な操作を

5.1. 再利用の検出手法提供するコード，そしていくつかのライブラリが含まれまず研究設問 1 に回答する．

ている．コアに含まれるライブラリは基本的な機能を提再利用の検出試行では提案手法を用いて再利用と考供する少数のライブラリとボード特有の機能を提供する

えられるいくつかのコード片を発見できた．Example

ライブラリがある．arduino-esp32 の ArduinoOTA ライ

Sketch の絞り込みのありなしにかかわらず比較は 3 日以内に完了し，再利用ではない検出結果も少なかった．したがってこの手法は現実的なリソースで Example Sketch
からの再利用を探すことに一定の効果があると言える．

ブラリや WiFi ライブラリもこのライブラリの一種である．これらのライブラリの Example Sketch も考慮に入れたい場合は Arduino コアのライブラリからも Example

Sketch を予め集めておく必要があると言える．

一方で提案した Example Sketch の絞り込みが再利用

5.2. 再利用の特徴

されたコードの発見を妨げていることもわかった．検出できなかったコードは第 4 章の分類 2 にあたるもの，分次に研究設問 2 に回答するため，前の章の発見できた類 3 にあたるもののうちパケット送信を行うコード，分

コード片の分析をまとめる．

類 4 にあたるコードの 3 つである．それぞれについて検出できなかった原因として考えられるものを議論する．

ここでは再利用であるか判断できなかったコードを省

まず分類 2 のコードについて考える．Example Sketch

いた，分類 1，分類 3 のうちパケット送信を行うもの，を絞り込んだときリアルタイムクロック関係のものとし

分類 4 に当たるコードそれぞれについて特徴をまとめる．

て RTClib の Example Sketch が対象に含まれていた．

分類 1 や分類 4 のコードはエラーの提示方法を工夫す

しかし RTClib の Example Sketch には発見されたようるなどの動機がない限り改変する必要のないコードだっな書式化処理はなかった．つまりヘッダファイルの共通た．また，SNTP パケット送信コードについても時刻を性から Example Sketch を絞り込むと似たような機能を取得するだけならば内容を工夫する必要はない．実際

持つ異なるライブラリからの再利用を検出できないと考

Blynk ライブラリ18 ではこの部分が BlynkSimpleEthernetSSL.h に取り込まれている．したがって再利用されているコードにはある機能を実装するコードスニペット
あるいは一般的なソフトウェア開発でのライブラリとも言える特徴があると考えられる．

えられる．
次に SNTP パケット送信コードがなぜ検出できなかったについて議論する．このコードは UDP 通信機能を使っているあるいは提供しているライブラリの Example

Sketch にあった．例えば log4Esp の AdvancedDemo では WiﬁUdp.h が include されており，WiFi ライブラリの UDP 通信機能が SNTP 通信のために使われている．
一方 big aquatan ではスケッチファイルでなく ntp.h の中で include されていたため絞り込みの際にそのヘッダを考慮に入れることができていなかった．したがってどのヘッダが include されているのかを絞り込みの情報に使うことはそのままでは難しく，ヘッダファイル内のinclude プリプロセッサ命令まで考慮する必要があるとわかった．

しかしこの検出試行で発見できた再利用の種類は 3 種
類にとどまった上，対象としたスケッチも 1 つのみであるため一般的な Arduino における開発に一般化できない．再利用の特徴についてはさらなる調査が必要であると言える．

6. 妥当性への脅威
検出試行では計算リソースの都合上ダウンロードした時点で最新のライブラリのみ検出に使用した．した

分類 4 のコードが検出できなかったことには他の要因

がって，もし古いバージョンにのみ見られるコード片がが関わっている．ライブラリをダウンロードする際は，ラドした．しかし，これらには Arduino コアが提供するラbig aquatan で再利用されていた場合はその部分を検出できない．このライブラリバージョンの制約は妥当性への脅威となりうる．

イブラリは含まれていない．Arduino コアとは Arduino

また，提案した手法を実現するツールは執筆者が開発

ボードやマイクロコントローラの種類ごとに実装されてし，必要と思われる部分にはテストを行った．しかし，イブラリメタデータに登録されているものをダウンロー

いる中核となるソフトウェアである．これにはボードに18 https://github.com/blynkkk/blynk-library

120

SEA

ソフトウェア・シンポジウム 2021 in 大分 (オンライン開催)

ツールにまだ未知のバグが含まれている可能性は否定で[6] H. Sajnani, V. Saini, J. Svajlenko, C.K. Roy, andC.V. Lopes, “SourcererCC: Scaling code clone detection to big-code,” In Proc. of ICSE, pp.1157–
1168, 2016.

きず，妥当性への脅威となりうる．

7. 結論[7] L. Jiang, G. Misherghi, Z. Su, and S. Glondu,“Deckard: Scalable and accurate tree-based detection of code clones,” In Proc. of ICSE, pp.96–105,
IEEE, 2007.

本研究では Arduino プロジェクトにおける Example

Sketch からのコードの再利用を CCFinderSW への入力を工夫して作成することで分析し，再利用されている部
分の特徴を調べた．一方で，再利用部分を見つけただけ
ではそのコードがどこから再利用されたのか明らかにできないという課題が見つかった．
本研究における今後の課題は以下のとおりである．まず，再利用元や再利用の目的を明らかにするため，開発者にインタビュー調査を行う予定がある．また，提案手法において入力データの絞り込み方法に課題があった．
今後は提案手法を課題を明確化し手法の改良や結果の応用方法について研究を進めるべきであると考える．

参考文献[1] M. Sojer and J. Henkel, “Code reuse in open
source software development: Quantitative evidence, drivers, and impediments,” Journal of the
Association for Information Systems, vol.11, no.12,
pp.868–901, 2010.
[2] 肥後芳樹，楠本真二，井上克郎，“コードクローン
検出とその関連技術，” 電子情報通信学会論文誌. D，vol.91，no.6，pp.1465–1481，jun 2008．
[3] A.L. Imoize, D. Idowu, and T. Bolaji, “A brief
overview of software reuse and metrics in software engineering,” World Scientiﬁc News, vol.122,
pp.56–70, 2019.
[4] 瀬村雄一，吉田則裕，崔恩瀞，井上克郎，“多様なプログラミング言語に対応可能なコードクローン検出
ツール CCFinderSW，” 電子情報通信学会論文誌 D，vol.103，no.4，pp.215–227，2020．
[5] C.K. Roy, J.R. Cordy, and R. Koschke, “Comparison and evaluation of code clone detection techniques and tools: A qualitative approach,” Scienceof computer programming, vol.74, no.7, pp.470–
495, 2009.

121

SEA