はじめてのExpress.js

Introduce Express

1.expressとは
2.なぜ Node.js + express を使うか
3.Getting started
4.パッケージの追加
5.Express + MongoDB

 
Githubにまとめたものを、せっかくなのでblogの方に転記しました。 一部ブログ用に加筆修正しています。

1.expressとは

expressは、Node.jsの軽量WebアプリケーションフレームワークRubySinatraのようなシンプルなフレームワークです。
Node.jsのHTTPサーバ機能は、プロトコルの仕様にそったローレベルなものであるため、
WebApplicationを開発しようとした場合、HTTPリクエストの解析から行わなければなりません。
(Java ServletやRuby Webrickのようなイメージ)

そのため、WebApplicationFrameWorkが必要となります。

2.なぜ Node.js + express を使うか

Node.js + express で開発するメリットは何か

メリット

  • 開発言語をJavaScriptに統一できる
  • ノンブロッキングI/O

開発言語をJavaScriptに統一できる

WebアプリケーションはJavaScriptの開発が欠かせなくなっており、 Java + JavaScriptRuby + JavaScriptといったスキルセットが 当たり前に求められるようになってきました。Node.js + express で開発をするとフロントからバックエンドまで、すべて言語をJavaScriptで統一できます。

ノンブロッキングI/O

Node.jsはGoogle Chromのv8エンジンで処理を行っており、 JavaScriptのイベント・ループをベースに非同期処理を行っています。

  • DB問い合わせで同期処理待ちを行わない
  • WebSocketのコネクションで待機処理を行わない

このような特徴から、シングルスレッドでも沢山のリクエストをさばくことが出来ます。

3.Getting started

早速インストールからサーバの起動までやってみます。

1) Install

$ npm install -g express
$ which express

2) Generate

$ express helloWorld

expressコマンドを実行してnpm installで依存パッケージをインストールします。
expressによって生成されるモジュールは以下のようなものです。

$ cd helloWorld
$ npm install
$ tree -C  -I node_modules
 .
 ├── app.js
 ├── package.json
 ├── public
 │   ├── images
 │   ├── javascripts
 │   └── stylesheets
 │       └── style.css
 ├── routes
 │   ├── index.js
 │   └── user.js
 └── views
     ├── index.jade
     └── layout.jade

viewは名前の通りのビューを、routesはコントローラとモデルを定義していきます。 なお、モデルとコントローラを分けたい場合は、自分でmodelディレクトリを切って分けることも可能です。モデルを分けたら、routesのファイル内でrequireしてあげれば利用できます。

生成されたapp.jsが処理の中心になっています。
依存関係のモジュールや環境設定、ルーティングなどを定義します。

app.jsの内容

f:id:taise:20130627221214p:plain

3) Hello World

Nodeサーバー起動

$ node app

http://localhost:3000/にアクセスすると、indexページが表示される。
expressの処理の流れは以下の図のようになっています。

f:id:taise:20130627221805p:plain

せっかくなので、上の図の処理の流れを見ながら画面表示する内容を変えてみます。

トップページに、コントローラから渡された"Hello World"と表示するには routes/index.jsを以下のように変更します。

exports.index = function(req, res){
  res.render('index', { title: 'Express' });
};

    ↓

exports.index = function(req, res){
  res.render('index', { title: 'Hello Wold' });
};

Nodeサーバー起動

$ node app

http://localhost:3000/にアクセスすると、タイトルが変更されています。

4.パッケージの追加

さてここまできたら、せっかくなので簡単なユーザ登録アプリを作ってみます。
ユーザ登録をすると一覧表示されるようなものです。

こんな感じ。

f:id:taise:20130627222833p:plain

まずはデータの保存/参照機能を追加します。
今回はDBにMongoDBを使用します。
Node.jsにはMongoDBのODM(Object Document Mapper)のmongooseというライブラリがあります。

Node.jsは、npmとpackage.jsonを使ってパッケージ管理をしているので、以下のようにmongooseを追加します。

1) package.jsonにmongooseを追加する

{
  "name": "helloWorld",
    "version": "0.0.1",
    "private": true,
    "scripts": {
      "start": "node app.js"
    },
    "dependencies": {
      "express": "3.2.6",
      "jade": "*",
      "mongoose": ">= 1.0.0"
    }
}

2) npm install

$ npm install

3) requireして利用する

追加したパッケージを利用するには、利用するファイル内でrequireをします。

