ブログ移行します

GitHub-pages+jekyll+Octopressによるmarkdownなブログシステムがステキすぎるので移行します。

http://kozy4324.github.com/

[JS][node]ヒアドキュメント的に文字列ブロックを書く方法

小ネタです。とあるnodeモジュールのgithub見てて「なるほど」と思ったのでポスト。V8、つまりnode環境であれば以下方法でヒアドキュメントみたいなことが可能なんですね。

console.log(function(){/*
aaa
bbb
ccc
*/}.toString().split(/\n/).slice(1, -1).join("\n"));

元ネタはこんな感じでUsageの出力に利用してますた。ECMAの仕様的にはFunction.prototype.toStringは定義されてないので出力結果はエンジンの実装依存ってことになりますがV8はOKと。まぁ僕の場合、nodeプログラムはほとんどCoffeeScriptで書いちゃうわけですけどね(ヒアドキュメントで変数埋め込みが使えるから)。

[書評]テスト駆動JavaScript

各所で良書だと評判の「テスト駆動JavaScript」を途中まで読みまして、自分もこれは良書だと思ったので書評的にブログエントリーを書いてみます。

table of contents

  1. 章立て
  2. この本を読むべき人
  3. オススメな読み方
  4. 所感
  5. まとめ

1.章立て

  • 第1部 テスト駆動開発
    • 第 1章 自動テスト
    • 第 2章 テスト駆動開発プロセス
    • 第 3章 現役で使われているツール
    • 第 4章 学ぶためのテスト
  • 第2部 プログラマのためのJavaScript
    • 第 5章 関数
    • 第 6章 関数とクロージャの応用
    • 第 7章 オブジェクトとプロトタイプの継承
    • 第 8章 ECMAScript第5版
    • 第 9章 控えめなJavaScript
    • 第10章 機能検出
  • 第3部 JavaScriptテスト駆動開発の実際
    • 第11章 Observerパターン
    • 第12章 ブラウザ間の違いの吸収:Ajax
    • 第13章 AjaxとCometによるデータのストリーミング
    • 第14章 Node.jsによるサーバーサイドJavaScript
    • 第15章 TDDとDOM操作:チャットクライアント
  • 第4部 テストのパターン
    • 第16章 モックとスタブ
    • 第17章 優れた単体テストを書く

2.この本を読むべき人

ターゲットとなる人は各章ごとに分かれると思いました。

第1部

「導入」です。読みべき人は以下。

  • 「TDDなにそれ?おいしいの?」な人
  • 「JSでTDD?Javaならやったことあるけど...」な人
  • TDDに懐疑的な人

持論としてTDDは「テスト手法」ではなく「設計と開発のためのプラクティス」と考えています。第1部ではそれに対する理解の足がかりが得られ、TDDの利点やJSでのTDDを始めるにあたっての必要な情報が解説されています。この第1部を読んで琴線に触れない人はそのままこの本を閉じて本棚にしまってください。

第2部

言語的な観点でJSと他言語の異なる点について解説しています。この章はTDD関係ありません。JSについて深い知識を有している人は読み飛ばしてOK。以下に当てはまる人は読んでおくといいと思います。

  • 「JSの関数はファーストクラスオブジェクト」の意味がよく分からない
  • 「実行コンテキスト」「スコープ」がよく分からない
  • 「クロージャとその利点」「即時実行関数の使い所」がよく分からない
  • 「プロトタイプ継承」がよく分からない
  • 「ECMAScript5」って言葉だけ知っているが詳細は知らない
  • 「UA文字列判定よりもよりよい機能検出(feature detection)」について知りたい

第3部

様々なモジュールの実装についてTDDでどのように行うかを解説していきます。ここからがこの本のメインコンテンツです。

  • 「TDDによるJS実装の詳細」を学びたい
  • 「イベントドリブンなJSでのTDDが分からない」という人
  • 「Hostオブジェクトが絡むとTDDどうやるの?」という人
  • 「Node.jsでのTDDプラクティスってどうなの?」な人

第1部を読んでTDDに興味が出た、詳細が知りたい、という人が理解を深めるためにこの章を熟読するべきです。AjaxやDOMといったクロスブラウザな部分をTDDで開発しながらうまく抽象化する手法、また通常のブラウザ上ではないサーバーサイド環境でNode.jsを取り上げておりTDDでのモジュール開発など、幅広く取り扱っているのがTDDプラクティスに留まらず大変参考になります。

