著者アーカイブ 杉浦

著者:杉浦

任意の本の色合いからカラーチャートを得るColor of Book

Color of Book – 雑誌の色からhtml,cssで利用できるカラーチャートの紹介
 Color of Bookは任意の本の色合いからカラーチャートを得るサービスです。Color of BookではAmazonに存在する本の表紙画像から画像を取得し、その画像中で多く使われている色、特徴的に使われている色を見つけ、それを図示してくれます。本の指定は自由検索、ファッション誌、スポーツ誌のジャンル選択の三種類です。0から作るのが面倒な時、ほげほげの本みたいな雰囲気の色を作りたい時などに特に利用できます。盗作にならない程度に使いましょう。
 このサイトはhttp://colorchart.jp/color/[ISBN-10]のアドレスでamazonで表示される任意の本の表紙を参照することが出来ます。ISBN-10はamazonの書籍商品ページのアドレスのdp/以下に表示されています。これを利用して検索機能のより充実したamazonページを経由してアクセスできるようにすればなお便利です。

著者:杉浦

GETメソッドとブックマークレット

 HTTPはHyperText Transfer Protocolの略であり、HTMLなどのwebコンテンツを送受信する際によく使われています。GETメソッドはHTTPプロトコルの通信方式の一つです。GETメソッドはURLの末尾にパラメータを付加して通信を行います。URLはブラウザの履歴、サーバやファイアウォールのアクセスログなどユーザが意図しない内に様々な場所に記録されます。このためURLを得ることでその通信時のパラメータを得ることのできるGET方式で第三者に渡されるべきでない情報を扱うことは厳禁とされています。
 GET方式は通信内容を把握しやすく、改ざんしやすい方式です。この扱いやすさのため検索エンジン等の通信時の情報が第三者に渡されてもかまわない様な通信ではGET方式がよく使われます。GET方式の様な通信はURLをしかるべき形に加工してそのURLに移動するだけで任意の通信が行えます。実際、下の様なコードで手軽にwebサービスを利用できます。リンクは直下のソースコードを一行にしただけのブックマークレットです。
選択されているテキストを英語から日本語へ翻訳するgoogle翻訳

javascript: (function () {
	open('http://translate.google.com/translate_t?hl=ja&sl=en&tl=ja&q=' + encodeURIComponent(window.getSelection()));
})()

選択されているテキストの類語をWeblio辞書 類語辞典で検索

javascript: (function () {
	open('https://thesaurus.weblio.jp/content/' + encodeURIComponent(window.getSelection()));
})()

選択されているテキストの正規表現をREGEXPERで表示

javascript:(function(){
        open('https://regexper.com/#'+encodeURIComponent(window.getSelection()));
})()
著者:杉浦

安全で整ったコードを作るためプログラムlint

 lintとはソースコードを厳密に詳細にチェックするプログラムの総称です。総称とある通り、多数の言語でlintは作成されています。
 規模や目的の複雑さにもよりますがプログラムを完全に想定した通りに動かすことは容易ではありません。また、想定外の問題が起きることも多々あります。lintはプログラムが動作不能になるような致命的な文法エラーのみならず様々なものを発見する目的で使用します。例えば、間違いを犯しやすい記述であるアンチパターン、インデントの乱れのようなコードスタイルのぶれなどです。lintはソースコードをコピペするだけで実行されるwebページの手軽なものから、様々な設定を行った上で複数フォルダ間を総じて検査するCLIのがっつりしたものまでさまざまな規模のものがあります。
 手軽なjavascriptのlintの一つとしてjshintというものがあります。このページはコピペだけでjavascriptの厳密なチェックを行ってくれます。
 以前記述した10行程度の簡単なコードをjshintにかけてみました。結果は下の図の通りです。

 セミコロンが抜けているという警告、未定義の変数が存在しているという報告がされました。前者は限られた状況、例えばブックマークレットや一行記述にコードを変形した際に、プログラムの挙動が変化したり、実行不能になったりする問題が起きます。今回のケースに限り後者は大きな問題です。この記述においてhoge_strはグローバル変数として扱われ名前領域の汚染など他の記述に影響を与えてバグの原因になりえます。
 非常に多くの場面で使われているオープンソースの一つであるjQuery中の一つファイルをjshintにかけた結果が下の図です。
 
 全体で130行程度のコードですが、完璧に記述されています。変数defineが未定義とされていますが、他のファイルとの連携のために記述されているもので、このファイルの処理中には一切登場しません。余談ですがこのファイルはjQueryのcoreフォルダ中で最も長いファイルです。上手く作られていますね。