var db = require('mongoose')

5.Express + MongoDB

1) DBコネクト

mongooseを追加したので、MongoDBと連携させます。
まずは、routes/user.jsでDBコネクトします。

var db = require('mongoose');
db.connect('mongodb://localhost/helloWorld');

2) スキーマ定義

routes/user.jsにschemaを追記します。

var schema = new db.Schema({
  id    : { type: String }
 ,name  : { type: String }
 ,age   : { type: Number }
});

3) Model定義

スキーマで定義したオブジェクトをModelとして登録します。

var User = db.model('User', schema);

4) createリクエストの作成

Userデータを作成する画面を追加します。
まずはapp.jsにルーティングを追加します。 usersでpostされたら、routse/user.jsのcreateに渡します。

app.post('/users', user.create);

次にroutes/user.jsにcreate処理を書いていきます。 createは、mongooseのModel.createを使ってデータを保存します。

exports.create = function(req, res){
  User.create({
    id   : req.param('id')
   ,name : req.param('name')
   ,age  : req.param('age')
  }, function(err) {
    res.send('created')
  });
};

次に、画面を作成します。
既にあるviews/index.jadeをコピーして作ります。

$ cp views/index.jade views/user.jade

コピーしたら中身を以下のように書き換えます。

extends layout

block content
  h1 Add User
    form(action='/users', method='post')
      input(type='text', name="id", placeholder="id")
      br
      input(type='text', name="name", placeholder="name")
      br
      input(type='text', name="age", placeholder="age")
      br
      input(type='submit', value='登録')

画面が作成できたので、この画面へのルーティングを設定します。
最初からroutes/user.jsuser.listがあるので、まずはそこを利用します。

exports.list = function(req, res){
    res.render('users');
};

ここで、サーバを再起動してみます。変更の度に何度も再起動するのは手間なので、変更を自動で反映してくれるsupervisorというパッケージを利用すると便利です。

$ npm install -g supervisor

supervisorで再起動します。

$ supervisor app

登録が成功すると"created"と表示されます。
(データが保存されていることはMongoDBのコンソールで確認できます)

5) Userリストを表示する

作成したユーザデータを表示します。
routes/user.jsのlistを変更して、MongoDBからデータを取得します。

exports.list = function(req, res){
  User.find({}, function(err, users) {
      res.render('users', {
        users: users
    });
  })
};

次に、リスト表示する画面を作成します。
先ほど登録で使った画面を流用します。
views/user.jsに以下を追記してください。

  h1 User Listing
  p ユーザ数: #{users.length}
    table
      tr
        td id
        td name
        td age
  if(users.length > 0)
    each user in users
      tr
        td #{user.id}
        td #{user.name}
        td #{user.age}

あとは、ユーザ登録時にこの画面を表示するようにルーティングを変更します。 create処理をした後にリスト表示処理をさせるには、redirectします。

exports.create = function(req, res){
  User.create({
    id    : req.param('id')
   ,name  : req.param('name')
   ,age   : req.param('age')
  }, function(err) {
    res.redirect("/users")
  });
};

これでページにアクセスすると、ユーザ登録/一覧表示ができるようになっているはずです。

今回のご紹介は以上です。 expressはNode.jsのWebアプリケーションフレームワークデファクトになりつつあります。そのため、そのうちRubySinatraにおけるPadrinoのように、expressを拡張したフレームワークが出てくるじゃないかと期待しています。
そういった広がりが出てくると、もっとNode.jsを使う場が広がってきますね。 ただ、Node.jsがシングルスレッドなので、フルスタックのような「重いフレームワーク」はあまり向いていないと思うので、新しいNode wayの考え方にそったエコシステムの発展が楽しみですね。

jsCafeでBackboneJSとAngularJSについて話してきた

jsCafeという勉強会に参加してきた。
参加2回目だったけど、AngularJSとBackboneJSを比較するとどうか、という内容でLTさせてもらった。

BackboneJS (Model / Collection)

@lxyumaさんのスライドは、前回に引き続き、ちゃんと手を動かすポイントがあってよかった。
ModelがmongoDBの”_id”を”id”としてつかうのにidAttributeを使えばいいよとか、jQueryのようにメソッドチェインをかける.chain().value()がCollectionで使えるとか知らなかった。

// chain() + value() のメソッドチェイン
var a_person = people.chain()
  .filter(function(person) { return person.get('bloodType') == "A"; })
  .max(function(person){ return person.get("age"); })
  .value();