第4部

よりよいTDDを行うためのプラクティスについて言及しています。

  1. モックとスタブについての考察
  2. テストの品質を上げるためのガイドライン

「TDD実践をもう始めた、そこからさらによいTDDを書きたい」という人が読むべき章です。ぶっちゃけ僕はまだちゃんとここまで読めてません。

3.オススメな読み方

各章の最後にある「まとめ」がよくまとまっているので、まずは各章の導入部分とまとめだけを読めば良いです。この方法であれば30分ぐらいでざっくり全容が把握できます。その後、第3部以降はまとめを読んで気になる章から読んでいけばよいかと思います。

またTDDに興味沸かないという人でもJSの知識として第2部は読んでおくとよいです。

4.所感

TDDは「テスト手法」ではなく「設計と開発のためのプラクティス」という認識が深まりました。うまく書かれたユニットテストはJSで直面する問題(AjaxやDOMといったクロスブラウザな部分の設計)に対してのよい設計を導いてくれると感じました(まだ実践できてないが)。

また外部から見たオブジェクトの仕様(IN/OUT、状態遷移、振る舞い)を表現する手法としてユニットテストは有効である。本書でも一貫してテストコードファーストでの解説がなされておりそれが実感できます。

ぶっちゃけ「JSのTDDはこうすればよい!」という銀の弾丸的なTDD方法論が分かったわけではありません。それはおそらく書くプロダクトコードでケースバイケース。ただイベントドリブンなJSにおいてどういった設計をしながらTDDで開発するのが良いか、という指針は確実に本書を読む前より理解出来たと思います。

5.まとめ

構成のまとまり具合と網羅しているJS情報が秀逸。良書認定! JSでTDDをしたい人は必読 。そうじゃなくても JSデベロッパーは第2部必読 です。

[CoffeeScript] 分割代入(destructuring assignment)便利です

CoffeeScriptではJavaScript1.7の機能がいくつか実装されてます。その中でのmyブームが分割代入(destructuring assignment)で、すごく便利なので本エントリーで紹介してみます。

分割代入って何?

MDNのドキュメントを見てもらうのがいいです。以上。

CoffeeScriptのコードで書いてみる

基本は「配列形式の分割代入」と「オブジェクト形式の分割代入」があります。それらを組み合わせた複雑な分割代入も可能です。まずは単純な配列形式の分割代入から。

ary = [1, 2, 3]
[a, b, c] = ary
console.log a # 1
console.log b # 2
console.log c # 3

続いてオブジェクト形式の分割代入。

obj = {x: 10, y: 20}
{x:objX, y:objY} = obj
console.log objX # 10
console.log objY # 20

変数名がプロパティ名と同じでよければもっと簡潔な書き方が可能です。

{x, y} = obj
console.log x # 10
console.log y # 20

配列形式のパターンマッチ

が可能です(Scalaみたいな高度なものじゃない)。これはCoffeeScriptだけの実装なのかな?例えば最初の要素と2番目以降の要素を分割する場合。

[a, b...] = [1..5]
console.log a # 1
console.log b # [2, 3, 4, 5]

最初と最後、それ以外を分割する場合。

[a, b..., c] = [1..5]
console.log a # 1
console.log b # [2, 3, 4]
console.log c # 5

想像つくかもだけど、以下あいまいなパターンはもちろんコンパイルエラーです。

[a, b..., c, d..., e] = [1..10]
# コンパイルエラー ⇒ multiple splats are disallowed in an assignment: d...

分割代入の利点

MDNのドキュメントにも書いてありますが「一つの文によって全体の構造を読み込むことができるという点」というのが大きいと思います。これは言い換えると「1行でそのロジックで処理するデータのデータ構造を表現できる」ということ。JSONのレスポンスデータを処理するコードっていうのはよくあるシチュエーションだと思いますが、ちょっと昔のコード見て「これってどういったデータ構造を処理するロジックなんだっけ?」って感じることが自分の書いたコードですらよくあります。ロジックの意図をより短いコードで表現できるこういった機能は利用するほかないです。

