Hatena::ブログ(Diary)

フリーフォーム フリークアウト Twitter

2013-04-20

MySQL Casual Talks vol.4

17:14 |

MySQL Casual Talks vol.4 : ATND

MySQL Casual Talks vol.4 を見てきました。

カジュアルだった

会の前半は初学者むけの内容が多く、その名の通りカジュアルでした。聴衆も半数以上は初参加だったようだし、時期的にもあらたにエンジニアとしてスタートを切る方が多いと思うので良かったと思います。最初の発表者の saisa6153 さんは実際に新卒の方だし、kenjiskywalker さんも sql に関しては初心者とのことでしたが、そういう人がどのように勉強したかを共有してくれるのは、これから勉強しようという人にはとても参考になるはずです。

まつけんさんの話は初心者向けというわけではないのですが、MySQL 5.6 をプロダクションで使ってハマったポイントをシェアという内容です。こういうハマったポイント共有系の情報は実際役に立つことがおおくて、自分もこのてのブログ記事などには何度も助けられてきました。こういう情報は自分もどんどんアウトプットせねばなと思いました。

もちろんコアな話も

後半はコアな話題。話の内容もそうなんですが、発表の仕方・盛り上げ方が手馴れていてさすがでした。

参加登録

今回のイベントは事前参加登録不要、当日先着順で入場というシステム。興味深い試みだし、結果的に成功でした。(当日時間通りに来た人はほとんど入場でき会場も満員)

いわゆる当日ドタキャン問題への対応は、どうしたって主催者に負担がかかるものになってしまうと思います。今回の方式は参加者側にもある程度のリスク (会場に入れないかもしれない) を負ってもらうことで、主催者側の負担も減るし当日来たくて来られるひとがイベントに参加できるという目的も達成できています。都内の無料技術系イベントの開催方式としてはありな着地点ではないかと思いました。

一方で会場からは遠方からの参加の場合確実に入れる保証がないのがつらいという意見もあがっていました。そのイベントがどの程度の "人気度" なのかが測れればよさそうなので、例えば atnd への事前参加登録は必須にしておいてその中から当日先着順に入場とすると、イベントに行こうと思っている人がどの程度いるのかあらかじめ分かっていいのかなと思ったりしました。

アイアンマン

全然関係ありませんが、今回の会場である日本オラクル最寄りの外苑前駅アイアンマン3 x オラクルの広告が出されていました。今回もスポンサーをするようですね。

f:id:cou929_la:20130420171437j:image

前作アイアンマン 2 でもオラクルがスポーンサーになり、ラリー・エリソンカメオ出演しているのは有名な話。ロバート・ダウニー Jr が「やあラリー」くらいの勢いで話しかけている面白いシーンです。

そんなアイアンマン 3 も今月末日本先行公開。非常に楽しみです。

HOME|マーベル|Marvel|

2013-01-21

Web API 設計のベストプラクティス集 "Web API Design - Crafting Interfaces that Developers Love"

| 22:59 |

f:id:cou929_la:20130120145130p:image

no title

Web API Design という本を読みました. Web API 設計のベストプラクティスがまとめられている, apigee という API のソリューションを提供している会社がだしているフリーの ebook です. コンパクトに 30 ページほどに読みやすくまとめられています.

以下要点のメモです.

開発者視点

  • API の目的はアプリケーション開発者 (API 利用者) が可能な限り成功すること. 開発者の視点で設計すること. 本書ではそのような API を実現する tips を紹介する.

Pragmatic REST

URL

  • 動詞ではなく名詞
    • リソースを名詞であらわす. Collection: `/dogs/`, Specific element: `/dogs/1234`
    • HTTP メソッドリソースの操作とする. POST は create, GET は read, PUT は update, DELETE は delete
  • 単数形よりも複数形をつかう
  • URL の階層を浅く保つ
    • リソースの関係を表したい場合. 例えばオーナー 5678 が飼っている犬をあらわす URL は `/owners/5678/dogs`
    • 目安として `/resource/identifier/resource` 以上に URL を深くすべきでない
    • URL は浅く保ち, 複雑さはクエリパラメーターに押しこむ

エラーハンドリング

例:

