あなただけの登山ルートがそこにはある『山頂をめざせ』:ボドゲ紹介

この記事何?

この記事は、 2016年ボドゲ紹介02 Advent Calendarの7日目です。

www.adventar.org

参加を決めてから気づきましたが、ボドゲ紹介01 の7日目は弊社のボドゲ部部長 @kano_e さんが書いていますので、そちらもどうぞ

www.evernote.com

今日紹介するゲームは、お気に入りなサイコロゲー「山頂をめざせ」です!

Gipfelstürmer: AMIGO - Familienspiel

Gipfelstürmer: AMIGO - Familienspiel

まずは簡単にルールから

まずはじめに、1人5匹のヤギとプレートを一枚ずつ持ちます。

このヤギさんを山頂に進めるのがゲームの目的です!

この5匹のヤギを山の麓に並べてゲームスタート! f:id:pokotyamu:20161203221143j:plain

ターンが回ってくると、サイコロを5個振って各看板に書いてある目をクリアーできれば一歩前に進めます。 サイコロは振り直したいものだけキープして、振り直しは2回まで振り直せます。

例えばこの写真は、3と6のツーペアが揃っているので、 f:id:pokotyamu:20161202224817j:plain f:id:pokotyamu:20161202224826j:plain

このツーペアの看板が進めるという感じでズンズンヤギさんを進めていきましょう!

自分のヤギさんを押し上げちゃえ

山頂までのルートにはヤギさんが止まる枠があるのですが、それには上限が決まっています。 小さい枠はみんなで1匹、大きい枠は個人で2匹までです。 じゃあ、それ以上は進めないのか?

f:id:pokotyamu:20161203223344j:plain

ここがこのゲームの醍醐味! 自分のヤギを押し上げちゃう事ができるんです!!

f:id:pokotyamu:20161203223334j:plain

上に行けば行くほど、看板の賽の目が難しくなるので、 このようになるべく道に続けるようにヤギを配置して、上に上に押し上げていくのがこの山頂をめざせの醍醐味です!!

相手を押しのけちゃえ

ゲームの中盤になると進む先に他の人のヤギがいる。。。という状況になります

f:id:pokotyamu:20161202225510j:plain

その場合どうするか。。。。

f:id:pokotyamu:20161203224450j:plain

f:id:pokotyamu:20161202225521j:plain

邪魔な敵は押しのけていくのです!!!

上手くいけば、一番下まで突き落とすことができます!!

終了条件

こうして、ヤギさんを押し上げたり、敵を押しのけたりして、一番先に山頂に2匹のヤギさんを山頂に登らせたら勝ちです!!

f:id:pokotyamu:20161202231405j:plain