前置きが長くなりましたが、実際にコードを書いてみます。例えばTwitterSearchAPIをJSONPで取得してレスポンスで何か処理するコードを書くとすると、

$.ajax
    url: "http://search.twitter.com/search.json"
    data:
	q: "バルス"
    dataType: "jsonp"
    success: (data) ->
        {page, results} = data
        # pageとresultsを処理するロジックが続く...

みたいな。TwitterAPIのレスポンスが以外とシンプルだったのであんまり伝わらないかもですが、レスポンスが複雑なデータ構造の場合はこの恩恵が受けれるはずです、きっと。

まとめ

CoffeeScriptでの分割代入(destructuring assiginment)について簡単ですがまとめてみました。利用することでロジックの記述が簡潔になるシチュエーションもいくつかありそうです。CoffeeScriptでのプログラミングテクニックとしてぜひ押さえておきたい機能かと!

今すぐ既存JavaScriptコードをCoffeeScriptに置き換えたほうがいいと思う理由を6つほど

最近お仕事で既存のJavaScriptプロダクトコードをCoffeeScriptで書き換えてるんですけど、まぁコードが簡潔になるわなるわで徐々にJavaScriptを受け付けない体になってる僕ですどうもこんにちは。

そんなわけで小難しい話なしで簡単に伝わりそうなCoffeeScript押しな理由を箇条書きで6つほどメモ。一人でもCoffeeScriptに興味持ってくれればコレ幸い。

前提の話

新しい言語を学ぶには学習コストが発生するわけなので、以下なケースのJavaScriptコードっていう文脈を背景に話します。

  • コード規模が数千行
  • コードのメンテナンス期間が長い(1年以上とか)
  • 複数人での大規模開発

こういった場合、少しでもロジックを簡潔に書けることがコードの可読性とメンテナンス性に大きく寄与していくので、これから説明するとこだけでの導入でも学習コストを上回る恩恵が受けれるんじゃないかなーと僕は思うのですよ。

CoffeeScript押しな理由

  • 簡潔な関数リテラル
  • thisのバインド
  • 文字列埋め込み+ヒアドキュメント
  • イテレーション
  • 配列内包
  • プロパティの存在チェック

簡潔な関数リテラル

JavaScriptで関数リテラルを書くとこうなります。

function cube(num) {
    return Math.pow(num, 3);
}

これをCoffeeScriptで書くとこうなります。

cube = (num) ->
    Math.pow num, 3

functionキーワードが必要なく「->」が関数リテラルを表現します。引数リストが必要なければ引数リストすら省略可能です。またreturnキーワードも必要なく、関数の最後に評価された式が戻り値となります。あとスコープを表すブレース(波括弧)は必要なく、スコープはインデントで表現されます(pythonライク)。また関数呼び出しの括弧も引数を与える場合は省略可能です。

ワンライナーで書けるのであればワンライナーにしてしまうのがCoffeeScriptっぽいと思うので、上記の関数の最終形はこうですね。

cube = (num) -> Math.pow num, 3

thisのバインド

ブラウザJSで誰しもが以下なコードを書いたことがあると思います。

var self = this;
document.getElementById("hoge").onclick = function (e) {
    self.clickHandler(e);
}

onclickを設定するスコープのthis参照のインスタンスメソッドをonclick関数内でコールしたいってやつですね。このselfって部分はthatやらいろんな流派をみたことがある。。これがCoffeeScriptだとシンタックスシュガーが用意されています。

document.getElementById("hoge").onclick = (e) => @clickHandler e

@はthisのシンタックスシュガーで「@clickHandler」は「this.clickHandler」と同じです。で上記例では関数リテラルを「->」ではなく「=>」と書いています。こうすると外側のthis参照と同じものが内側の@(this)でも参照できるというわけです。selfやらthatといったthis参照をローカル変数に格納する手間が削減され、これまで人それぞれな書き方だった部分も言語仕様として解決されるわけです。

文字列埋め込み+ヒアドキュメント

Rubyライクな変数展開が文字列リテラルで可能です。

sayName = (name) -> "my name is #{name}!"
sayName "kozy" # "my name is kozy!"

そしてヒアドキュメントで複数行の文字列リテラルが書けるのです。