{
    "developerMessage": "開発者向けメッセージ",
    "userMessage": "ユーザ向けメッセージ. 必要に応じて",
    "errorCode": 1234,
    "moreInfo": "http://dev.example.com/errors/1234"
}

バージョニング

  • 必ずバージョンをつけること
  • v と整数のバージョン番号を URL のトップレベルにつける. e.g. `/v1/dogs`
    • バージョン番号にドット (マイナーバージョン) は不要. APIインタフェースであり実装ではない. マイナーバージョンは粒度が細かい.
  • バージョンは URL にいれるべきか, HTTP ヘッダにいれるべきか
    • ブラウザからの開発しやすさを考えて URL にバージョンをいれるべき
  • パラメータURL とヘッダどちらに入るかは次のルールにしたがう
    • API のレスポンスをハンドルするロジックが変わる場合, URL にいれる
    • そうでない場合 (例えば OAuth の情報) ヘッダに入れる

Partial response と Pagination

いずれも一部の必要なデータだけをクライアント側に返す戦略. Partial response は利用者が指定したフィールドだけを返す. Pagination は返す件数を制御する方法.

  • Partial response
    • `fields` パラメータにカンマ区切りで指定
    • e.g. `/dogs?fields=name,color,location`
  • Pagination

リソース操作ではない API のデザイン

  • 計算・翻訳・変換など, ドメインによってはリソース操作でない API も存在しうる
  • その場合名詞でなく動詞をつかう
    • e.g. `/convert?from=EUR&to=CNY&amount=100`
  • ドキュメントには特殊なケースだということを明記しておくこと

複数フォーマットのサポート

属性名

  • JavaScript の規約にあわせる
    • 先頭小文字のキャメルケース

例:

{"createdAt": 1320296464}

検索のための tips

  • 検索は複雑なクエリが想定されるので, Google にならって動詞URL にするのがよい
  • `/search?q=fluffy+fur`
  • 検索のスコープを絞る場合は search の前にスコープをつける
    • `/owners/5678/dogs?q=fluffy+fur`
  • 結果のフォーマットは拡張子ふうに指定
    • `/search.xml?q=fluffy+fur`

API リクエスト先をひとつの subdomain にまとめる

例外的な動作への tips

クライアントHTTP エラーコードをインターセプトする場合
  • たとえば FlashHTTP のエラーレスポンスを受け取ると, エンドユーザのアプリにエラーコードを表示する
  • これを避けるために `suppress_response_codes=true` というクエリパラメータを提供する
    • これが指定されていると HTTP レスポンスコードが常に 200 になるようにする
  • レスポンスボディは通常通りのエラーコードやメッセージを返す. クライアントアプリはこれを見てハンドリングする
限られた HTTP メソッドしかサポートしないクライアントへの対応
  • 例えば PUT, DELETE をサポートしないクライアントへの対応
  • `method` クエリパラメータで指定するようにする
    • `/dogs?method=post` (create), `/dogs` (read), `/dogs/1234?method=put&location=park` (update), `/dogs/1234?method=delete` (delete)

認証

Chatty APIs

  • Chatty API (おしゃべりな API, つまり情報が少なく何度も呼び出さないといけないもの) をいかに避けるか
  • まず RESTful に設計し, そのごショートカットを追加する
    • 複数の API 呼び出しを組み合わせないと実現できない使い方を, 一度の呼び出しで実現できる API を追加してあげる
    • 先にショートカットを作ってはいけない. まずは RESTful なデザインで, 必要に応じてショートカットを追加する
  • partial response にドット演算子を導入して, 別のリソースのフィールドを参照できるようにする
    • `/owners/5678?fields=name,dogs.name`

SDK

  • API がよく設計されドキュメントも整っていれば SDK は不要
  • 一方で API をつかうためにドメインの知識が必要な場合, SDK を提供するという手がある
  • API を改修するのではなく SDK を提供することで API をクリーンに保てるなどいくつかのメリットがある

API Facade Pattern

  • システムのフロント (API) とバックエンド (システム本体や DB など) のつなぎかた. Facade Pattern をつかう
  • フロントとバックエンドの間に抽象的なレイヤーを一枚はさむ
  • 設計のしかた
    1. まず理想的な API インタフェースを設計する
    2. stub を用意して上記のインタフェースを実装する
    3. facade と実際のシステムをつなぐ

参考

2012-12-29