console.log(a_person.attributes);

資料も毎回内容ぎっしりですごい。

BackboneJS (View / Event)

@minty_operaさんのスライドはgithubにhtmlファイルが置いてあるのでgit cloneとかして見る感じ。
開発経験が全然ないとおっしゃっていたけども、講師をかって出たり、わからないといいつつも綺麗なスライドを作っていて、そうした努力がすごい。

jQuery (Selector / Event)

@_takahiro0113 さんのスライドは、jQueryってきいたことあるけど、何か良くわからないって人には分量やレベル感がとっても良いスライドだった。
チラっと実業務でjQueryとか書くともっと複雑なことをいろいろやるとおっしゃってたので、そのいろいろが気になった。
次回にでも聞いてみたい。

LT

で、LTさせてもらいました。
AngularJS or BackboneJS というテーマで、最近MV*フレームワークがたくさんあるけど、どれ使ったらいいのということで、人気の二つを比較したという内容になってます。

#AngularJS or BackboneJS

全体的に時間が押してて焦っていたのと、LT初めてだったので緊張してカミカミだったので、もっと慣れてきたい・・・。
一番ウケていたのはbombermine(AngularJSでできてる)で他のプレーヤーにやられた時だった。

このLTをきっかけに、BackboneJSの仕組みを整理して、よくある処理パターンの図を書いて理解を深められたのが良かった。

#よくある処理パターンの図

f:id:taise:20130609232554p:plain

スライドの23枚目にもあるけど、ViewがDOMとModelのイベントを監視してそこから処理が始まるという形を理解すると、BackboneJSの構造化の恩恵を受けられると思う。

D3.js入門(棒グラフをつくってみる)

D3.jsとは

D3.jsというJavaScripのライブラリをご存知でしょうか。

http://ja.d3js.info/ (日本語の公式サイト)

csvや配列などのデータをもとに、グラフを描画することができるライブラリです。
グラフなどは、公式サイトを見ていただければわかる通り、比較的簡単に自由度の高く、綺麗な図が描画可能です。  日本ではまだ認知度はあまり高くないですが、海外では既に多くの事例があり、GithubのYour Contributions(コミット回数が表示される図)などでも使われています。

データ・ドリブン

JavaScriptといえば、マウス操作などのイベントが中心となって処理が行われるため、イベント駆動言語などと言われたりしますが、D3という名前は”Data Driven Document”の略であり、データをもとにドキュメントや図を描画します。

データ・ビジュアライゼーション

こちらのGalleryに沢山の綺麗な図がのっていますが、これらは全てD3.jsによって作られたもので、様々なビジュアライズが可能であることがわかるかと思います。

https://github.com/mbostock/d3/wiki/Gallery

D3.js 入門

はじめに

では早速始めてみようということで、参考になるWebページを探してみますが、英語のドキュメントはたくさんあるものの、まだまだ日本語のドキュメントが少ないのが現状です。有志の方々が少しずつ翻訳していただいていますが、詳しく解説したものがまだ少なく感じます。 (APIを翻訳すると言って出来ておらず、すみません・・・)

ということで、最近気象庁が気象データのCSV配布を開始しましたので、降水量のデータを用いて一番イメージしやすい棒グラフの作成チュートリアルを書いていきたいと思います。

まずはhtmlの準備

ベースとなるhtmlを作成します。 D3.jsは"http://d3js.org/d3.v3.js"でホスティングされているため、わざわざダウンロードして使う必要はありません。もしminified版が使いたい場合は、こちらを指定してください。

<html>
  <head>
    <title>meteorology</title>
</head>
<body>
  <output id="graph"></output>

  <script src="http://d3js.org/d3.v3.js"></script>
  <script src="./js/precipitation.js"></script>
  </body>
</html>

CSVファイルの準備

では利用するCSVファイルを準備します。 気象庁の情報は、以下のリンクから自分の好きなように項目を選んで取得することができます。 出力項目、地域、期間などが自由に選べるため、かなり便利です。

http://www.data.jma.go.jp/gmd/risk/obsdl/index.php

今回は過去10年間の平均気温と降水量をダウンロードして使用しています。 (平均気温はまだ使いません。)

CSVファイルの読み込み

D3.jsにはファイルを読み込む機能とテキストをCSVにパースする関数があります。

d3.text(data, function(file) { /* ... */ });