あなたは白色ヤギさんや黄色ヤギさんみたいに準備万端に用意する派? [f:id:pokotyamu:20161202231042j:plain

それとも、緑色ヤギさんみたいに5つのぞろ目を気合いで出す派? f:id:pokotyamu:20161202231058j:plain

  • どのルートを進ませるかという戦略
  • 自分の力で出す目をコントロールする力

両方がバランス良く必要な、山頂をめざせいかかでしょうかo(・ω・´o) この日は着々とヤギさん並べてる間に6の5個ゾロ出されて負けましたw

おわりに

毎週水曜 19:30~ 弊社ボドゲ部活動中です! ほぼ毎週ゲストさんもいらっしゃっていますので、お時間ありましたらぜひ湯島まで〜

ff-boardgame.herokuapp.com

明日はowl_8 - Adventar の今年遊んだボドゲ です!

Webを支える技術を読んでる まとめ5

この記事について

技術研修で読み進めているWebを支える技術について、各章のまとめを順次上げていく。

HTTPヘッダとは

おさらい

Webを支える技術を研修で読んでる まとめ2 - pokotyamu的書きなぐり日記 メッセージヘッダーの部分が今回説明するHTTPヘッダである。

概要

ヘッダには、メッセージボディに対する付加情報(メタデータ)を入れる。 例えば、メディアタイプや言語タグなどである。 また、リソースへのアクセス権を設定する認証や、クライアントとサーバの通信回数と量を減らすキャッシュなどのHTTPの機能はヘッダで実現する。

つまりこのような機能は第7~8章で述べたHTTPメソッドステータスコードと、本章のHTTPヘッダの組み合わせによって表現される。

本章では、 HTTP1.1で主に使用される頻度の高いものだけに絞って説明する。

歴史的背景

  • HTTP0.9の頃には、HTTPヘッダは存在しなかった
  • HTTPの仕様がバージョンアップするに連れ、本文のメタデータを表現するために電子メールのメッセージ仕様を使う方式が採用される
    • そのため、現在のHTTPヘッダは電子メールのヘッダと同じものもある
    • メールのメッセージ仕様は番兵構造である。^1
  • メールは一方通行のやり取りだったが、HTTPは双方向にやり取りをするため拡張する必要がある

日時

DateやExpiresで表現する。 メッセージ作成の時間や、PUTやDELETEの時間指定などに使用される。 
以下は主要な日時を使用するヘッダである。

利用するメッセージ ヘッダ 意味
リクエストとレスポンス Date メッセージを作成した日時
リクエスト If-Modified-Since 条件付きGETでリソースの更新日時の指定
リクエスト If-Unmodified-Since 条件付きPUTやDELETEでリソースの更新日時の指定
レスポンス Expries レスポンスをキャッシュ出来る期限
レスポンス Last-Modified リソースを最後に更新した日時
レスポンス Retry-After 再度リクエストを送信出来るようになる日時の目安
Date: Tue, 06 Jun 2010 03:34:00 GMT

HTTPメソッドで使用する日時は、必ず GMT(グリニッジ標準時)で返さなければならない。

MIMEメディアタイプ

MIME(Multipurpose Internet Mail Extensions)の略。 名前の通り、電子メールのヘッダから採用されたものである。 今後はメディアタイプで示す。

Cotent-Type

メディアタイプの指定を行う。

Content-Type: text/plain

このメッセージボディの中身がどのような形式のものなのかを指定する。

メディアタイプには、以下の表の9つのタイプが存在している。

タイプ 意味
text 人の読めるデータ text/plain
image 画像データ image/jpeg
audio 音声データ audio/mpeg
video 動画データ video/mp4
application その他のデータ aplication/pdf
multipart 複数データからなる複合データ multipart/related
message 電子メール message/rfc822
model 複数次元で構成するモデルデータ model/vrml
example 例示用データ example/foo-bar

text/planeの/の左側を「タイプ」、右側を「サブタイプ」と呼ぶ。 タイプは勝手に増やすことは出来ないが、サブタイプは比較的自由に作ることが出来る。 サブタイプ一覧については数が膨大なので、IANAのページを参照する。 IANAは、「Internet Assigned Numbers Authority」の略。 ドメイン名、IPアドレスプロトコル番号など、インターネット資源のグローバルな管理を行っている南カリフォルニア大学情報科学研究所のプロジェクトチーム。サブタイプの管理もここが行っている。

charset (日本語メッセージの注意)

文字エンコーディングを指定する。

Content-Type: application/xml; charset=utf-8

charsetは省略可能だが、タイプがtextの場合は注意が必要である。 HTTPでのtextタイプのデフォルト文字エンコーディングは、ISO 8859-1と定義されている。 もし、日本語文字列が入っているメッセージに対して、ISO 8859-1と解釈しようとするため、文字化けを引き起こす可能性がある。 さらに、メッセージボディ内で、文字エンコーディングを指定している場合でも、Conttent-Typeヘッダのcharsetが宣言されているならば、こちらが優先される。

文字化けを起こさないように気をつけるためには、必ずcharsetパラメータを付ける事が望ましい。

言語タグ

charsetパラメータは文字エンコーディング方式を指定するが、リソース表現の自然言語を指定する場合は、 Content-Languageを使用する。

Content-Language: ja-JP

言語タグの「-」の左側には、ISO 639が指定する言語コードが入る。 日本語ならば「jp」英語ならば「en」など
右側にはISO 3166が定義する地域コードが入る。 日本ならば「JP」アメリカならば「US」など

言語コードと地域コードの組み合わせにより、1つの国に複数言語ある場合や多数の国で使われる言語にも対応することができる。

コンテントネゴシエーション

メディアタイプや文字エンコーディングや言語タグはサーバが一方的に決定するだけでなく、クライアントと交渉して決めることも出来る。

クライアントが処理出来るメディアタイプを伝える時は、Accept クライアントが処理できる文字エンコーディングを伝える時は、Accept-Charset クライアントが処理できる言語を伝える時は、Accept-Language

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
Accept-Language: ja,en-us;q=0.7,en=0.3

q=のパラメータは優先度が指定でき、1に近いほど優先される。 省略されている場合は1が入る。

Content-Length

Content-Lengthヘッダを利用して、メッセージボディのサイズを10進数のバイトで示すことが出来る。 静的ファイルなど、あらかじめサイズが分かっているリソースを転送する場合などは、これを利用する。
 しかし、動的な画像ファイルなど、すぐにサイズが確定しない場合、Transfer-Encodingヘッダを利用して、ボディを複数の塊(チャンク)にして、転送することが出来る。 これにより、最終的なサイズが分からないデータに対しても、ボディを少しずつ転送することが出来る。

次にチャンク転送の例を示す。

POST /test HTTP/1.1
Host: example.jp
Transfer-Encoding: chunked
Content-Type: text/plain; charset=utf-8

10
The brown fox ju

10
mps quickly over

e
 the lazy dog.
 
0
<空行>

各チャンクの先頭にはチャンクサイズが16進数で入る。 上記の例において、16バイトで表現する16進数の「10」と14バイトを表現する「e」が登場する。 最後には必ず長さ0の空行を付ける。

なお、HTTP1.1の仕様では、全てのHTTP1.1実装は、チャンクエンコーディングを受信しなければならない。

認証

概要

現在主流のHTTP認証方式には、HTTP1.1が規定しているBasic認証とDigest認証がある。 またWeb APIでWSSEというHTTP認証の拡張仕様を利用する場合もある。

今回は、主流の2つを簡潔に説明する。

そもそも認証について、あるリソースに制御がかかってる場合、401 UnauthorizedとWWW-Authenticateヘッダを利用して、クライアントにリソースへのアクセスに必要な認証情報を通知出来る。

DELETE /test HTTP/1.1
Host: example.jp
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Example.jp"

これは、Basic認証も、Digest認証もどちらも使用する。

Basic認証

最も簡単かつ基本的な方式。 ユーザ名とパスワードを使って認証を行う。

ブラウザから送信される認証情報は、「ユーザ名:パスワード」という形式で「:」区切りで並べ、これをBASE64エンコーディングした文字列をHTTPヘッダのAuthorizationフィールドに記載する。

古くから使用される方式のため、ほとんどのWebサーバやWebクライアントが対応しているが、認証情報が暗号化やハッシュ化されないため、通信途上で第三者に覗き見られる危険性がある。

そもそも、

$ echo Z3Vlc3Q6VGFrZTU= | base64 -D
guest:Take5

このようにbase64をデコードすることによって、簡単に元の文字列を判定することが出来る。

よって、Basic認証を使う時は、それが許される程度のセキュリティ強度でいいのか?SSL(Secure Socket Layer)やTLS(Transport Layer Security)を使ってHTTPS(HTTP over Secure Socket Layer)通信し、通信路上で暗号化するか?を検討する必要がある。

Digest認証

Digest認証は、Basic認証よりもセキュアな認証方式である。
あるメッセージに対して、ハッシュ関数を適用した結果のハッシュ値を使って認証を行う。 ハッシュ関数とは、データからそのデータを代表する数値を求める関数のことで、ハッシュ関数を使って得られた値のことをハッシュ値と呼ぶ。

Basic認証では、

DELETE /test HTTP/1.1
Host: example.jp
Authorizaition: Basic dXNlcjpwYXNzd29yZA==

このようなリクエストで送信していたが、Digest認証では、

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Digest realm="Example.jp", nonce="1ac421d9e0a4k7q982z966p903372922", qop="auth", opaque="92eb5ffee6ae2fec3ad71c777531578f"

このようにより複雑なレスポンスが返ってくる。

このWWW-Authenticateの値のことをチャレンジと言う。 クライアントはまず認証なしで、リクエストを送信した上で、チャレンジを使って次回のリクエストを組み直す。

nonceはnumber used onceの略で、リクエストごとに変化する文字列である。 nonceの値は、サーバの実装に依存しているが、基本的には、タイムスタンプやサーバだけが知り得るパスワードから生成する。

qopはquality of protectionの略で、authauth-initを指定して使用する。 qopの値はクライアントが送信するダイジェストの作成方法に影響を与える。 authの場合、メソッドURIからダイジェストを作成する。 auth-initの場合、メソッドURIに加えてメッセージボディーも利用する。 これにより、POSTやPUTでボディを送信するときは、auth-initを使うとメッセージ全体が改ざんされないことを保証することが出来る。

opaqueは、クライアントには不透明(推測できない)文字列で、同じURI空間へのリクエストえは共通してクライアントからサーバに送る。

これらを以下のような流れで実行する。

  1. ユーザ名、realm、パスワードを「:」で連結し、MDS(Message Digest Algorithm)ハッシュ値を求める
  2. メソッドURIのパスを「:」で連結し、MDSハッシュ値を求める
  3. 1の値、サーバから得たnonce、クライアントがnonceを送った回数(cnonce)、qopの値2の値を「:」で連結し、MDSハッシュ値を求める

サーバ上にパスワードのハッシュ値を保管し、そのハッシュ値を元に認証を行うため、パスワードそのものをサーバに預けなくて良くなる点から、セキュリティリスクを下げることが出来る。

Basic認証の場合は、同じURI空間のリソースであれば、クライアントは一度認証してしまえば、2回目以降は自動的にユーザ名とパスワードを送れた。しかし、Digest認証では、サーバからのnonceがなければクライアントが側でダイジェスト計算されないため、一度401 Unauthorizedレスポンスを返さなければならない。

また、パスワードを暗号化するだけなので、メッセージを暗号化したい場合は、Basic認証同様HTTPSを利用する方法が考えられる。

さらに、ApacheなどのWebサーバでは、Digest認証がオプション扱いでサポートしておらず、自前で実装しなければならないといった状況が考えられる。

キャシュ

概要

キャッシュとは、サーバから取得したリソースをローカルストレージ(HDDなど)に蓄積し、再利用する手法のことである。 ローカルストレージにキャッシュしたデータそのものをキャッシュと呼ぶも事もある。 クライアントが蓄積したキャッシュは、キャッシュが有効な間、再度そのリソースにアクセスしようとした時に、再利用する。

キャッシュ用ヘッダ

クライアントが、サーバから取得したリソースがキャッシュ可能かどうか? そのリソースのキャッシュに関するメタデータが入るヘッダについて説明する。

Pragma

Pragmaヘッダに指定できる値は、公式にはno-cacheのみ。 この値はリソースをキャッシュしてはならないことを示す。 クライアントは、次回リソースにアクセスする時、必ず再度サーバにアクセスしなければならない。

Expries

Exouresヘッダはキャッシュの有効期限を示す。 指定できる値には、日時をGMTのみである。 リソースを変更することがない場合、永久にキャッシュ可能であることを示したくないが、そのような場合でも、Expriesには、最長で、約1年後の値を入れることが推奨されている。

Cache-Control

HTTP1.1から導入されたヘッダ。 PragmaもExpiresもどちらも、Cache-Controlで代用出来る。

Pragma: no-cache
Cache-Control: no-cache

これら2つは同様の意味として使える。

また、有効期限の書き方として、相対時間(あと○○秒有効) といった設定が出来るようになった。

Cache-Control: max-age: 86400

この他にも、様々な細かい設定が行うことが出来る。 詳細については、RFC 2616を参照。

使い分け

以上の3種類の使い分けについては、次の3つの方針がある。

  • キャッシュさせない場合は、PragmaとCache-Controlのno-cacheを同時に指定する
  • キャッシュの有効期限が明確に決まっている場合は、Expiresを指定する
  • キャッシュの有効期限を相対的に指定したい場合は、Cache-Controlのmax-ageで相対時間を指定する

条件付きGET

クライアントがExpiresやCache-Controlヘッダを検証した結果、ローカルキャッシュをそのまま再利用出来ない時でも、条件付きGETを行えば再利用出来る可能性がある。 仕組みとしては、変更されているかを調べる項目をリクエストヘッダに送って、そのレスポンスからそのまま使えるかどうかを検証する。

If-Modified-Since

まず、リクエストの例は次のようになる。

GET /test HTTP1.1
Host: example.jp
If-Modified-Since: Thu, 11 May 2010 03:34:00 GMT

これはローカルキャッシュの更新日時が2010年5月11日3時34分ちょうどであることを示している。 これに対して、サーバはこれ以降変更がない場合、以下のレスポンスを返す。

HTTP/1.1 304 Not Modified
Content-Type: application/xhtml+xml; charset=utf-8
Last-Modified: Thu, 11 May 2010 03:34:00 GMT

304 Not Modifiedは条件付きGETへのレスポンスで、リソースが変更されていないことを示す。 これにより、レスポンスにボディを含まないため、ネットワーク帯域を節約出来るメリットがある。

If-None-Match

これも、リクエストの例をベースに説明する。

GET /test2 HTTP1.1
Host: example.jp
If-None-Match: ab3322028
HTTP/1.1 304 Not Modified
Content-Type: application/xhtml+xml; charset=utf-8
ETag: ab3322028

If-Modified-Sinceヘッダによく似ているが、一番の違いはETagというヘッダの値を更新の判定に使用している点である。 ETagはリソースが更新されるたびに新しい値に変わる文字列であり、特に文字列的な意味はない。 このETagはリソースに紐付けているため、たとえETagの文字列が同じでも違うリソース同士では意味が無い。

ETagの生成方法は静的ファイルと動的ページでは異なる。

  1. 静的ファイルの場合

    Apacheのデフォルトでは、静的ファイルのETagの値はinode番号、ファイルサイズ、更新日時から自動で計算してくれる。 ただし、inode番号は、同一内容のファイルでもファイルシステムが異なれば別の値となる。 例えば、サーバを分散されている時に注意すべきである。 そのため、ファイルサイズと更新日時のみでETagの値を計算させるようにする。

  2. 動的ページの場合 ApacheなどのWebサーバは動的に生成されるHTMLやフィードなどは自動的にETagを計算してくれない。 そのため、Webアプリケーション側でETagの値を計算する必要がある。 一般的には、リソースのメタデータ(更新日時、サイズなど)から作成する方法や、リソースの更新カウ

使い分け

それぞれを使い分けるための方針は次のようになる。

  • Last-Modifiedヘッダしか分からない場合はIf-Modified-Since
  • サーバがETagヘッダを出している場合にはIf-None-Match
  • 時計を持っていないサーバに対してはIf-None-Match
  • ミリ単位で変更される可能性のあるリソースにはIf-None-Match

持続的接続

HTTP1.1での新機能がこの持続的接続(Persistent Connection)

HTTP1.0までは、サーバがレスポンスを返すたびにTCPコネクションを切断していた。 これを解決するために、Keep-Aliveヘッダを利用して、まとめて接続し続ける手法が開発された。 これにより、クライアントはレスポンスを待たずに、同じサーバにリクエストを送信することが出来る。

HTTP1.1では、このKeep-Aliveが標準化されている。 コネクションを切断したい場合は、リクエストのConnectionヘッダにcloseという値を指定すれば良い。

Webを支える技術を研修で読んでる まとめ4

この記事について

技術研修で読み進めているWebを支える技術について、各章のまとめを順次上げていく。

ステータスコードとは

概要

WebサービスでもWebAPIでもリクエストに対するレスポンスの内容を概略的に表したものがステータスコードである。 これらを正しく使うことは、WebAPIを作成する上でのマナーである。 例えば、エラーを表すコードを返さなければならないのに、成功のコードを返してしまったら、受け取った側はそれを正しいものとして認識してしまう。 つまり、ステータスコードが正しく守られていない場合は、専用のクライアントを実装しなければならず、色々なクライアントで使用出来るというWebAPIの利点を活かすことも出来ない。 そのため、誤用することなく、正しい理解をすることが求められる。

Webを支える技術を研修で読んでる まとめ3 - pokotyamu的書きなぐり日記で述べた、レスポンスメッセージの1行目にあるのが、ステータスラインである。 おさらいすると、ステータスラインは、プロトコルバージョン、ステータスコード、テキストフレーズから成る。 例えば HTTP/1.1 200 OKといった形のステータスラインがあった場合。 200ステータスコードである。

ステータスコードは3桁の数字であり、先頭の数字によって5つに分類することが出来る。

ステータスコード 意味
1xx 処理中
2xx 成功
3xx リダイレクト
4xx クライアントエラー
5xx サーバエラー

この5つに分けられている理由としては、次の3つが挙げられる。

  • どのようなレスポンスであったかの概要を理解することができる
  • クライアントとサーバの結びつきを緩やかにすることができ、サーバのバージョンアップやクライアントの置き換えが行いやすくなる
  • ステータスコードが新たに追加された場合でも、先頭の数字さえ分かればクライアント側で最低限の処理を行うことができる


以降では、5つの分類それぞれの概要と代表的なものについて説明する。 基本的にRFC2616の原文リンクの和訳と補足の形ですすめる。

1xx

概要

1xx系は、処理が継続していることを示す。 クライアントはそのままリクエストを継続するか、サーバの支持にしたがってプロトコルをアップデートして再送信する。 実際に見かける場は、ほとんどないため、今回は割愛する。

2xx

概要

何かのリクエストが成功したことを示す。

200 OK

リクエストが問題なく受理されて、要求に従ったレスポンスが返る。 ブラウザでページが読み込まれて、表示された時に使用されることから、一番遭遇頻度が高いステータスコードといえる。

201 Created

リクエストが完了し、新たに作成されたデータのURIが返る。 新たに作成されたURIの情報はレスポンスヘッダのLocationで示される。 ※ただし、PUTで作成した場合は、Locationは返らない さらにレスポンスで返されるリソースのタイプはContent-Typeで示される。

この生成処理は、リクエストを返す前には終了していなければならず、もし直ぐに返せない場合は、202 Acceptedを返す。

3xx

概要

他のリソースへのリダイレクトを示す。 クライアントはこのステータスコードを受け取った時、レスポンスメッセージのLocationヘッダを見て新しいリソースへ接続する。

301 Moved Permanently

リクエストで指定したリソースが新しいURIに移動したことを示す。 その時のロケーションはレスポンスヘッダ内のLocationで示される。 もし、301のステータスコードGET,HEADメソッド以外で受け取ったユーザエージェントは、条件の変更などが発生する場合があるため、ユーザが確認出来るまで、自動的にリダイレクトの要求を受け取るべきではない。

302 Found

リクエストで指定されたURLが一時的に存在せず、別のURLに仮の移転をしているので、移動先のURLに転送したことを示す。

302のステータスコードも301と同様にGET,HEADメソッド以外で受け取ったユーザエージェントは、条件の変更などが発生する場合があるため、ユーザが確認出来るまで、自動的にリダイレクトの要求を受け取るべきではない。

303 See Other

主にPOST後のリダイレクトで用いられる。 フォームからPOSTした後にリダイレクトしてTOPページに戻す場合が考えられる。 最初の処理では、POSTでリクエストしたが、ブラウザはリダイレクト先にはGETを使う。

307 Temporary Redirect

HTTP1.1で追加され、本来の302が持つべきだった内容を再定義している。よって今後の設計においては、302ではなく307を使うことが推奨される。
最初のURLでは実際の処理は行わず、リダイレクト先に改めてリクエストを出し直して欲しい時に使う。 つまり、最初のリクエストがPOSTだった場合、ブラウザはリダイレクト先にもPOSTを使う。 基本的な処理自体は302と変わらないが、元々リクエストに使った動詞をそのまま使って、変更先のURIにリクエストして欲しい場合は307を使うべきである。

参考:HTTPステータスコード – 302 Foundと303 See Otherと307 Temporary Redirectの違いについて

301と307(302)の違い

どちらも、URIの移動を示すステータスコードである。 ユーザ目線からしても、どちらもページが移動する挙動のため意識する必要はない。 しかし、 検索エンジンからすると以下のように挙動が変わる。

  • 301の場合は、URLが移転先のものになる
    • サイトのリニューアルでURLが変更になった場合
  • 307(302)の場合は、URLが元のURLのものになる
    • サーバーエラーが発生したときにエラーページへリダイレクトする場合

サイトのURIを変更する時は、これらの違いを意識する設計が求められる。 参考:301リダイレクトと302リダイレクトは離婚と不倫 – SEO例え話

4xx

概要

クライアントエラーを示す。 原因はクライアント側のリクエストにある。 エラーを解消しない限り正常な結果が得られないので、同じリクエストをそのまま再送信することは出来ない。

400 Bad Request

リクエストの文章が間違っている時に発生する。 クライアントは、再度修正して送り返す必要がある。

401 Unauthorized

適切な認証情報を与えずにリクエストを行った時に発生する。 レスポンスのWWW-Authenticateヘッダで、クライアントに対して認証方式を伝える。

403 Forbidden

リクエスト自体の処理は受け付けたが、権限がないために実行出来ない時発生する。 ファイルの閲覧や、外部サイトからのアクセスを禁止しているページで発生する。 解消するためには、サーバ側の設定を調整するしかない。

404 Not Found

指定したリソースが存在しない場合に発生する。 既に削除されてしまっていた場合や、URLの入力ミスなどの時に起こる。

403などで外部サイトからのアクセスを禁止している時に、要求が拒否された理由を正確に明らかにしたくない場合や、他の応答が適用されない場合、404が使用されます。

5xx

概要

サーバエラーを示す。 原因はサーバ側にある。 サーバ側の原因が解決すれば、同一のリクエストを再送信して正常な結果が得られる可能性がある。

500 Internal Server Error

サーバ側に何らかの異常が生じていて、正しいレスポンスが返せない時に発生する。 レスポンスボディには、異常の原因が入る。

503 Service Unavailable

サーバがメンテナンスや高負荷に耐え切れずサービスを提供していない時に発生する。 ツイッターのクジラが出たなどが有名どころ。 f:id:pokotyamu:20160510190718j:plain

エラー処理

4xx系と5xx系は、どちらもエラーを表現している。 エラーコードはHTTP仕様が規定しているが、ボディーにどんなメッセージを入れるかは規定していないので、そのページが人間用なのかプログラム用なのかで分けてエラーメッセージを返すとよい。

まとめ

今回のステータスコードを一覧にまとめる。

ステータスコード 補足文章 概略
200 OK リクエストが問題なく受理されて、
要求に合わせたレスポンスが返る
201 Created データの作成が行われ、新たに作成されたデータのURIが返る
301 Moved Permanently リクエストで指定したリソースが
新しいURIに移動したことを示す
302 Found リクエストで指定されたURLが一時的に存在せず、
別のURLに仮の移転をしているので、
移動先のURLに転送したことを示す
303 See Othoer 主にPOST後のリダイレクトで用いられる
307 Temporary Redirect 基本302と同じ。
元々リクエストに使った動詞をそのまま使って、
変更先のURIにリクエストして欲しい場合に使用
400 Bad Request リクエストの文章が間違っている時に発生する
401 Unauthorized 適切な認証情報を与えずにリクエストを行った時に発生する
403 Forbidden リクエスト自体の処理は受け付けたが、
権限がないために実行出来ない時発生する
404 Not Found 指定したリソースが存在しない場合に発生する
500 Internal Server Error サーバ側に何らかの異常が生じていて、
正しいレスポンスが返せない時に発生する
503 Service Unavailable サーバがメンテナンス中や高負荷に耐え切れず
サービスを提供していない時に発生する

Webを支える技術を研修で読んでる まとめ3

この記事について

技術研修で読み進めているWebを支える技術について、各章のまとめを順次上げていく。 前  pokotyamu.hatenablog.com

次 

HTTPメソッドの概要

HTTPメソッドには9つの種類がある。

メソッド 意味
GET リソースの取得
POST 子リソースの作成、リソースへのデータの追加、その他処理
PUT リソースの更新、リソースの作成
PATCH リソースの一部更新
DELETE リソースの削除
HEAD リソースのヘッド(メタデータ)の取得
OPTION リソースがサポートしているメソッドの取得
TRACE 自分宛てにリクエスト・メッセージを返す(ループバック)試験
CONNECT プロキシ動作のトンネル接続への変更

以降、各メソッドについて見ていく。 また、ステータスコードについては、次の第8章で述べる。 今回説明中で使用するステータスコードは、あくまで実装の一例である。そのため、実装のやり方によっては変化することがある。

各ヘッダの確認方法はGoogle Chromeの場合 以下の参考リンクのレスポンスヘッダのコピーを参照 参考:coliss.com - Chrome デベロッパーツールの使い方: プロのように華麗に使いこなすための20のテクニック

GETメソッド

GETでは、指定したURIの情報を取得する。 Webページの取得、画像の取得、映像の取得、フィードの取得など、実際にブラウザを利用している時に一番使われるメソッドがGETメソッドである。

GET / HTTP/1.1
Host: www.hottomotto.com
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Date: Tue, 26 Apr 2016 03:27:37 GMT
Server: Apache
Vary: Accept-Encoding
X-IIJ-Cache: MISS
Transfer-Encoding: chunked

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- 途中略 -->
</body>
</html>

レスポンス例のレスポンスボディー内に、指定したリクエストのhtmlの情報が返されている。 これを読み込んでWebブラウザ上で表示している。

POSTメソッド

POSTメソッドでは3つの役割が存在する。

子リソースの作成

ブログページを親とした時に、ブログ記事が子リソースに当たる。 つまり、ブログ記事の投稿がこの子リソースの作成に当たる。

POST /list HTTP/1.1
Host: example.jp
Content-Type: text/plain; charset=utf-8

こんにちは!
HTTP/1.1 201 Created
Content-Type: text/plain; charset=utf-8
Location http://example.jp/list/item5

こんにちは!

201 Createdというステータスコードが返ってきたが、これは正常にリソースの作成が出来たことを示す。 Locationヘッダにその新しいリソースのURIが入っている。

リソースへのデータの追加

ログリソースの追加などがこれに当たる。

POST /log HTTP/1.1
Host: example.jp

2016-04-25T10:13:00Z, GET /log, 200
HTTP/1.1 200 OK

ここではPOSTのレスポンスとして、200が返ってきたが、これは、リソースの作成ではなく、データの追加を示す。 POSTがデータ作成を意味するか、またはデータ追加を意味するかは実装に依存するため、WebAPIの仕様書などを調べる必要がある。

他のメソッドでは対応出来ない処理

URIの長さにはブラウザの実装上2000文字以内などの制約が入る場面がある。 そのような長いキーワードの場合、URIのクエリにキーワードを入れてGETする方法は利用出来ない。 この時に POSTを利用することで、ボディの中にキーワードを格納することが出来る。

POST /search HTTP/1.1
Content-Type: application/x-www-form-urlencoded

q=very+long+keyword+hogehogehoge......

PUTメソッド

PUTは2つの役割が存在する。

リソースの更新

先ほどのPOSTの記事作成で作ったリソースの内容を更新する。

PUT /list/item5 HTTP/1.1
Host: example.jp
Content-Type: text/plain; charset=utf-8

こんばんは!
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8

こんばんは!

このように、PUTメソッドは、元のリソースを更新するときに使う

リソースの作成

http://example.jp/newitemが存在してないものとする。

POST /newitem HTTP/1.1
Host: example.jp
Content-Type: text/plain; charset=utf-8

新しいリソース/newitemの内容
HTTP/1.1 201 Created
Content-Type: text/plain; charset=utf-8

新しいリソース/newitemの内容

PUTは存在しないURIへのリクエストのため、サーバはリソースを新しく作成すると解釈し、201 Createdを返す。 /newitemが存在していた場合は、更新として処理される。

PATCHメソッド

2010年のRFC7589で追加された一番新しいメソッド。 リソースの一部更新で使用される。 例えば、ブログ記事のタイトルの更新などに使用される。

PATCH /list/item5 HTTP/1.1
Host: example.jp
Content-Type: text/plain; charset=utf-8

##一部更新内容##
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8

##一部更新が反映##

このように、基本的には、PUTの子リソースの更新となんら変わらない。 それぞれの違いについては後述する。

Github APIでも採用されているほか、Ruby on Rails v4.0から正式に採用された。

DELETEメソッド

名前の通りリソースの削除を行うメソッド

DELETE /list/item2 HTTP/1.1
Host: example.jp
HTTP/1.1 200 OK

一般にDELETEのレスポンスはボディーを持たない。 そのため、ステータスコードにボディーがないという意味の204 No Contentが使われる場合がある。

POSTでPUT/DELETEを代用する

今現在、一番よく利用されているのが、GETとPOSTメソッドである。 HTMLのフォームで指定出来るのもこの2つだったが、技術の発展とともに、AjaxXMLHttpRequestというモジュールを利用することで、任意のメソッドを発行できるようになった。 しかし、XMLHttpRequestをサポートしない携帯電話向けブラウザでは2つのメソッドしか利用出来ない。 また、プロキシサーバではPUTによって勝手にサーバーに関する情報をクライアントに追加させたり置き換えさせたりするため、セキュリティの問題で2つのメソッド以外のアクセスを制限する場合がある。

このような状況で、サーバにPUTやDELETEを伝えるためには、

  • _methodパラメータ
    • フォームの隠しパラメータに_methodというパラメータを入れる
    • その中に本来送りたかったメソッドの名前を入れる
    • Ruby on Railsが採用している
  • X-HTTP-Method-Overrde
    • XMLなどの場合に使用
    • X-HTTP-Method-Overrdeヘッダにメソッド名を指定することで、実現する
    • GoogleGoogle Data Protocolが採用している

HEADメソッド

GETとよく似ていているが、GETはリソースを取得、HEADはリソースのヘッダ(メタデータ)のみを取得するメソッド

HEAD /list/item1 HTTP/1.1
Host: example.jp
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8

先述した通り、ヘッダのみ返すため、HEADへのレスポンスにはボディーを含まない。 利用用途としては、ネットワークの帯域を節約しつつ、リソースの大きさや、更新日時を調べるために使う。

OPTIONSメソッド

OPTIONSは、そのリソースがサポートしているメソッドの一覧を返す。

OPTIONS /list HTTP/1.1
Host: example.jp
HTTP/1.1 200 OK
Allow: GET, HEAD, POST
OPTIONS /list/item1 HTTP/1.1
Host: example.jp
HTTP/1.1 200 OK
Allow: GET, HEAD, PUT,DELETE

OPTIONS自体は、Allowヘッダには含めない。 また、OPTIONSメソッドは開発者が独自で実装しなければならない。

主要ではないHTTPメソッド

今まで説明した、7つのメソッドが主にHTTPメソッドとしては使われやすい。 ここからは、少し使用頻度の低い2つのメソッドについて説明していく。

TRACEメソッド

TRACEは、HTTPリクエストを「オウム返しに」HTTPレスポンスとして返す。 ただし、注意すべき点として、リクエストをそのまま返すため、レスポンスの中にCookieヘッダAuthorizationヘッダも含まれてしまう。 そのため、Cross-Site Tracing(XST)攻撃に利用された。 XST攻撃とは、XSS^1とTRACEメソッドを組み合わせた攻撃手法である。 以下、徳丸浩の日記 - 実はそんなに怖くないTRACEメソッドから引用

XSS単独では、XSSによりJavaScript等が動いているブラウザ上のレスポンス(ヘッダ及びボディ)は取得出来ますが、リクエストヘッダを取得することはできません。このため通常は、HttpOnly属性の指定されたCookieや、Authorizationヘッダ(Basic認証のIDとパスワード)を取得することはできません。 しかし、TRACEメソッドを実行すると、先に見たようにリクエストヘッダがそのままレスポンスとして返るので、XSS単独ではとることのできないHttpOnly属性の指定されたCookieや、Authorizationヘッダを盗み出すことができます。これがXST攻撃です。とくに、BASIC認証のIDとパスワードを盗むことができると、長期にわたって不正にログインすることができてしまうため、XSSの影響が大きくなります。

CONNECTメソッド

RFC 2817の定義によると

A CONNECT method requests that a proxy establish a tunnel connection on its behalf. The Request-URI portion of the Request-Line is always an 'authority' as defined by URI Generic Syntax [2], which is to say the host name and port number destination of the requested connection separated by a colon:

```レスポンス例 CONNECT server.example.com:80 HTTP/1.1 Host: server.example.com:80

日本語に軽く訳すと、 「CONNECTは、proxyとのトンネル接続を作るために使われる。リクエストURIの中にhostme名、ポート番号、リクエスト元の情報がコロン区切りで記述される。これらは、URIの一般的なシンタックスである。」

べき等性と安全性

べき等とは「ある操作を何回行っても結果は同じという考え方」である。 数学の絶対値、0の乗算(3 * 0 = 0)などがあげられる。

また、安全性とは「操作対象のリソースの状態を変化させないこと」を意味している。

これらを主要メソッドであるGET、POST、PUT、PATCH、DELETE、HEADに当てはめると次のような図に分類出来る

安全性あり 安全性なし
べき等 GET、HEAD PUT、DELETE
べき等でない POST,PATCH

GETとHEADは、値を取ってくるだけなのでべき等かつ安全なのは自明である。 PUTとDELETEは、値を更新や作成、削除する点から変化を与えるため安全性はないが、何度やっても値は同じなのでべき等性はある。 POSTは、リクエストの結果次第で何が起こるか分からないためべき等性はなし。更に、リソースの状態に変化も与えるため安全性もなし。 POSTの例としては、通販サイトでのブラウザの戻るボタンを押してしまった時に、2重注文のような問題が発生する可能性を示している。 PATCHは、更新の時に、べき等でなく、安全性もない更新であると定義されている。

POSTとPUTとPATCHの使い分け

POSTとPUT

どちらも新しいリソースの作成を行えるが、それぞれの使い分ける指針として、 リソースのURI決定権が挙げられる。

POSTでリソースを作成する場合、URIの決定権は サーバ側にある。 なので、レスポンスヘッダー内にLocationが含まれる。 この動作の例としては、TwitterのようにUTIをサーバーが自動的に作成する場合が挙げられる。

PUTでリソースを作成する場合、 クライアントが決めたURIがそのままサーバ側で使用される。 なので、レスポンスヘッダー内でLocationが含まれていない。 この動作の例としては、Wikiのようにクライアントが決めたタイトルがそのままURIになるものが挙げられる。

PUTとPATCH

Ruby on Rails(以下Rails)の導入された経緯から、この2つのメソッドの違いを考える。 元々Railsでは、レコードの更新に対して、PUTメソッドが使われていた。 Railsで使用するレコードの中にはupdate_atという更新時間の項目が常に含まれている。これは、ユーザが指定していない時でも作成される。 この時、レコード内の別の項目だけを更新した時にupdate_atも一緒に更新時間が変わってしまう。つまり、同じ更新を行う時に毎回同じ結果が返るという べき等性が失われている。 そこで、最初からべき等性も安全性もない、PATCHメソッドを用いることで、この誤用を解消した。

このように、PUTとPATCHは基本的に処理内容としては、同じだが、べき等性が必要か否かで選ぶと良い。 参考:Edge Rails - PATCH is the new primary HTTP method for updates

メソッドの誤用

先ほど、べき等性と安全性の対応表を出したが、全てがあの表に当てはまるとは限らない。 そのパターンについて述べる。

なお、これらのパターンは開発者の問題であることが多く、前述した図が基本と考えて良い。 そのため、べき等性や安全性を考慮して、適切なメソッドを適切なタイミングで使用することを心がける。

GETが安全でなくなる場合

GET: /resources/1/delete HTTP/1.1
Host: example.jp

このようにGETで要求しているにもかかわらず、example.jp/resources/1 を削除しようとする時、安全性がなくなる。 これを防ぐためには、GETの発行前後でリソースに変化が入っていないか?を考えると良い。 基本的にGETでは参照しか出来ないはずなので、deleteなどの動詞がURIに入ってる段階で矛盾している。

PUTがべき等でなくなる場合

価格の更新に対して、現在の価格の50%増加させるといったように、今の差分から処理を行う時 毎回結果が変わってくるため、べき等性がなくなる。 このようなときには、PATCHを使うか、「+50%」といった相対的な表現を避けるべきである。

DELETEがべき等でなくなる場合

ソフトウェアの最新バージョンがhttp://example.jp/latestというエイリアスリソースで管理されている時、このURIに対してDELETEを行うとどうなるか? もし、エイリアスリソースそのものを削除するという処理の場合、http://example.jp/latestが削除されるだけなので、べき等性は保たれる。 しかし、エイリアス先のリソース(最新バージョンのリソース)を指していた場合、ver2.0が削除された次の削除はver1.9になるため、べき等性がなくなってしまう。

このようにエイリアスリソースを削除するように設計するのもいいが、このような特殊なリソースについては、更新や削除などの操作が出来ないような設計にするのが求められる。

CRUDな設計

これまで、9つのHTTPメソッドの種類をまとめた。 これらのメソッドのうち、GET、POST、PUT、DELETEは4つでCRUDという性質を満たす。 CRUDとは、

  • Create:作成、生成
  • Read:読み取り
  • Update:更新
  • Delete:削除

の4つの頭文字を取ったものである。

それぞれの対応関係は、以下の図のようになっている。

CRUD 意味 メソッド
Create 作成 POST、PUT
Read 読み込み GET
Update 更新 PUT
Delete 削除 Delete

CRUDな設計の代表例は、railsのscaffoldした雛形Webアプリケーションが挙げられる。 参考:TECHSCORE - 4.scaffoldを利用した開発(1)

Webを支える技術を研修で読んでる まとめ2

この記事について

技術研修で読み進めているWebを支える技術について、各章のまとめを順次上げていく。

前 Webを支える技術1~5章

次 

HTTPの概要

HTTPはTCP/IPをベースにしている。 TCP(Transmission Control Protocol) IP(Internet Protocol) 現在のHTTPはバージョン1.1が主流として使われており、10年以上更新されていない。 現代の開発スタイルでは、HTTP1.1を有効に使っていこうという流れになっている。^1 ネットワーク・プロトコルは階層毎にわかれている。

各階層は次のようになっている。

  • ネットワークインターフェース層
  • インターネット層
    • IPを使ってパケット単位でネットワークで実際にやり取りする部分
      • この時、最終的にたどり着くかは保証していない
    • IP
  • トランスポート層
    • IPでのデータ転送の届け先を保証する部分
      • ここで初めて相手に対してコネクションを張る
    • UDPTCP
      • どちらも通信用の標準規格
      • UDPは、届いているかどうかを確認せず、データを送りっぱなしにする。信頼性は低いが転送効率が高く遅延しにくい。
      • TCPは、再送制御やデータ欠落の検知など信頼性を確保する仕組みが整っているため、転送効率より確実性が高い
    • ポートを利用するが、1〜65535の数値
  • アプリケーション層
    • 実際のメールやHTTPを実現する部分
    • TCPでプログラムを作る時は、ソケットを使うのが一般的
    • HTTP、NTP、SSHSMTPDNS

階層にすることの特徴は

  • 抽象度別に分けることが出来る
    • ネットワークインターフェース層のほうが抽象度が低い
  • 各階層の実装が独立している
    • 下位層の実装に依存しない
    • 障害発生時などの問題を各層毎に区切ることが出来る

HTTPの仕組みについて

HTTPはアーキテクチャスタイルに クライアント/サーバ を採用している。 クライアント(Webブラウザ)が情報を提供するサーバ(Webサーバ)に接続し、各種リクエストを出してレスポンスを受け取る。 このようなプロトコルリクエスト/レスポンス型(Request-Response Style) と呼ぶ。

クライアント/サーバそれぞれの役割

クライアントでは、リクエストの送信から受信する際、次のことを行う。

  1. リクエストメッセージの構築
  2. リクエストメッセージの送信
  3. (レスポンスが返るまで待機)
  4. レスポンスメッセージの受信
  5. レスポンスメッセージの解析
  6. クライアントの目的を達成するために必要な処理
    • ブラウザであれば、HTMLのレンダリング処理
    • 検索エンジン用にデータを集めるロボットプログラムであれば、HTMLの解析結果をDBに格納する処理

次に、サーバでは次のことを行う

  1. (リクエストの待機)
  2. リクエストメッセージの受信
  3. リクエストメッセージの解析
  4. 適切なアプリケーション・プログラムへの処理の委譲
    • DBから最新記事を取得処理
    • 広告へのリンク作成処理
  5. アプリケーション・プログラムから結果を取得
  6. レスポンスメッセージの構築
  7. レスポンスメッセージの送信

HTTPメッセージ

先述した、リクエストメッセージとレスポンスメッセージはまとめて、 HTTPメッセージ と呼ぶ。

リクエストメッセージの構造

リクエストメッセージの構造は以下の図のようになっている。 名称未設定 2.001.jpeg

リクエスト行のURIには、http://example.jp:8080/search?q=test&debug=true#n10のようなURIフラグメントは、リクエストメッセージには含めない。この場合のリクエスト行は、URIフラグメントを除いた、パス以降の文字列が入る。具体的には/search?q=test&debug=trueが入る。

また、リクエストURIは基本絶対URIでも相対URIでも使用出来る。^2 しかし、プロキシへのリクエストの場合必ず 絶対URI となる。

レスポンスメッセージの構造

レスポンスメッセージの構造は以下のずのようになっている。 名称未設定 2.002.jpeg

参考:ネットワークエンジニアとして TCP/IP - HTTP

HTTPのステートレス性

HTTPはステートレスなプロトコルとして設計されている。 これは、サーバがアプリケーション状態を保存しないということである。

アプリケーション状態とは?

アプリケーション状態は、別名セッション状態とも言う。 システムにログインしてから、ログアウトするまでの一連の操作間の状態をアプリケーション状態と呼ぶ。

もしステートフルなプロトコルだと、アプリケーション毎のやり取りをサーバが記憶する必要がある。 反対にステートレスなプロトコルだと、アプリケーション自身でやり取りを全て記憶する必要がある。

それぞれの概要は次のようになる。

  • やり取りについて
    • ステートフル:簡潔(サーバが記憶しているから)である。
    • ステートレス:冗長(今までの状態を話す必要があるから)である。
  • 利点
    • ステートフル:送信するデータ量が少なくて済む。
    • ステートレス:クライアント数が増えた際にシステムをスケールさせるのが楽になる。
  • 欠点
    • ステートフル:クライアント数が増えると、サーバが記憶しなければならないデータ量が増えるため負担が増える。
    • ステートレス:送信データ量が増える。認証など、サーバに負担がかかる処理を繰り返す。通信エラーの際にリクエストが処理出来ているか分からない。

Webを支える技術を研修で読んでる まとめ1

輪講形式で読んでいて、気になった点をまとめておく

第1部:Webの概要

  • RPC
    • 分散システムを実現するための技術の1つ
  • 分散システムの流れが来たが、複雑さの問題から発展しなかった
  • Webはシンプルな単方向リンクだけを持つものとして開発
  • SOAP
    • メッセージ転送の方法だけを定めたプロトコル
    • 標準化戦争勃発
  • REST
  • リソース
    • リソースとはWeb上の情報
    • 世界中の無数のリソースは、それぞれURIで一意の名前を持つ
    • URIを用いることで、プログラムはリソースが表現する情報にアクセス出来る
  • RESTなアーキテクチャのために
    • クライアント/サーバ
      • ユーザインターフェースと処理を分離する
    • ステートレスサーバ
      • クライアントのアプリケーション状態をサーバで管理しない
      • ステートフルな場合、Cookieを使ったセッション管理をしている
        • REST的には間違い
    • キャッシュ
      • 一度取得したリソースをクライアント側で使い回す
        • 効率化はできるが、情報の信頼性が下がる
    • 統一インターフェース
      • URIで指し示したリソースに対する操作を統一した限定的なインターフェースで行う
    • 階層化システム
      • サーバとクライアントの間にロードバランサを設置して負荷分散を行う
    • コードオンデマンド
      • ブラウザ以外にクライアント側を拡張出来る
      • プログラムをクライアントにダウンロードして実行する

第2部:URI

  • URIの仕様
    • railsのrouteファイルなどに関わってくるから、ここから大事!
  • URIスキーム
    • http://hogehoge.com
    • httpの部分がURIスキーム
  • URIフラグメント
    • hogehoge/member#user1
    • ページ内の#以下の文字列の要素を示す
  • URIの設計

第3部:HTTP(Hypertext Transfer Protocol)

  • HTTPの基本
    • 階層型プロトコル
      • p69参照
    • 同期型プロトコル(レスポンスを待つ)
    • HTTPメッセージ
      • ヘッダとボディーに分かれている

アメリカの中学生を対象にワークショップやってみて感じた日本との違い

留学6週目の最終週の記録です。

今週はSunnyvaleの中学校でロボットでサッカーを行うロボット教室をやりました。
f:id:pokotyamu:20150914085104j:plain
ロボットはDAISEN社製のTJ3Bという既成品を使用して
それの組み立て→プログラム作成という流れで行いました。daisen-netstore.com
ロボットはC言語を用いたプログラムに従って動くのですが、
実際に子供たちが作成する時はC-styleというビジュアルプログラミングソフトを使用して行います。*1
f:id:pokotyamu:20150916084728p:plain

今回はその中で私が感じた日本の子供たちとの違いについてまとめていきたいと思います。

1.子供の自発性に任せる


【日本の場合】

進研ゼミの告知の仕方が日本の教育の全てを物語ってるのではないでしょうか?
「この夏休みで短所を長所に変えよう!!!」
つまりは、日本の教育では、短所をなるべく消して平均的に取れるように指導を進めていく風潮が強いということです。
この教育方針には、

メリット
・クラス全体が同じ進捗で進めやすい
・なんでもそれなりにこなせる人間を増やせる
デメリット
・尖った人間が育ちにくい
・一度ついていけなくなると落ちこぼれる可能性が高い

というメリット・デメリットがあると考えました。
高校生のときに、中学後半の英語や数学を授業レベルでやり直すのは難しいのは容易に想像が出来るかと思います。
自分からというより、受動的にしか受けようがないというのが今の教育の限界なのかもしれません。
そして、平均的に出来るだろうという気持ちから、
失敗するのが怖いという思考になってしまうのかなと思います。

【アメリカの場合】

ロボット教室をやってて思ったのは
自分達が用意したスライドの2歩ぐらい先を勝手に自分で考えて進めていたことです。
最後には、お互いに分からないとこを教え合って授業と言っても後ろからサポートしてあげるだけ、という時間が多かったです。

こっちの子供たちの好奇心は、実際に形にするまで止まりません。
トライ・アンド・エラーで勉強できることを彼らは知っているのです。

では、もしこの時日本式に
「みんなで一緒に進めるからちょっと待ってて。」
と言って彼らのやる気を止めたらどうなるか?

答えは、全く関係ないことをやり始めて、その後ロボットには目もくれなくなります。
それだけこっちの子供は自発的に興味を持ったものには全力で突き進みますが、
上から押し付けたり指示すると興味をモチベーションが下がってしまう文化が、ここにはあると感じました。

さらにもう1つ
アメリカの学校では、単位毎に飛び級が認められています。
やってることが幼稚なら先に進む。
分からないで進むなら、理解するまで止まる。

このような教育を受けることが出来ます。

2.何事にもアグレッシブ


【日本の場合】

日本の授業風景を思い出してください。

先生「質問ある人ー?」
生徒「・・・・・・」
先生「はい、次進みますー」

これは、よくある日本の教室の光景だと思います。

全員の前で質問することに対して恥ずかしさや、授業を止めてしまうのでは?という申し訳無さ
そんな空気感からなかなか手を挙げるのは簡単ではないことは、私も当時感じていました。

いわゆる、日本人はシャイだねってやつですね。

【アメリカの場合】

もし、自分の分からない点が出てきたら
「これはどうなってるの?」
「どうして動かないの?」
こんな質問をひたすら連呼してきます。

この連呼するというのがポイントで、自分が分からないポイントは
とことん理解するまで知りたいという欲求が、彼らには働いているように感じました。
だからこそ、自分の理解している範囲内ではドンドン進めていきたいのでしょう。

特に今回の授業では、自分がプログラムを書く→ロボットが実際に動くことで確認出来る。
このサイクルで開発を進めていけたので、早くもっと高度なことがしたいという気持ちに駆られたように感じます。

3.意見の伝え方と納得の仕方


【日本の場合】

小学校、中学校で何か決め事をするときに一番使われるもの
そう「多数決」ですね。
多くの日本人が多数決で決まったなら、自分が納得せずとも受け入れてしまう
そんな経験はありませんか?

現在の大人が受けた教育で、多くの人が議論を行う経験が少なかったように感じます。
自分の意見を主張するより周りに合わせる。
5段階評価アンケート形式で真ん中が多かったりする。

自分の意見を意地でもねじ込もうとする方法が確立されてないため
どうしても感情的に突き進む連中が、最近よく国会前で騒いでいたりするのかなと。
教育されてないから、あんな滑稽な演説しか出来ないのだろうとまとめながら感じました。

デモ自体やることはいいのですが、もう少しロジカルに演説すればいいのに、
戦争法案!」「徴兵制にはさせない!」「安倍下ろし!」
これしか言わないデモに何の意味があるのか。

【アメリカの場合】

ロボット教室の場面でこのようなことがありました。
今回のサッカーの試合では、白い枠からはみ出したら1分間退場扱いというルールがあります。
試合時間は5分なので、そのうちの1分とはかなり大きいペナルティと感じたのでしょう。
1人の子供が「30秒に変更してよ!!!」
これを10回以上審判である私達に訴えてきました。
確かに、彼のロボットは何回も場外に進んでいました。
これに対して「それは出来ない」という回答を私達は繰り返しました。

教室が終わった後の反省で言われたのは

・"Just rule!!”と突っ張る
・なぜ30秒に変更してはダメなのかの理由を伝えてあげる

この2つでした。
まず1つ目は、自分達が試合をしている彼らより圧倒的に上の位置で判断していると伝えてあげることで
変な申請をこれ以上させないという効果があります。
これをしないと、今回のようにナメられて、自分の意見をねじ込めようとしてきます。
そして2つ目は、ロジカルに納得するとそれ以上自分の意見を訴えても無駄だと本人が一番わかっているということからです。
実際、今回1分と設定した理由としては、授業の中で最低限フィールドから出ないようなプログラムを組むようにという指示をしていたので
かなり重いペナルティとなっていました。
それを伝えることが出来れば、彼も納得して試合をすることが出来ただろうなと今になって思っています。


まとめ

以上の3点について最後にまとめると
日本人の教育の場合

・短所を直して全体を平均的にする
・疑問があっても蓋をして進める
・反対の意見を述べることが悪いことという空気感がある

アメリカ人の教育の場合

・長所をひたすら伸ばし続ける
・自分だけでは分からない疑問は即解決する
・自分の意見をロジカルに否定することでのみ納得する

今回は特にアメリカの子供たちのメリットの部分を強調して記事を書いてみました。
もちろん、デメリットも考えたらあると思います。
けど、それはアメリカ社会と日本社会の違いだと思っていて、
アメリカでは個の特徴的な人の集合体で会社が動いている。
日本では、平均的な力でベースとなる底力を上げることで会社が動いている。
まぁ最近は日本でもITベンチャーはアメリカナイズされた考え方を持ってる会社も多いかと思います。
そこで、自分が働く場合は、自分の価値観(スキルセットの揃え方)もアメリカナイズさせる必要があるのかと感じました。

参考資料
日本とアメリカの学校の違い - NAVER まとめ

*1:ビジュアルプログラミングといえば、scrachやsmalrubyが有名ですね