Google JavaScript Style Guilde をリビジョン 2.64 にあわせて修正しました

| 11:09 |

Google JavaScript Style Guide 和訳 — Google JavaScript Style Guide 和訳

またもや一ヶ月くらい放置してしまったのですが, Google JavaScript Style Guilde がアップデートされていたので訳文もそれに追従しました

今回の変更は最近の js エンジンの最適化方法にあわせた修正がいくつかあったのが印象的でした

その他は説明の詳細化, typo の直しなど細々とした修正でした.

  • 定数の命名規約の説明の詳細化
  • 名前付けの規約に名前空間とファイル名が追加
  • `goog.scope` を使ったプロパティエイリアスについての規約を追加. closure を使わない場合はあまり関係がありません.
  • コメントについて. トップレベルコメントからコピーライトや作者情報を省くなど.
  • その他 closure, jsdoc まわりの説明の修正など

2012-12-17

ブラウザのバグを見つけたときにやること

22:26 |

f:id:cou929_la:20121217221036p:image

*1

  1. バグを見つける
  2. すでに報告されていないか調べる
  3. ブラウザの種類とバージョンの絞込み
    • 他のブラウザでは発生するか. 他のバージョンでも発生するか (stable を使っているなら beta や nightly でも見てみる等)
  4. テストケースの最小化
    • バグを再現させる最小のテストケースを作ります
    • 今回出会ったのは表示系のバグだったので, html / css を削りながら現象を再現させていき, 同じ現象が起こる最小の html を作りました
  5. バグの報告先とフォーマットの確認
  6. レポートを書く
  7. 報告する

主要ブラウザの報告ガイドラインと報告先

ブラウザのリリースチャンネル

異なるバージョンの共存はこちらが参考になります (Mac の場合)

MacをJavaScriptの開発環境にするメモ - os0x.blog

2012-12-11

twitter bootstrap のテストを読んだメモ

| 23:58 |

f:id:cou929_la:20121211235517p:image

Bootstrap

GitHub - twbs/bootstrap: The most popular HTML, CSS, and JavaScript framework for developing responsive, mobile first projects on the web.

twitter bootstrap のテストはどういう仕組みになっているんだろうと思い読んだときのメモです.

概要

Makefile が起点. テストそのものは qunit で書かれていてそれをがんばってコマンドラインから叩けるようにしている. node でローカルにサーバをたてて qunit のテストを実行する html を配信, それに対して phantomjs でリクエストを送る仕組み. テスト実行結果は phantomjs から dom を読んで判断している.

Makefile

test:
	jshint js/*.js --config js/.jshintrc
	jshint js/tests/unit/*.js --config js/.jshintrc
	node js/tests/server.js &
	phantomjs js/tests/phantom.js "http://localhost:3000/js/tests"
	kill -9 `cat js/tests/pid.txt`
	rm js/tests/pid.txt

lint

まずはじめに jshint で lint する. `js/.jshintrc` に設定が書いてある中身はこちら.

    {
        "validthis": true,
        "laxcomma" : true,
        "laxbreak" : true,
        "browser"  : true,
        "debug"    : true,
        "boss"     : true,
        "expr"     : true,
        "asi"      : true
    }

それぞれのオプションについて

  • validthis
  • laxcomma
    • 前置コンマでも警告を出さないようにする
  • laxbreak
    • 安全でない改行でも警告を出さない. どんなケースが該当するのかは種類が多いようなのでわからないが, コーディングスタイルによって改行位置は変わるのでいろいろと議論はあるようだ.
  • browser
  • debug
    • `debugger` 文が出てきても警告しない
  • boss
    • for 文の比較部など, 比較式が期待される部分で代入を行なっていても警告をださない. 確かにそういうループの書き方をすることもある.
  • expr
    • 代入や関数呼び出しが期待されている部分に式があっても警告しない.
  • asi
    • セミコロンが行末になくても警告を出さない. そういえばセミコロンをかたくなに付けない人たちの主張をちゃんと読んだことないし今度調べてみよう.

js/tests/server.js

ポート 3000 番で http サーバをたてて, プロジェクトホーム以下のファイルを静的に返すようにしている. またプロセス番号を `pid.txt` に落とす.

内容もこれだけ.

/*
 * Simple connect server for phantom.js
 * Adapted from Modernizr
 */
    