このようにかくことで、XMLHttpRequestでファイルを取得し、関数で処理することができます。
CSVファイルのヘッダー行は今回使わないので、d3.csv.parseRows()で取得したCSVの配列を5行目まで削除しています。
即時関数の最後でグラフの作図処理を呼び出しています。

(function(){
 d3.text("data/tempAvg_precipitation.csv", function(csvFile) {
   var csvData = d3.csv.parseRows(csvFile);
   // delete header lines from csv 
   csvData.splice(0, 5)
   presipitation(csvData);  // グラフ作図関数
   });
})();

作図エリアの確保

では続いてグラフを作図するエリアを指定していきます。 グラフを書く場合、グラフの目盛りや単位を書いたりすると思います。
そのため、1000 * 400のグラフを作る場合、marginをとって目盛りを表示するスペースを確保しておきます。

// graph of precipitation / month
var presipitation = function(dataset) {
  // graph area
  var width = 1100,
       height = 500,
       margin = 50,
       w = width - (margin * 2),  //  400
       h = height - (margin * 2), // 1000
       barPadding = 2;           //棒グラフの間隔


  var svg = d3.select("#graph")
                      .append("svg")
                      .attr("class", "chart")
                      .attr("width", width)
                      .attr("height", height)
                      .append('g')
                      .attr('transform', 'translate(' + margin + ', ' + margin + ')');
                                                               
};

さて、ようやくd3がでてきました。 D3.jsにはCSSのようなセレクタがあります。使い方はjQueryに似ています。メソッドチェインを使ってどんどん処理をつないでいくところもjQueryに似ていますね。

今回の作図はSVGを使っています。 SVGは、XML形式でベクター画像の描画を行います。
SVGの使い方については、最近ドットインストールでSVG入門のレッスンが追加されていました。 これを見ておくと、D3.jsをより扱いやすくなると思います。
http://dotinstall.com/lessons/basic_svg

SVGは属性情報を追加することで色やサイズ、描画位置などを指定していきます。 translateは描画位置を移動させます。目盛り用に縦・横それぞれにのmarginを取っています。 また、marginは棒グラフに適用したいため、”g”(グループ)を追加しています。棒グラフの要素をg要素以下に作成すると、g要素で指定された属性がそれ以下の要素にも反映されます。

棒グラフを描画する

さて、いよいよグラフの描画を行います。
まずは棒グラフの棒の描画位置を決めていきます。 その後、実際の棒グラフの高さと幅を指定していきます。 SVGはHTMLと同じで左上が(0,0)になります。

作図エリアは"chart"クラスにありますので、セレクタを使います。
今回はselectAllで要素を取得しています。selectとselectAllは返すデータのタイプが単一要素か配列かという違いがあります。 SVG要素の配列をselectAllで宣言し、data()を使ってcsvデータの配列にバインディングしています。

そしてバインディングされた要素をenter()することでデータを使う準備がされます。
詳しく知りたい方はhttp://ja.d3js.node.ws/document/tutorial/circle.htmlを読んでみてください。

  // set rect size
  svg.selectAll(".chart")
    .data(dataset)
    .enter()
    .append("rect")
    .attr("x", function(d, i) { return i * (w /  dataset.length) })
    .attr("y", function(d) { return h - d[4] ); });

棒グラフの棒はrectで描画していきます。
attr("x", function(d, i) { / ... / }) は、バインディングされたすべての配列要素に対してカウンタiを使いながらx軸の描画位置を設定しています。カウンタに1つの棒のサイズをかけてあげれば描画位置が出てきます。
y軸については少し注意点があります。
下の図の白い枠の棒の長さがy軸の指定する位置になり、そこから青色の棒が描画されます。
今は白い枠の棒の長さをy軸で表現しているので、全体の長さから青色の棒の長さを引いてあげます。 CSVファイルの5列目に降水量のデータがあるので、d[4]が長さで使いたいデータです。

ではようやく棒グラフのサイズを指定していきます。(上の図の青色の部分です。)

  // graphing each data of dataset
  svg.selectAll("rect")
    .attr("width", (w / dataset.length) - barPadding) 
    .attr("height", function(d) { return d[4] });

1つの棒の幅は「全体の幅 / データの数 - 棒と棒の間隔」で計算できます。 1つの棒の高さはデータの大きさそのものです。 なお、データの大きさが大きすぎるときはここで高さの調整をしてあげます。

さて、これで棒グラフっぽいものが完成しました。

