本稿は、メトリクスツール開発に向けた新しい枠組みの構成要素「メトリクスプラグイン」を開発するためのガイドラインである。
設計思想や仕様の紹介を通して、メトリクスプラグインの開発を促進することが目的である。
商用・非商用を含め、世界には様々なメトリクスツールが存在する。
しかし、その多くは指標値の一覧表示、もしくはグラフとして図示する程度のものであり、必ずしもユーザに対して有意義な情報を提供できるとは限らない。
(あまり直感的でない。)
ただ、それら現存のツールに冗長さが見られるのも無理はない。
ツールを利用するユーザの立場ごとに、どの指標が必要か不必要かを判断しなければならないが、それはツールの開発者の知るところではない。
その結果、あらゆる指標値をそのまま全て列挙せざるを得ないのだろう。
この冗長さを打開すべく、メトリクス向けの新たな枠組みを用いた実装物「SynapseScript」「メトリクスプラグイン」が開発された。
入力値に対応した出力値を応答する「メトリクスプラグイン」を、ユーザが自分の用途に合わせて接続することで、ユーザ自身の必要とする情報を効率的に提供するのである。
ここで特筆すべきは、その「メトリクスプラグイン」をユーザ自身で新たに作成できる点である。
ユーザの思うようなプラグインが用意されていない場合、ユーザは自身の持てる技術を存分に活かしながら独自のプラグインを開発できるのだ。
そんな「自分でプラグインを開発しよう」とする開発者を助けるため、本ガイドラインを作成した。ご活用いただけるなら幸いである。
ここでは、本ガイドラインに記載されている用語の定義を行う。
-
SynapseScript
関数の役割を果たす「メトリクスプラグイン」を接続するための仕組み。データ記述言語。
-
指標
プログラムなどの評価対象を計測する側面。いわば「ものさし」に相当する。実例として「行数」や「複雑度」など。
-
入力(input)/ 出力(output)
変換系(メトリクスプラグイン)がデータAをデータBに変換する時、変換前のデータ(つまりA)を入力と呼び、変換後のデータ(つまりB)を出力と呼ぶ。
また、この変換のため変換系に対してデータAの提供を行うが、この行為自体も入力と呼び、変換系がデータBを作り出す行為も出力と呼ぶ。
-
ビルドツールmake
プログラムからソフトウェアを構築(ビルド)するための複雑な手続きを、makeコマンドの利用により単純化するもの。
-
プログラム
ソフトウェアプログラム。コンピュータを操作するための言語表現。ソースコードとも。
-
メトリクス
プログラムなどの評価対象を、何らかの尺度・指標(ものさし)で計測することを言う。
-
メトリクスプラグイン
具体的なメトリクスの処理(写像処理)を行う機能単位。何らかの入力値に対応する出力値を応答する変換系(翻訳者)である。
例えば、プログラムを入力して、そのプログラムの行数を計測して出力するなどを実現するもの。
技術的概要
メトリクスプラグインは、ある入力値を一定の規則に従って変換し、出力値を応答するものである。
より具体的には、ソフトウェアのビルドに用いられるツール「make」を転用して、プラグインとしてのデータ変換処理を実現する。
makeのマクロ定義によって情報を入力し、その変換処理の結果を標準出力に対してJSON形式で出力する。
また、makeコマンドで動作するため、SynapseScriptを経由せず単体で用いることも可能である。
(図中の橙色がmakeに相当する。)
図1 プラグインのデータ入力とデータ出力
|
ただし、実際はこう単純には使えない。入力データや出力データに特殊文字が含まれている場合、そのエスケープ処理が必要になるのだが、
動作環境に依存しないように配慮しようとすると、そのエスケープ処理自体が煩雑になってしまう。そこで、回避策としてBase64エンコードを用いることにする。
プラグインの入出力に際してデータをそのまま扱うのではなく、Base64でエンコードした形で扱おうというものである。
図2 プラグインのデータ入力とデータ出力(Base64利用)
|
エンコードやデコードの手間が掛かってしまうが、これで大方のデータを取り扱うことができる。ただし、makeが動作しているシェルの制約で、入力データの長さには限りがある。
巨大なデータを扱う場合には、データそのものを直接扱うのではなく、そのデータの在り処を示す情報を用いて間接参照するなど、工夫が必要になろう。
以上が、メトリクスプラグインの概要である。
ファイル構成
一つのメトリクスプラグインは、一つのディレクトリに対応する。以下には「Division2」というプラグインのファイル構成を示そう。
図3 プラグイン「Division2」のファイル構成
|
プラグインディレクトリ「Division2」の中に幾つかのファイルが含まれているが、この中の必須項目は「Makefile」のみであり、それ以外のファイルは全て任意項目である。
従って、メトリクスプラグインはその開発者によって自由に組み立てることができるのだ。
例題プラグイン(割り算)
図4 割り算のメトリクスグラフ
|
ファイル構成を示したメトリクスプラグイン「Division2」だが、端末(ターミナル)を介して実際に動かしてみよう。
必要であれば、こちら(Division2.zip)を解凍してご利用いただきたい。
プラグインディレクトリ「Division2」を用いて、割り算「100÷3」を実演するが、それに先立ち「100」と「3」をBase64エンコードに掛けておかねばならない。
$ printf "100" | base64
MTAw
$ printf "3" | base64
Mw==
「100」は「MTAw」、「3」は「Mw==」と表される。では、dividend(被除数)を「MTAw」、divisor(除数)を「Mw==」として、メトリクスプラグインによる割り算を実行してみよう。
$ cd /path/to/Division2
$ make dividend="MTAw" divisor="Mw=="
{"quotient" : "MzMuMzMzMzMzMzMzMzMzMw==", "floorQuotient" : "MzM=", "remainder" : "MQ=="}
quotient(商)として「MzMuMzMzMzMzMzMzMzMzMw==」、floorQuotient(整数化した商)として「MzM=」、remainder(剰余)として「MQ==」が得られた。
これをBase64でデコードしてみよう。
$ printf "MzMuMzMzMzMzMzMzMzMzMw==" | base64 --decode
33.3333333333333
$ printf "MzM=" | base64 --decode
33
$ printf "MQ==" | base64 --decode
1
それぞれ「33.3333333333333」「33」「1」と正しく計算されている。つまり、メトリクスプラグインによって割り算を行うことができた。
以降では、この割り算プラグイン(Division2)を題材として説明する。
データの入力
メトリクスプラグインへのデータ入力は、次のようにして記述する。ここでは「xxxx」という4文字を入力する。
make input="xxxx"
これは最も単純な1入力の例であるが、先の割り算のように多入力の場合は次のように記述する。
make dividend="MTAw" divisor="Mw=="
上記2例の中で「input」「dividend」「divisor」と記している部分があるが、これはキー(makeの用語では「マクロ」)と呼ぶ。
等号「=」を挟んで、「"xxxx"」「"MTAw"」「"Mw=="」として引用符で囲んだ文字列を、値と呼ぶ。
値は、プラグインが利用される時に初めて具体的なデータを得るものであり、プラグインの開発時には何が渡されるか不定であるが、
キーはプラグインの開発者が独自に定めることができ、何が与えられるかわからない値を取り扱うための識別子となる。
キーと値のペアでデータ入力を行い、複数の入力が必要ならばスペースで区切って連ねることになる。
こうして渡された入力データは、Makefile内で「$(input)」「$(dividend)」「$(divisor)」と記述すれば利用できる。
あとは、この入力データを好きなように変換し、次節で述べる形式に従って出力するだけである。
データの出力
前節の例では「xxxx」という文字列を入力していたが、今度はその文字列をそのままの形で出力しよう。JSONという形式に従って以下のように出力される。
{ "output" : "xxxx" }
入力の際と同様に、ここでもキー「"output"」と値「"xxxx"」のペアで表現される。
ちなみに、入力の際はキーに引用符「"」が付かなかったが、出力の際は引用符を付ける。これはJSONの仕様によるものである。
次に示すものは、複数値を出力する例(割り算)である。「quotient」「floorQuotient」「remainder」の3ペアを
{"quotient" : "MzMuMzMzMzMzMzMzMzMzMw==", "floorQuotient" : "MzM=", "remainder" : "MQ=="}
入力のキーと同じく、出力のキーも開発者が独自に定めることができる。また、複数の値を出力するには、カンマ「,」で区切れば良い。
Makefile
割り算プラグイン「Division2」のMakefileの内容を以下に示そう。(一部修正)
#
# Division2 - Metrics for SynapseScript
#
# Created by M.Miyazaki [2013.01.06]
#
all:
@sh ./Scripts/Division2.sh "$(dividend)" "$(divisor)"
inputs:
@echo dividend divisor
outputs:
@echo quotient floorQuotient remainder
help:
@less help.txt
簡単な記述であることがお分かりいただけるだろう。このMakefileには4つのターゲット「all」「inputs」「outputs」「help」が定義されている。それぞれを以下に説明する。
-
all(デフォルトターゲット)
入力値を出力値に変換する具体的な処理は、このターゲット「all」に記述する。これは必須ターゲットである。
この例では入力データ2つを、また別のシェルスクリプト(./Scripts/Division.sh)に渡している。割り算の計算は、そのシェルスクリプト内で記述されているのだ。
より詳細に述べれば、そのスクリプト内ではプログラミング言語Perlを用いて割り算の処理を行なっている。
もちろん、計算処理をPerl以外の言語で実装しても構わない。プラグイン開発者に言語の選択が委ねられているのだ。
-
inputs
このメトリクスプラグインが、どのような入力値を必要としているか、その一覧を出力するターゲットである。これは必須ターゲットである。
プラグインディレクトリ内で、ユーザが「make inputs」と叩けば、次のように出力される。
dividend divisor
「dividend」と「divisor」の2入力を与えれば良い、と分かる。これは入力データのキーを機械的に出力するだけで良い。
SynapseScriptの処理系が、この情報を利用することになる。入力データのキーと、区切り文字としての半角スペースと改行のみが許されている。
-
outputs
このメトリクスプラグインが、どのような出力値を応答するか、その一覧を出力するターゲットである。これは必須ターゲットである。
プラグインディレクトリ内で、ユーザが「make outputs」と叩けば、次のように出力される。
quotient floorQuotient remainder
他の説明は、ターゲット「inputs」と同様である。
-
help
このメトリクスプラグインが、どのような変換を行うかの説明文を表示するターゲットである。これは任意ターゲットである。(ただし、利便性のため、できる限り用意していただきたい。)
上述したターゲット「inputs」「outputs」は機械的なものであったが、このターゲットでは、人が読むことを前提にした説明文を表示することになる。
プラグイン「Division2」における説明文を以下に示そう。
#
# Division2 - Metrics for SynapseScript
#
# Created by M.Miyazaki [2013.01.06]
# Modified by M.Miyazaki [2013.02.18]
#
### Description
Calculate division.
### Inputs
dividend : A number that divided.
divisor : A number that divide.
### Outputs
quotient : Quotient of division.
floorQuotient : Quotient of division with floor.
remainder : Remainder of division.
### Examples
Try this example...
$ make dividend=`printf "100" | base64` divisor=`printf "21" | base64`
> {"quotient" : "NC43NjE5MDQ3NjE5MDQ3Ng==", "floorQuotient" : "NA==", "remainder" : "MTY="}
$ printf "NC43NjE5MDQ3NjE5MDQ3Ng==" | base64 --decode
> 4.76190476190476
$ printf "NA==" | base64 --decode
> 4
$ printf "MTY=" | base64 --decode
> 16
Thank you for trying SynapseScript! :-)
その記述内容や形式は基本的に自由であるが、1.何を実現するプラグインか、2.何を入力するか、3.何を出力するか、の3つについては記載していただきたい。
また、可能であれば利用例を掲載していただきたい。きっとユーザの利用を助けるだろう。
説明すべきターゲットは以上の4種類である。これら4つのターゲット名と重複しなければ、他のターゲットを用意していただいても構わない。
ここでは実例として、四則演算のメトリクスプラグイン「Arithmetic」を開発する。
手順1. プラグインを設計する
まずは、プラグインの設計を行う。プラグインは多入力多出力を許す関数であり、図5のように描くことができよう。
今回は、何かしらの2数を入力して、加算・減算・乗算・除算を行い、和・差・積・商を出力するものである。
つまり「Arithmetic」は、2入力4出力のメトリクスプラグインだ。
図5 プラグイン「Arithmetic」のメトリクスグラフ
|
手順2. プラグインの形を整える
次に、メトリクスプラグインの基盤となるファイル群を作成する。プラグインディレクトリ「Arithmetic」を作成し、その中に「Makefile」「help.txt」を作成する。
また、算術処理はPHPで記述することにして「Scripts/Arithmetic.php」を作成する。いずれも空のテキストファイルで良い。
もちろん、PHPでなく他の言語でも良い。また、Makefile内で計算処理を済ませてしまっても構わない。
図6 プラグイン「Arithmetic」のファイル構成
|
手順3. Makefileの作成
メトリクスプラグインの核となる「Makefile」を作成する。以下のように記述すれば良いだろう。
実を言うとその中身は、プラグイン「Division2」のものと酷似している。それほど形式的なものなのだ。テンプレートを1つ用意しておけば、あとはそれを使い回すだけで良い。
図5で示したとおり、入力は「input1」「input2」の2つ、出力は「sum」「difference」「product」「quotient」の4つである。
#
# Arithmetic - Metrics for SynapseScript
#
# Created by M.Miyazaki [2013.02.19]
#
all:
@php ./Scripts/Arithmetic.php "$(input1)" "$(input2)"
inputs:
@echo input1 input2
outputs:
@echo sum difference product quotient
help:
@less help.txt
手順4. 変換処理の実装
入力値を出力値に変換する部分を実装しよう。今回はPHPを用いて以下のように記述した。これを、Scriptsディレクトリ内のArithmetic.phpとして保存しておく。
説明用の簡単な実装を示しているが、本来は適切な例外処理を施すべきである。(非数値の入力やゼロ除算等を考慮し、対処すべきである。)
<?php
#
# Arithmetic - Metrics for SynapseScript
#
# Created by M.Miyazaki [2013.02.19]
#
$input1 = base64_decode($_SERVER['argv'][1]);
$input2 = base64_decode($_SERVER['argv'][2]);
$sum = base64_encode($input1 + $input2);
$difference = base64_encode($input1 - $input2);
$product = base64_encode($input1 * $input2);
$quotient = base64_encode($input1 / $input2);
$formatString = "{\"sum\" : \"%s\", \"difference\" : \"%s\", \"product\" : \"%s\", \"quotient\" : \"%s\"}\n";
printf($formatString, $sum, $difference, $product, $quotient);
?>
手順5. 動作確認
変換処理を実装したら、その動作確認を行う。先の図5で示したとおり「10」と「3」を入力して、その動作を検証する。
$ cd /path/to/Arithmetic
$ make input1=`printf "10" | base64` input2=`printf "3" | base64`
{"sum" : "MTM=", "difference" : "Nw==", "product" : "MzA=", "quotient" : "My4zMzMzMzMzMzMzMzMz"}
$ printf "MTM=" | base64 --decode
13
$ printf "Nw==" | base64 --decode
7
$ printf "MzA=" | base64 --decode
30
$ printf "My4zMzMzMzMzMzMzMzMz" | base64 --decode
3.3333333333333
手順6. 説明文の用意
「make help」で表示されるメトリクスプラグインの説明文を用意する。説明文を以下のように記述し、help.txtとして保存しておく。
#
# Arithmetic - Metrics for SynapseScript
#
# Created by M.Miyazaki [2013.02.19]
#
### Description
Do arithmetic operations.
Addition, subtraction, multiplication, division.
### Inputs
input1 : A number.
input2 : A number.
### Outputs
sum : Result of addition.
difference : Result of subtraction.
product : Result of multiplication.
quotient : Result of division.
### Examples
Try this example...
$ make input1=`printf "10" | base64` input2=`printf "3" | base64`
> {"sum" : "MTM=", "difference" : "Nw==", "product" : "MzA=", "quotient" : "My4zMzMzMzMzMzMzMzMz"}
$ printf "MTM=" | base64 --decode
> 13
$ printf "Nw==" | base64 --decode
> 7
$ printf "MzA=" | base64 --decode
> 30
$ printf "My4zMzMzMzMzMzMzMzMz" | base64 --decode
> 3.3333333333333
Thank you for trying SynapseScript! :-)
手順7. 完成
以上の手順により、メトリクスプラグインを開発することができた。その成果物は、こちら(Arithmetic.zip)のようになる。