var connect = require('connect')
  , http = require('http')
  , fs   = require('fs')
  , app = connect()
      .use(connect.static(__dirname + '/../../'));

http.createServer(app).listen(3000);

fs.writeFileSync(__dirname + '/pid.txt', process.pid, 'utf-8')

js/tests/phantom.js

これがテストランナーにあたる.

  • 引数で渡された url へアクセスする
  • `waitFor()` はテストの実行完了を待つ関数. タイムアウトを設定できる.
  • waitFor の第一引数の無名関数がテスト完了をチェックしている. 単純に dom 中の innerText を見てテスト完了のメッセージが出ているかをチェックする.
  • waitFor の第二匹数の無名関数はテスト結果に応じて終了コードを設定してプロセスを抜ける. テスト結果は例のごとく dom から取得. テストが落ちていたら 1 で exit する.

テストがコケた場合終了ステータスが 1 になるので, make が以下のようなエラーメッセージを出してくれる & make 自体の終了コードも非 0 になる.

make: *** [test] Error 1

また, こんなかんじで `page.onConsoleMessage` でページのコンテキストで出された console.log のメッセージを phantomjs のコンテキストに持ってきている.

page.onConsoleMessage = function(msg) {
  console.log(msg)
};

テストを実行する (phantomjs に呼ばれる) index.html 側ではテストの進捗を console.log でも出すようにしている (後述). 通常 qunitdom 上にテストの進捗や結果を出すが, 今回は無理やりコマンドラインから実行している. そのためコマンドラインからテストの進捗・結果が見えないので, このように console.log をうまくページ -> phantomjs のコンテキストへルートしてあげている. コメントによるとこのへんの仕組みは modernizr のテストを参考にしているそう.

Modernizr/test at master ? Modernizr/Modernizr ? GitHub

js/tests/index.html

ここから先はふつうの qunit のテストと同じ. jquery, qunit.js などなど必要なパッケージを読み込んでから, `js/tests/unit/` 以下のテストを読み込んで走らせている.

`js/tests/unit/bootstrap-phantom.js` で `QUnit.begin` (いわゆる setup, teardown) などにログを残す関数を仕込んでいる. ここでテストの進捗・結果を console.log して, それをさきほどの phantomjs 内の onConsoleMessage が拾って表示させている.

// Logging setup for phantom integration
// adapted from Modernizr

QUnit.begin = function () {
  console.log("Starting test suite")
  console.log("================================================\n")
}

QUnit.moduleDone = function (opts) {
  if (opts.failed === 0) {
    console.log("\u2714 All tests passed in '" + opts.name + "' module")
  } else {
    console.log("\u2716 " + opts.failed + " tests failed in '" + opts.name + "' module")
  }
}

QUnit.done = function (opts) {
  console.log("\n================================================")
  console.log("Tests completed in " + opts.runtime + " milliseconds")
  console.log(opts.passed + " tests of " + opts.total + " passed, " + opts.failed + " failed.")
}

後片付け

node のサーバプロセスを kill し, pid ファイルを削除

テストを実行した結果

実際実行してみるとこんなかんじ.

$ make test
jshint js/*.js --config js/.jshintrc
jshint js/tests/unit/*.js --config js/.jshintrc
node js/tests/server.js &
phantomjs js/tests/phantom.js "http://localhost:3000/js/tests"
Starting test suite
================================================

✔ All tests passed in 'bootstrap-transition' module
✔ All tests passed in 'bootstrap-alerts' module
✔ All tests passed in 'bootstrap-buttons' module
✔ All tests passed in 'bootstrap-carousel' module
✔ All tests passed in 'bootstrap-collapse' module
✔ All tests passed in 'bootstrap-dropdowns' module
✔ All tests passed in 'bootstrap-modal' module
✔ All tests passed in 'bootstrap-scrollspy' module
✔ All tests passed in 'bootstrap-tabs' module
✔ All tests passed in 'bootstrap-tooltip' module
✔ All tests passed in 'bootstrap-popover' module
✔ All tests passed in 'bootstrap-typeahead' module

================================================
Tests completed in 2026 milliseconds
142 tests of 142 passed, 0 failed.
kill -9 `cat js/tests/pid.txt`
rm js/tests/pid.txt