著者:杉浦

ホワイトテストと網羅率

 テストはプログラムの構成要素を参考にするもの、参考にしないもので二種類に分けられます。前者がホワイトテスト、後者がブラックテストとされます。ホワイトテストは設計の通りにプログラムが動作するかを確かめます。ホワイトテストによるテストではテスト内容を条件分岐の網羅などソースコードを元に定められます。ホワイトテストで考えられるテストは、ソースコードの全ての部分を実行する、ソースコードの全ての部分を様々な状態で実行する、ソースコードの全ての部分をあり得る全ての状態で実行する、といった様なテストです。
 ホワイトテストにはテスト達が所定の網羅条件をどれだけ達成しているかを表すカバレッジ(網羅率)という単位が定められています。hogehoge coverage xx%やCx xx%の様に表されることが多いです。

命令網羅 (statement coverage) (C0) 実行可能な命令の網羅率です。条件分岐の仕方に関わらずコード全体のうちどれだけが実行されたかを表します。
分岐網羅 (branch coverage) (C1) 実行可能な分岐の網羅率です。全体のうちどれだけの分岐を通ったかを表します。
条件網羅 (condition coverage) (C2) 実行可能な条件の網羅率です。全体のうちどれだけの条件を通ったかを表します。

真にプログラム上でありうる状態を網羅するためには条件網羅であっても力不足ですが、現実の時間は有限です。組み合わせ爆発にあるように、真に網羅を行うテストは実行時間が現実的でありません。後述しますが、網羅を目標にするテストのみではバグを見逃すことが多々あります。
 次のコードを例に命令網羅、分岐網羅、条件網羅それぞれを説明します。

function (a,b,c){
	if((a == 1 && b == 2) || c==3){
		//ifの中の処理。分岐なし
	}
	return;
}

このコードで入力引数がa=0,b=0,c=3のテストのみを実行した場合、C0:100%、C1:50%、C2:33%となります。まずC0:100%について説明します。これは実行可能な命令の網羅率です。引数がa=0,b=0,c=3ならばifの中に入りコード全体の命令を実行したことになり網羅率100%となります。次いでC1:50%について説明します。これは実行可能な分岐の網羅率です。このコードはifの中に入る入らないで2通りの実行ルートがあります。引数がa=0,b=0,c=3のテストのみを実行した場合、片方のルートのみを通ったということであり網羅率50%です。最後にC2:33%です。これは実行可能な条件の網羅率です。このコードにおいて実行可能な条件の組み合わせは(a == 1 && b == 2)=true,(a == 1 && b == 2)=falseかつ(c==3)=true,(a == 1 && b == 2)=falseかつ(c==3)=falseの3種類です。(a == 1 && b == 2)=trueの場合、二つ目の条件c==3の結果を評価せずとも条件の真偽値が定まるため二つ目の条件を評価しない言語が大多数です。そのためカバレッジでも二つ目の条件を評価しません。1/3を網羅したためC2:33%です。
 カバレッジはテストケースを考えるのに有用な基準ですが先に述べた通り100%を追求することは割に合わないことが多いです。実際のケースは上手く記述しようとも巨大で複雑になります。そのような場合、完全に網羅を行い、現実的な実行時間に収まるテスト達を考えることは困難です。加えて、カバレッジの追求のみでは実行パスに関わらないエラー要素、例えばa=b/cという処理におけるc=0の場合の様なバグが漏れやすいです。あくまで経験ですが高級言語の様な通常の記述において暗黙的な処理を多分に含む言語ほど命令、条件の網羅によるテストから漏れるバグが増えます。多方面からテストを行うことによって効率よくソフトウェアの品質を検証できます。