htmlString = """
    <a href="#{href}">
    <img src="#{src}" />
    </a>
    """

ヒアドキュメントの場合はダブルクォーテーションのエスケープも気にする必要なし。簡単なHTMLのテンプレート処理であればCoffeeScriptだけで可能ですね。何かしらのテンプレートエンジンを利用するにしても元ネタとなるテンプレート文字列をプログラム内にplainなテキストとしてどうやって保持するかはJavaScriptの永遠の課題だと思ってました(文字列リテラルで保持?外部ファイルでAjax?textareaのinnerHTMをretrieve?)。それが解決できるだけでもCoffeeScriptは導入したほうがいいと思うよマジで。

イテレーション

オブジェクトのプロパティと値、および配列(Arrayライクなオブジェクト)のイテレーションがCoffeeScriptだと簡単に書けます。

console "#{key}: #{value}" for key, value of obj
console "#{key}: #{value}" for own key, value of obj
console "#{item}" for item in ary

オプジェクトプロパティのイテレーションは「of」を利用。プロトタイプチェーンを辿らずにイテレーションしたければ「for own」のほうを利用するとhasOwnPropertyが利用される形となります。

配列のイテレーションは「in」を利用します。配列のほうはコンパイルされた結果lengthプロパティをチェックする「for(var i=0, l=ary.length; i < l; i++)〜」なイテレーションに変換されるので、Arrayのメソッドは利用できないけどlengthは持っているArrayライクなargumentsやDOMNodes(getElementsByTagNameで取得できるやつ)なんかも上記の書き方で気にせずイテレーションできちゃいます。

またイテレーションの条件もwhenキーワードでワンライナーで書けたりするのも素敵です。たとえばnull以外の要素のみをイテレーションする場合。

console.log item for item in ary when item isnt null

配列内包

JavaScript1.7の機能がCoffeeScriptでは実現されており、イテレーションからの値の生成が簡単にできます。forイテレーションの結果はそのループの最後に評価された値の配列が返ります。論よりコード。

sqrt = (i*i for i in [1..5])
console.log sqrt # [1, 4, 9, 16, 25]

ECMAScript5で実装されたmap関数と同じようなことが出来ますね。僕はデータからHTML文字列の変換なんかでよくこんな書き方をしちゃいます。

ary = [
    {href: "a.html", text: "ページa"}
    {href: "b.html", text: "ページb"}
    {href: "c.html", text: "ページc"}
]
a_html = ("<a href="#{data.href}">#{data.text}</a>" for data in ary).join "¥n"
console.log a_html
###
<a href="a.html">ページa</a>
<a href="b.html">ページb</a>
<a href="c.html">ページc</a>
###

プロパティの存在チェック

jsonpなんかやってると複雑なデータ構造に対するプロパティの存在チェックしながらで以下なコードとかみたことある。

var status = json && json.data && json.data.status;

ショートサーキット評価って呼ばれるやつですね。CoffeeScriptとはこれをスマートに解決してくれます。

status = json?.data?.status

Rubyライクに「?」を付けることで存在するかどうかのチェックコードが入ります。途中のプロパティが存在していなければundefinedが返ります。また関数呼び出しに対して「?」をつけると内部的にはfunction型かどうかのチェックがしっかり入ります。

result = obj.callback?()

まとめ

どーでしょう?ちょっとしたことが多かったりしますが、こういったシンタックスシュガーにより手続き的でおまじない的なコードが減るので、本来やろうとしている処理だけが残りコードの可読性に寄与すると思います。みんなCoffeeScriptに興味持ってくれて、特にうちの会社からJavaScriptが無くならないかなーと日々夢みてますホント。

本当はパターンマッチと分割代入(destructuring assignment)なんかも入れたかったんだけど、それだけでエントリ1本書けそうな気がしたのでまた後で書く。。。

補足

実は関数リテラルのくだりはテストコード書く場合に一番恩恵を受けると思う。Jasmineなんかは無名関数のスコープで1スペック表現する仕様なんで、無名関数のネスト祭りなわけなんですよ。このページの「Nested Describes」の項に書いてあるサンプルコードがCoffeeScriptで書き換えるのをパっと想像しただけでどれだけ簡潔になるかって話ですよね。

最近のエントリー
カテゴリ
アーカイブ