グラフに色を付ける

せっかくなのでデータの大きさに応じて色を変えたいと思います。 色は0〜255のrgbで表現できます。 データの最大値が255になるように、まずはデータの最大値を255で割ってあげます。 その値を全てのデータに対してかけてあげればデータのサイズに応じた色を塗ることができます。

全てのデータから最大値を求めるには
d3.max(dataset, function(d) { return d[4] })
と書いてあげればよいです。

あとは、selectAllで棒を描画するrectに対して"fill"属性を追加し、rgbの値を入れていきます。

  // coloring
  var colorDivNum = d3.max(dataset, function(d) { return d[4] })  / 255;
  svg.selectAll("rect")
    .attr("fill", function(d) {
        return "rgb(0, 0," + Math.round(d[4] / colorDivNum) + " )";
    });

グラフのサンプル
どうでしょうか、これでそれっぽくなったと思います。

今回はここまでですが、実際に棒グラフを書く場合は目盛りなども欲しくなると思います。 そちらのほうもいずれ解説してみたいと思います。

銃・病原菌・鉄 (上)まとめ

銃・病原菌・鉄

文明の発展の差は何に起因したのか。

文明の発展は食料生産力の差によるもの。

<集約農業可能な土地/作物の有無>

環境によって集約農業が出来る土地/できない土地があった。
集約農業が出来る土地にあった国では、人口の増加に成功し、 単位面積あたりの人口密度を高めることができた。

  • 非食料生産者の維持可能な食料生産力

人口密度が高くなると、社会の中の人々の争いが起こるため(万人の闘争)、 秩序を維持するための仕組み・ルールを設けることが必要になる。 そのため、人口の多い社会では集権的な政治が必要となる。
政治家や専門家といった、食料生産に従事しない人を養うことができる 高い生産性が必要となる。

  • 更なる人口増加をもたらす政治組織・専門性

専門家を養うことに成功した社会は、さらに土地あたりの食料生産力を高めることで、 人口を増やすことができた。
人口の多い社会は、戦争を行うと勝つことができるため、より広い土地を得ることができた。 集権政治に成功した社会は、多くの専門知識を持ち、他の近隣の人々よりも多くの人を抱え、 戦争によって所有する土地を広げることができた。


なぜインカ帝国はスペインを侵略することができなかったか

鉄・病原菌・航海術を保有していたかどうか

<専門技術の発展、疫病の免疫の有無、文字の有無 >

  • 製鉄技術の有無
  • 馬のような戦争に適した動物の有無

スペイン兵が鉄製の武器・甲冑を身につけ、馬に乗って戦っていたのとは対象的に、 インカ帝国兵は、服に棍棒で戦っていた。 スペイン160余名に対してインカ帝国が8万名であったことから、 数よりも保有する技術力の高さによって勝敗が決まる時代となった。

  • 家畜の有無
    • 疫病の免疫の有無

戦争当時、スペインがヨーロッパから持ち込んだ天然痘が、 インカ帝国で大流行した。 旧大陸では、家畜によって疫病が久しくもたらされており、免疫を持っていたが、 新大陸では、家畜がおらず、疫病も免疫もなかったため、旧大陸によってもたらされた 疫病が大流行した。

  • 文字の有無
    • 航海術の有無

旧大陸では文字によって知識が蓄積・発展し、その結果航海術を得たが、 新大陸では文字がなく、航海術もなかったため、侵略は一方的なものとなった。

<侵略を助けたその他の要因>

  • 集権政治は国家支配が容易であった

集権的な政治機構を持った国の場合、君主が捕らえられると指揮系統が掌握され、 官僚組織が機能しなくなり、崩壊してしまう。


なぜ文明の発展した国以外では食料生産をのばすことができなかったか

文明の発展は食料生産力の差によるもの。

<集約農業ができるかどうか。>

  • 農作物/家畜起因のもの

    • 集約農業に適した農作物の品種があること

      • 自然発生したものが農業を行った方が生産効率が高いこと
      • 栽培種として人が好む農作物であること
    • 家畜にすることができる動物がいるかどうか

      • ある地域でうまく育成できても、他の土地の条件ではうまく行かないケース
  • 土地起因のもの

    • 農業を行うことに適した気候であること
    • 集約農業を行うことの出来る広さの土地があること
    • 水源があること

発展の差は人種の差によるものでは決してない

ゴールデンウィーク中に下巻も読み終わりたい。