著者:杉浦

覚えておくべき変数の少ないソースコード

 この記事の話はリーダブルコード9章のあたりにより詳しく書いてあります。
 人間が一度に覚えて置ける項目の数の話は色々ありますが、それらの話のうちに大量の物事を詳細に覚えていられると述べるものは滅多にありません。覚えておくべき変数の少ないコードは人間が変数に格納されるであろう値を覚えながら読むことのできる良いコードです。そのようなコードは保守性が高く、バグが起こりにくいです。
 覚えておくべき変数を少なくするためには、そもそも変数を増やさないことが最良です。もしあるソースコード中に出現する変数が3つのみであれば、そのソースコードがどれだけ長大であっても、記憶しておくべき変数は3つより多くなりません。よく消える変数は一時的な値の置き場となっている変数、アルゴリズムの制御を担っている変数です。どちらもとりあえず書いて動かしてみる、という手法を行ったコードによく現れ、見直しによるコードの整理によって除去されます。次のコードの場合、bは用いず、aにまとめられるというになります。

var a = 'hogehoge';
/* aを用いるがaの値を変更しない処理 */
var b = 'hogehoge';
/* bを用いた処理 */

 変数が参照される範囲を小さくするという次善策もあります。変数には参照できる範囲、スコープが定められています。このスコープを少ない行数の範囲に留めることで、一度に覚えておくべき変数の数が少ないコードを実現します。言語にもよりますがスコープはおおよそ変数の宣言場所から、宣言を行った塊であるモジュール、クラス、関数などが終わるまでと定められます。宣言時の塊の最小単位の終わりがスコープの終わりとなることを基本とする言語が多いです。このスコープが小さい変数ばかりであれば、覚えておくべき変数が常に少ないコードの実現に近づきます。
 小さいスコープを実現するためには少なくとも二つの方針があります。
 一つは変数の宣言を変数を使用する直前にすることです。ある変数が使用されるはるか前に宣言されていた場合、使われない変数に頭を取られたり、使用された場所でこれ以前この変数はどのような操作をされたのか考えることになったりします。次のコードは塊の最初に変数a,b,cを宣言しており、全ての変数を最後まで記憶する必要があります。

var a,b,c;
/* aのみを用いた処理 */
/* bのみを用いた処理 */
/* cのみを用いた処理 */

一方で使用直前に宣言した場合、次の様になります。

var a;
/* aのみを用いた処理 */
var b;
/* bのみを用いた処理 */
var c;
/* cのみを用いた処理 */

このコードは変数b,cを記憶する時間が全ての変数を最初に宣言するコードより短くなっています。
 もう一つは小さい塊を多数用意し、処理を細分化し、各々その中で変数を宣言することです。この小さい塊を多数用意する手法には問題の細分化による単純化、容易な単体テスト、抽出された汎用処理の再利用、などといった利点もあります。関数やメソッドの様な多用される塊は余裕をもって一画面に収まる様にされます。一画面に収まる程度ならば処理は複雑になりにくく、一度に使用される変数も少ないです。この手法においてソースコード全体で使用される変数の数は十分多いですが、コードを読む際には塊単位で読めばよく、一度に覚えておくべき変数は少なくなりやすいです。次のコードは関数hoge_aを読む時は変数aのみを記憶すればよく、b、cも同様です。

function hoge_a(){
	var a;
	/* aのみを用いた処理 */
}
function hoge_b(){
	var b;
	/* bのみを用いた処理 */
}
function hoge_c(){
	var c;
	/* cのみを用いた処理 */
}
著者:杉浦