ActiveRecordで複数項目をdistinctする

1つのカラムに対して重複しないデータを取り出そうとした場合、SQLではdistinctを使います。 それをActiveRecordでやろうとした場合、uniqを使うと思います。

例えば、アンケートシステムで回答したユーザの属性情報が以下のように定義されていた場合を考えてみます。

f:id:taise:20130416072440p:plain

職業(job)の重複無しリストを取得するには以下のように書きます。

[1] pry(main)> User.select(:job).uniq
  User Load (0.2ms)  SELECT DISTINCT job FROM "users"
=> [#<User job: "会社員">, 
#<User job: "公務員">,
 #<User job: "大学生">]

次に、単純に年齢(age)、性別(gender)、職業の3つの属性について取得する場合です。
まずは愚直な書き方をしてみます。
ActiveRecordの場合はfindやwhereなどを使って全ての属性を取得するケースが多いので、このような必要項目のみを取得する方法は、大量データを取得する場合を除いてあまり使われないかもしれません。

[2] pry(main)> User.select("age, gender, job")
  User Load (0.3ms)  SELECT age, gender, job FROM "users"
=> [#<User age: "20", gender: "male", job: "会社員">, 
#<User age: "25", gender: "male", job: "公務員">,
#<User age: "20", gender: "female", job: "大学生">, 
#<User age: "25", gender: "male", job: "公務員">, 
#<User age: "25", gender: "male", job: "公務員">]

今度は、年齢(age)、性別(gender)、職業の3つの属性について重複無しの組み合わせ情報を取得する場合です。いわゆるコンビネーションというやつです。

SQLで書く場合は単純に3つの項目でdistinctすれば良いのですが、上のような書き方では1項目しかとれませんし、select()の引数にシンボルで複数項目を指定するとエラーがでて怒られてしまいます。

[3] pry(main)> User.select(:age, :gender, :job).uniqArgumentError: wrong number of arguments (3 for 1)
from /Users/taise/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.13/lib/active_record/relation/query_methods.rb:70:in `select'

そのため、取得したいカラム名を通常のselect文で書くような形で書いて、「"(ダブルクォーテーション)」でかこったものにuniqをくっつけてあげれば、コンビネーションを取得するクエリが実行されます。

[4] pry(main)> User.select("age, gender, job").uniq  
  User Load (3.4ms)  SELECT DISTINCT age, gender, job FROM "users"
=> [#<User age: "20", gender: "female", job: "大学生">, 
#<User age: "20", gender: "male", job: "会社員">, 
#<User age: "25", gender: "male", job: "公務員">]

ちなみに、select().uniqをつなげる形で書いてあげてもOKです。

[5] pry(main)> User.select(:age).uniq.select(:gender).uniq.select(:job).uniq
  User Load (0.4ms)  SELECT DISTINCT age, gender, job FROM "users"
=> [#<User age: "20", gender: "female", job: "大学生">, 
#<User age: "20", gender: "male", job: "会社員">,
 #<User age: "25", gender: "male", job: "公務員">]

この書き方だと、重複を取り除く問い合わせをしているのに、select().uniqが重複しているというのが皮肉ですが、これでうまく行きます。 where句の条件をつないでも同じような効果が得られるのですが、この辺りのActiveRecordの柔軟性は驚きました。

Tweetpingからわかるイマドキのあれこれ

ちょっとネタにするのが遅れたけれど、TweetpingというWebアプリが面白い。
正しくは、これを使って見えてくることが面白いです。

 WIRED JAPAN「リアルタイムのツイート」がまたたく世界地図

せっかくなので、Tweetping のリンクをタブで開いて、様子を見ながらブログを読んでみてください。

東南アジアのIT普及

Twitterのようなツールは、北米、ヨーロッパ、東アジアといった地域で使われているイメージがあるけれど、東南アジアでかなり使われていることがわかります。 特に、インドネシア、フィリピン、タイは広い地域でかなり使われています。 タイムゾーンが違うのと、人口(母数)も違うので一概に比較はできないことを差し引いても相当なものです。

Twitterがこれだけ使われているということは、外で持ち出して使える環境が整っているということです。
つまり、スマートフォンのようなデバイスが普及していることと、ネットワーク・インフラが整備されているということも言えると思います。
で、調べてみたらやっぱりそういった記事がありました。

http://itpro.nikkeibp.co.jp/article/COLUMN/20130107/448041/

Twitterが使われているということは、Webアプリを使う文化が根付いているとも言えます。
さて、先ほどタブでTweetpingを開いていた方は一度見てみてください。
今後、Webアプリを世界で売っていきたいときは、英語やフランス語等だけでなく、インドネシア語なども翻訳切り替えをすることを検討してみてもいいかもしれません。

独自文化を作る中国

東南アジアに引き換え、IT文化の浸透した国なのに真っ暗な(全然つぶやかれていない)地域があります。
そう、中国です。暗黒大陸といった様相です。
人口は13億人以上で、都市部ではスマートフォンを使っているのが当たり前ですが、びっくりするくらい光っていません。

それもそのはず、かの有名な金盾(きんじゅん)という巨大ファイアーウォールがTwitterの利用を阻んでいるからです。
以前中国に行ったときに、試しにネットでいろんなサイトにアクセスしたことがあるのですが、TwitterだけでなくFacebookや日本のほとんどのブログを見ることができませんでした。噂には聞いていましたが、金盾のフィルタリングは強力です。
そして、検索サービスの百度になぜかリダイレクトさせられます。多分、百度は情報統制のコントロールが効いているから、そっちを使えということなんでしょうが・・・。
プロキシサーバや特殊なVPNを介して金盾を回避することも出来るそうですが、普通の人はそこまではしないでしょうから、わざわざアクセスの面倒な国外のサービスを使おうなんてなりません。

では、こうしたWebサービスがないかというとそうではなく、Twitterに似た別のサービスがある(weibo)ようです。もともとQQというショートメッセージ・サービスが非常に流行っていたことは聞いていましたが、最近ではLineに似たWeChatというサービスが出ているようです。
こうした独自のWebアプリ文化が生み出されているのは、金盾によるものだけでなく、潜在的な利用者が13億人という規模だからこそ成り立っている部分はあるかもしれません。
逆に、中国でWebサービスを提供するのは、こうした政治的な配慮も十分に必要となるため、非常に困難だと言えるかもしれません。

"モダン"なJavaScriptが詰まっている

Tweetpingのサイトの左側に使っているライブラリが書いてありますが、イマドキはやりの技術が詰まっていて面白いです。 こんなリアルタイムに画面を書き換えるアプリをAjaxで毎回TCPつないだり、サーバーサイドが各クライアントのリクエストを全て毎回さばいていたら負荷が大変なことになってあっという間にパンクしてしまいます。

これだけ負荷を感じずに利用できるのは、WebSocketを使ったデータ送信とJavaScriptMVC使ったブラウザが頑張るアプリになっているからでしょうね。 ちゃんとソースを読んではいないですが、Socket.IOでインプットデータだけを渡して、 bacoborn.js + Underscore.jsをベースにProcessing.jsで描画しているようです。 ライブラリ管理は最近目にすることが多いRequireJSを使っています。
この辺りは、積極的に使って身につけていきたいところです。

 

というわけで、時期を外した感がありますがTweetpingからわかるイマドキのについていろいろと書いてみました。 Webアプリの面白さと感動を久しぶりに味わいました。
こんなアプリ作れるようになりたいな。

ステートフルJavaScript ―MVCアーキテクチャに基づくWebアプリケーションの状態管理

ステートフルJavaScript ―MVCアーキテクチャに基づくWebアプリケーションの状態管理

アメリカなう

サンフランシスコについた。
時差は-17時間だそうで、まだ日曜の14時すぎの真っ昼間です。

f:id:taise:20130225015937j:plain

まずはサンフランシスコの街並み。

f:id:taise:20130225022329j:plain

噂に聞いていた通り坂がすごい。

f:id:taise:20130225022511j:plain

そして、シリコンバレーへ。
通りがけにいろんな知っている会社が普通にある。

f:id:taise:20130225071604j:plain

なかでもGoogleが一番自由でおもしろい。

f:id:taise:20130225034335j:plain

自分達の他にも同じように観光にきている人がちらほら。

f:id:taise:20130225034701j:plain

社内の敷地に比較的自由に出入りができる。
有名なGoogleカラーの自転車がそこら中に適当に置いてあったりする。

f:id:taise:20130225034844j:plain

さらには歴史的な著名人の石像や、意味わからない恐竜の骨が、社内の庭に置いてあったりする。

f:id:taise:20130225034942j:plain

近々、専用の飛行機上を作るのだとか。 本気で遊んでいて面白いなぁ。