画像リサイズwebアプリbulkresizephotosの紹介

bulkresizephotosは複数の画像のサイズをまとめて変更するwebアプリです。
 このwebアプリは手軽という点で優秀です。複数の画像をあっという間にリサイズしてくれます。ページを開いて画像をまとめてDrag & Dropして操作準備完了です。
このアプリが無料でできる動作はScale、LongestSide、Width、Height、ExactSize。それとAddWatermarkのオプションです。
 Scaleは画像を一律の割合で拡大、縮小します。下図のExamplesにある様に、各動作はそれが画像をどのようにリサイズするかを教えてくれます。

 Width、Height、ExactSizeは幅を一定、高さを一定、幅と高さを一定、とリサイズとExmaplesを見ればすぐにわかります。LongestSideのExamplesは少々不親切です。LongestSideは長辺(Longest)の側(Side)の長さの指定です。600×400の画像と100×200の画像を指定1200でLongestSideを実行した場合、それぞれ1200×800、600×1200のサイズの画像になります。
 AddWatermarkは透かしの追加のことです。見本マークや紙幣の透かしの様に、AddWatermarkで指定した画像が他の画像全てに合成されます。

著者:杉浦

電話番号の慣例と仕様の橋渡しをする正規表現

 電話番号は国内の固定電話番号は10ケタ、携帯電話の電話番号は11ケタと定められています。しかしながら表記は慣例というのみで明確な定義がありません。***-****-****や***-***-****や(****)**-****などはよく見ます。これらや区切りなしに対応していれば大体カバーできますが、やっかいなのが企業等の広告用電話番号です。お客さんに覚えてもらうために彼らは語呂合わせなどで電話番号を自由に区切って表記します。こういった番号が対象に含まれる電話番号認識が必要となった場合、一つ一つのケースに対応はとてもしてられません。慣例で表記される()-を無視して仕様中にある数の数を数える正規表現で電話番号を認識しましょう。?によるあってもなくてもいい、が有効です。

雑なパターン:(?:\d[\(\)-]?){10,11}

いくらか丁寧なパターン:\((?:\d\)?-?\(?){10,11}

著者:杉浦

読むのが早いソースコード

 ソースコードは早く理解されるコードであることが要求されます。早く理解されるためには、書かれている文字が何なのか読み取られるという方法があります。同じ動作を関数化することはよく使われる手法です。

function natcmp_name($a, $b) {
	if (empty($a['nickname']) || $a['nickname'] == "") {
		$a['nickname'] = $a['fullname'];
	}
	if (empty($b['nickname']) || $b['nickname'] == "") {
		$b['nickname'] = $b['fullname'];
	}
}

 これは連想配列aと連想配列bを比較する関数です。比較の方法はニックネームの自然な辞書順の比較、もしニックネームがなければ代わりにフルネームを使う、です。この関数はabならば>0を返します。自然な辞書順というのは主に数字に関連した部分です。単純な辞書順では一文字ずつ文字を読み取り、違いが出た時点で順序を決定します。この単純な辞書順において’1abc’という文字列は’10abc’という文字列よりも後に並びます。これは2文字目のaと0の比較で0の方が辞書順で前に来るのが適当であるためです。自然な辞書順において’1abc’という文字列は’10abc’という文字列よりも後に並びます。
 この関数を用いてある3人の名前の並び順を決定する。コードを書くと次の様になります。

function natcmp_name($a, $b) {
	if (empty($a['nickname']) || $a['nickname'] == "") {
		$a['nickname'] = $a['fullname'];
	}
	if (empty($b['nickname']) || $b['nickname'] == "") {
		$b['nickname'] = $b['fullname'];
	}
	strnatcmp($a["nickname"], $b["nickname"]);
}
natcmp_name($person[1],$parson[2]);
natcmp_name($person[2],$parson[3]);
natcmp_name($person[3],$parson[1]);

 3回の比較が12行程度で記述できました。これを関数抜きで記述した場合、次のようになります

if (empty($person[1]['nickname']) || $person[1]['nickname'] == "") {
	$person[1]['nickname'] = $person[1]['fullname'];
}
if (empty($person[2]['nickname']) || $person[2]['nickname'] == "") {
	$person[2]['nickname'] = $person[2]['fullname'];
}
strnatcmp($person[1]["nickname"], $person[2]["nickname"]);
if (empty($person[2]['nickname']) || $person[2]['nickname'] == "") {
	$person[2]['nickname'] = $person[2]['fullname'];
}
if (empty($person[3]['nickname']) || $person[3]['nickname'] == "") {
	$person[3]['nickname'] = $person[3]['fullname'];
}
strnatcmp($person[2]["nickname"], $person[3]["nickname"]);
if (empty($person[3]['nickname']) || $person[3]['nickname'] == "") {
	$person[3]['nickname'] = $person[3]['fullname'];
}
if (empty($person[1]['nickname']) || $person[1]['nickname'] == "") {
	$person[1]['nickname'] = $person[1]['fullname'];
}
strnatcmp($person[3]["nickname"], $person[1]["nickname"]);

 21行であり、比較回数が増えればもっともっと増えます。これに目を通すのは前の例より時間がかかります。さらに置換ミスやタイプミスによる想定外の動作に気づきにくいという問題もあります。
 もっとも、一番読むのが早いのは何も書かれていないコードです。上に並べたコードは比較をしましたが比較から何も返ってきません、データを参照して、操作しているだけです。最後のコードに至ってはデータを上書きで壊すバグの元ですらあります。再利用の可能性のある場合でもコメントアウト、再利用の可能性のない場合は完全に消去。読む必要のある部分は0行になります。

著者:杉浦

正規表現の(?:)

 (?:)は(?:)で括られたグループは後方参照されないという記号です。後方参照は便利ですが、()もそれ以上に便利で多用しがちです。()が増えるとどこに何が格納されるかわかりにくくなりとても面倒です。(?:)ですっきりする例を挙げます。

 <([a-z])(?:(\s[^>]+)?)>(.*)<\/\1>

 HTMLやXMLの様なタグに使えそうな正規表現です。使えそうというのは、この表現は記事を書いている時の思い付きであり、私自身使ってないからです。.*はバグの温床です。これを(?:)抜きで状態遷移図っぽく可視化すると
 
 (?:)を使って可視化すると

 となります。前者のgroup2はいらない感じがしますが、後者では見事に消えています。

著者:杉浦

導入の簡単なwebページテストツール、Selenium IDEの紹介

 Selenium IDEは使うまでの導入が非常に楽なwebページテストツールです。多量のテストコードを書くのは手間ですし、Chrome、Firefox限定ですが、アドオンを入れるだけ、自分の操作を記録してコードに起こしてくれると扱いが簡単です。この記事はfirefox版でのインストールと操作の記録、再生の操作説明になります。
 アドオンというだけでインストールはSelenium IDE – Firefox 向けアドオンのページに飛んで”firefoxへ追加”からアドオン追加をするだけです。追加が完了した場合、右上のアイコンが現れます。

 アイコンを押したら下図の画面が出ます。赤丸ボタンで操作を記録開始します。

 記録停止は同じ場所に現れる赤い四角ボタンです。下図は、シーポイントラボのホームページを開いて、chrome開発者ツ…という記事を開いて、画面下へスクロールして、本文をクリックした、という操作を記録した場合になります。記録の保存、読込もできます。

 操作はGUI上から記録抜きに記述できます。操作コードには任意のjavascriptコードを実行というものもあり、ブックマークレットの応用でそれなりに拡張できます。困ったことにSeleniumIDEはfirefoxがfirefox quantumになったあたりで一度サポートが途切れて生まれ変わってます。検索して出てくる情報が古いとあてにならないことが多々あります。