* JavaScriptプログラマのための
全方位的完全武装ガイド

ma.la ---- 高度なWebアプリケーション開発にはもちろん、スマートフォンやPC向けのネイティブアプリやサーバーサイドでの利用など、JavaScriptの利用シーンが広がっている一方で、良いJavaScriptプログラマは浮気性であり他の言語を学ぶことを好みます。主にブラウザ上でのUI開発を軸にJavaScriptを学んだ発表者が、JavaScriptの経験が異なる言語、異なる分野でどのように役に立つのか、他の言語で学んだ知識がどのようにJavaScript開発に役に立つのかを語ります。 ---- ** テーマ - 自己紹介・UIエンジニアとは何か - 必修科目としてのJavaScript - 非同期処理・分散処理のアーキテクチャ - これから先JavaScriptで出来ることは何か ---- - 1. 自己紹介 ---- ** 自己紹介 - ma.la ---- - ホムっペ - http://ma.la/ ---- - twitter @bulkneets - #followmejp ---- ** 肩書き - livedoor - UIスペシャリスト ---- ** 個人的な肩書き - 最速インターフェース研究会 - 主任研究員 ---- ** 肩書き重要 - 自分に対するプレッシャー - そのようにあろうとする意志 ---- ** livedoor - 主にJavaScriptが書ける人として入社 - 色々あって退社 / 京都旅行 - 再び入社 ---- ** 何やってる人か - 一般的にはプログラマ - Webアプリケーションエンジニア - livedoor Readerとか作ってます ---- ** 仕事 - JavaScript / Perl - UI設計と実装 - 負荷分散・高速化 - API設計 - 自社サービスのセキュリティ監査 - etc ---- ** 自分の考えるUIエンジニア - エンジニアの視点でUIデザインが出来る人 - プログラマとデザイナーの中間 - どちらかというとプログラマ寄り ---- ** 今の自分 - 必要であればクローラ書いたり - MySQLチューニングしたり - メッセージキューサーバー書いたり ---- ** 反省 - ずいぶん色々やってきました - orz ---- ** 何でも屋 vs 専門家 - 「何でも屋」としてのUIエンジニア - プログラミングもできるしデザインも出来る ---- ** 何でも屋 vs 専門家 - 「何が出来るのか」を知らないと良いデザインが出来ない ---- ** なんでも出来るメリット - 異なるレイヤーの知識が生かせる ---- ** デメリット - 器用貧乏になりがち - ほんとはやりたくない仕事振られる - 例: 障害対応 ---- ** プログラマとデザイナの境界線 - 狭義のデザインとは - 見た目? 色合い? 雰囲気? ---- ** 広義のデザイン - Webサービスにおけるデザイン - サービスの企画自体 - DBスキーマ設計 - 必要なもの全て ---- ** なぜUIエンジニアなのか - CPUやネットワークの高速化に対して - 人間に対する最適化が不十分 ---- ** なぜUIエンジニアなのか - 最も効率の良い箇所を「チューニング」する - HotSpotの最適化 ---- ** クライアント側の最適化 - livedoor Reader - クライアントサイドでの検索 - 画面遷移なしでの継ぎ足しスクロール - Google AutoPager (Autopagerize, AutoPatchworkの原型) ---- ** クライアント側の最適化 - キーボードショートカット - 先読み Prefetch - etc. ---- ** 直接・間接的な影響 - 良いUIは競争力になる - 良いUIは伝搬する - 良いUIは真似される ---- ** ジレンマ - 良いUIが普及しなければならない - UIが競争力ではなくなることが理想 - 自分の価値を落とすために働く ---- ** プログラマの宿命 - 機械にできることは機械にやらせる - 最終的に自分の仕事が無くなっても良しとする覚悟 ---- ** 2005年 - Ajax - サーバーサイド / クライアントサイドの密な連携 ---- ** なんで今まで出て来なかったの? - ブラウザの進化? - Googleがやりはじめたから? ---- ** やろうと思えば色々できた - CGIでJavaScriptのコード動的に作ったり - iframeを使った差分ロード - scriptタグの逐次出力によるストリーミング ---- ** 境界線に立つ - 今でこそ概念が理解されているが - サーバーサイド / クライアントサイド - 両方の面倒を見れないと作れない ---- ** 境界線に立つ - イメージ: -- コウモリ・天邪鬼・トリックスター・キメラ - 一人で何でもやる / 出来るようなひと - 自宅サーバーで一人でWebサービス作るような人 ---- ** どんな人が向いているのか - 友達がいないひと - 一人で何でも出来るようになる!! ---- ** 2011年 - JavaScriptの高速化 - 同じ領域のエンジニアが増えた -- フロントエンドエンジニア ---- ** フロントエンドエンジニア - 彼らはキメラですか? -- もしかして: jQueryエンジニア - 彼らは孤独ですか? -- もしかして: リア充 ---- ** フロントエンドエンジニア - もしJavaScriptしか書けないのなら - 良いデザインのためにサーバーサイドの知識も必要 - 何が出来るのかを知るために ---- ** 最近思うこと - ボトルネックはどこに? ---- ** 昔 - ボトルネックはクライアントサイドだ!! - もっとこの領域に人が来ないと駄目だ!! - ちまちまチューニングしててアホか!!!! ---- ** 今 - 全部遅い!! ---- ** 今 - 全部やらねーと駄目だな ---- ** というと - あまり現実的ではないですが - あらゆるレイヤにボトルネックの存在 ---- ** 昔 - JavaScriptしか書けない - 出来ることをやるしかない - Perlは10年前レベルだった ---- ** 全部ボトルネック - ハードウェア? - 言語? - アルゴリズム? - データベース? - 開発速度? - セキュリティ? ---- ** どこに身を置くか - 複数のレイヤーを理解した上で - 自分が得意なことをやる - 楽しいと思うことをやる - 必要とされることをやる - 他の人にできないことをやる ---- ** 全方位とは - どうせならオール5を目指す - 異なる分野の知識は無駄にならない - 今まで見えなかったものが見えてくる ---- - 自己紹介終わり ---- - 2. 必修教科としてのJavaScript ---- ** とりあえず覚えておけという言語 - 昔: C ? - 今: JavaScript ---- ** プログラミング遍歴 - 大体10歳の頃からプログラミングを始める - N88-BASIC → Perl + JavaScript ---- ** なつかしのBASIC - その場で書いて、その場で実行 - 実行途中で書き換えて、再開 ---- ** 原始的プログラミング体験 - Try and Error - インタプリタ言語脳 - 人のソースいじれるのが当たり前 ---- ** Webへの傾倒 - 低レイヤーに没頭する人 -- バイナリアン・コンピューターサイエンス - 高レイヤーに行く人 -- CGI・Perl・PHP / お手軽プログラミング ---- ** どこに身を置くのか - ちゃんと勉強してこなかったコンプレックス - 低レイヤーには低レイヤーの - 高レイヤーには高レイヤーの ---- ** 今プログラミングを始める人に - JavaScriptをすすめる理由 ---- ** メリット - 大抵の環境で最初から入ってる - ネイティブアプリでも何かとHTML + CSS + JavaScriptは使われる - 日常の手頃なハックに - ブラウザの拡張機能やuserscripts ---- ** 何でもJavaScriptで出来る? - できることが増えるようになった - ネイティブアプリ開発 ---- ** WebアプリケーションにおけるJavaScript - 昔: 第二の言語としてのJavaScript - 今: 必修言語としてのJavaScript ---- ** JavaScriptライブラリ - 手馴れた言語に似せた設計 - Prototype.js / Ruby, Rails - MochiKit / Python - dojo / JAVA ? ---- ** JavaScript - prototypeベースのオブジェクト指向 - 標準的な書き方は有る ---- ** にもかかわらず - 著名JSライブラリの多くは - 「JavaScriptを俺好みにする」実験 ---- ** jQueryの普及 - jQuery / JavaScriptらしい? - もはや独自の言語とも言える ---- ** サーバーサイドjs - クライアントサイドとのノウハウの共有 - メリット「覚える言語が一つで済む」 ---- ** サーバーサイドjs - デメリット「覚える言語が一つで済む」 ---- ** フロントエンド → バックエンド - Ajax / XMLHttpRequest - イベント駆動 / 状態遷移の管理 - JavaScriptの経験がクローラ開発に役に立ったり - サーバーサイドでの非同期I/Oの活用 ---- ** 良いJavaScriptプログラマは - イベント駆動スタイルのコードに親しみがある - 無名関数を平然と使う - クロージャ、高階関数の概念を自然に身につける ---- ** JavaScriptを学ぶこと - お手軽 なのに 奥が深い - 異なる言語から得られる知見 ---- ** 第二言語 - Perl / Ruby / PHP / Python ? - Lisp / Haskell / Erlang / Go ? ---- ** JavaScriptで他の言語を学ぶ - 2005年 関数型言語への傾倒 - beyond.js 奇妙なライブラリ ---- ** 浮気相手としてのJavaScript - 浮気相手ゆえ俺好みに調教されたJavaScriptが - 大量に存在 - JavaScriptを通じて他言語のエッセンスを学べる ---- ** プログラマの成長促進剤 - もちろんJavaScript以外も覚えたほうがいいけど - JavaScriptの(キモい)ライブラリを読むだけでも - 他の言語の勉強になる ---- - 必修科目としてのJavaScript - 終わり ---- - 閑話休題・セキュリティ的なことの話 ---- ** セキュリティ的なことの話 - WebアプリケーションエンジニアがJavaScriptを学ぶ必要性 - JavaScriptに起因するセキュリティホール - キリがないのでざっくりと ---- ** よくある脆弱性 - JAVAでJavaScriptのコードを生成 - PerlでJavaScriptのコードを生成 - PHPでJavaScriptのコードを生成 - JavaScriptでJavaScriptのコードを生成 ---- - これがメタプログラミングか ・・・ ---- ** JavaScriptのコードを動的に作る - オススメしない!! でもみんなやってしまう - みんな間違える - 他言語に関する知識不足が要因の一つ ---- ** JavaScriptのコードを動的に作る - JavaScriptをちゃんと理解してないと - 間違える → 危険 ---- ** JavaScriptのデータだけ出力する - じゃあJSONにしましょう - JSONの中に </script>が入ってると - scriptタグ閉じちゃう!! ---- ** JavaScriptのデータだけ出力する 2 - じゃあscriptタグの中に書くのやめましょう!! - → jsonを出力するだけのAPI ---- - URLに ?.html って付けたらIE6がHTMLとして勘違い・・・ - → XSS ---- - ---- ** 複数言語の混在が当たり前 - Webアプリケーションの常 - HTML + CSS + JavaScript - 異なるコンテクストで解釈される可能性 ---- ** Webアプリケーションを安全にするには - とにかく広範な知識が必要 - 覚えておかないといけないことが多すぎる ---- ** 最低限覚えて欲しいこと - js動的生成するな - 10年速い ---- ** ソニーの事例 - store.playstation.comのXSS見つける → Twitterに書く - たまたま同じタイミングで海外ニュースサイトに取り上げられていたのを知る - 緊急メンテ + XSS直して再開 ---- ** ソニーの事例 - onclick="location.href='[query parameter]'" - 指摘されたパターンのみ修正してる - JavaScriptに詳しい人であれば、抜け穴がある状態 -- バックスラッシュ通る ---- ** そして - まだ直ってないと書く - → 関連会社の人からコンタクトが来る - 再びメンテ突入 - お礼を言われる ---- ** その後どうなったか? - まだメンテ中 ---- - 俺のせいみたいで気分よくない・・・ ---- - なんか悪いことしましたね・・・ ---- ** Evernoteの事例 - JavaScript動的生成によるXSS - 直したよ → 直ってない ---- ** Evernoteの事例 - 日本人で使ってる人、そんなにいねーだろと思ってたら結構使ってる人いた・・・ - たまたま来日してたCEOに呼び出される - 刺身 ---- ** Evernoteの事例 - 「直りました、もう安全です」と勝手に広報する人 - 実際のところ、その後も3,4回ぐらい継続的にXSS報告 - ※よくあることです ---- ** Evernoteの事例 - 1匹いたら10匹はいると思ったほうが - 美味しい刺身が悪用される可能性を減らす ---- ** LastPassの事例 - データベース漏洩したタイミングで色々調査 - ただしハッシュ化されたパスワード - PHPでJavaScript動的生成 - JSONのcontent-typeがtext/html => HTML混入 ---- ** はてなの事例 - はてなカラースター(個人的に) - 飯おごってくれるって ---- ** みんな使ってても大丈夫とは限らない - 見えてる人には見えている穴 - 実装方法自体にリスクがあるケース - ユーザーが増える → 一度出したら直せない ---- ** 修正困難なケース - 例えば - iframe埋め込み前提のコンテンツ + クリックジャッキング - ブログパーツ(第三者提供のスクリプト実行) ---- ** 直せばいいだけ? - 既に普及してる機能とのトレードオフ - 初期にリスクを評価できていれば・・・ - ブラウザの仕様や、JavaScriptについての知識が必要 ---- ** 今なんのためにJavaScriptを使うのか - クライアントサイド技術を使った高速化 - クライアントサイド技術を使った暗号化 ---- ** Evernoteの場合 - インライン暗号化 - クライアントサイドのJavaScriptで復元 ---- ** クライアントサイドでの暗号化 - LastPassのパスワード - Evernoteのパスフレーズ - JavaScriptが使える前提であれば可能 -- サーバーサイドではパスワードを一切知らない、という実装 ---- ** クロスドメイン・メッセージパッシング - ローカルストレージ - サーバーを介さない通信が可能 ---- ** 昔 - IE独自仕様: UserData - サーバーに送られないCookieみたいなもん - location.hash - URLの#以降の部分 ---- ** 今 - HTML5による標準化 - localStorage, postMessage - サーバーにデータを送らないで実装する - バッドノウハウ必要なし ---- ** UIの改善だけではない - JavaScriptで出来ること・すべきこと - サーバーでできないことをやる - サーバーが信頼できない前提でのAPI設計 ---- ** これから必要とされるポリシー - バグがあっても安全にするアプローチ - Sandbox ---- ** これから必要とされるポリシー - Don't be evil -- 我々を信用して - よりも - If we are evil -- 悪意があっても、あなたのデータは安全 ---- ** ぶっちゃけ - インターネットそんな安全じゃないですよ ---- - セキュリティの話2 - ライブラリレベルでの問題 ---- ** ライブラリや拡張機能に問題があるケース - jQuery / jQuery Mobile - 不適切な設計 / 何回かに分けて書いた - http://subtech.g.hatena.ne.jp/mala/ ---- ** 大事なこと - サーバーサイドでこういうコードあったらマズイでしょ? - といったことが - クライアント側では平然と行われている ---- ** 例えばJSONP - JSON with Padding - コールバック関数を指定したJSONデータ - 外部URLから取ってきたjavascriptを実行 ---- ** 例えばJSONP - サーバーサイドでこういうコードあったらマズイ - eval( fetch_url( http://... ) ) - ブラウザ上では平然と行われている ---- ** jQuery - CSSセレクタだと思ったらHTML要素作成 - http://ma.la/jquery_xss/ - → 任意のJavaScript実行 - jQuery 1.6.3で修正予定 ---- ** jQuery - 仕様じゃね → 驚き最小の原則に反する ---- ** UI設計 | API設計に共通の哲学 - フールプルーフとか - フェイルセーフとか - ユーザーが何も知らなくても安全にする - バグがあっても深刻なことが起きないようにする ---- ** jQuery Mobile - 外部ドメインのURLでも読み込んで表示可能だった - → 任意のJavaScript実行 - 修正されたけど。。 ---- ** 著名ライブラリの脆弱性 - 検証する人が少ない - 赤信号みんなでわたってみんな死ぬ ---- - セキュリティの話 - 終わり ---- - 3. Webアプリケーションのための - 並列・分散処理 - アーキテクチャ ---- ** JavaScriptから見たとき - サーバーサイドで非同期処理は余り普及してない - 特殊なケースだけ ---- ** サーバーサイドから見たとき - JavaScript シングルプロセス - 重い処理やらせるとブラウザごと固まるJavaScript -- UIスレッドの分離 | Web Workers ---- ** マルチプロセス - たくさんプロセス立ち上げる - 単純にFork ---- ** 協調スレッド - Perl / Coro - Ruby / Fiber + NeverBlock - 透過的なI/O多重化 イベント駆動の隠蔽 - コルーチンを利用した1プロセス内の軽量スレッド ---- ** メッセージパッシングによる分散処理 - アクターモデル Erlang, Scala - シェアードナッシング - CPUコア数に合わせて性能が向上する ---- ** メッセージパッシングによる分散処理 - 関数型言語 = 副作用がない - 「同じ関数」に「同じ引数」を渡せば同じ結果 -- ネットワーク越しの別のノードで動作してても関係ない - 分散処理の隠蔽が可能 ---- ** 「協調動作」か「分散」か - CPUのコア数が増加 - 今後も「シングルプロセス + イベント駆動」の利点はあるのか? ---- ** 複数の方式の組み合わせ - CPUコア数に比例した少数のワーカープロセス + イベント駆動 - Nginxとか ---- ** 複数の方式の組み合わせ - 重い処理だけ別プロセスにやらせる ---- ** 考慮すべき項目 - 必要な同時接続数 - 1リクエストあたりの処理時間 -- 処理時間が予想可能かどうか - 単位時間あたりのリクエスト数 ---- ** Webアプリケーション本体 - 1つのプロセス内で共有できるリソースの割合がキモ - 基本的には単純なマルチプロセスが楽 - 殆どの場合、複数リクエストにまたがった協調動作が必要ない - 共有リソースはデータベースやKVSにある ---- ** シングルプロセス + イベント駆動が適したアプリ - 複数リクエストにまたがって -「状態を共有すること」に強い意義があるケース - 共有する情報が - シリアライズが困難 / 巨大 / 排他制御が困難 - 普通のWebアプリケーションでは、あまりない ---- ** シングルプロセス + イベント駆動の問題点 - ブロッキング処理が入ると他のリクエストも処理できない - 全部非同期I/Oで - CPU使う処理は別プロセスに - 気を使うことが多い ---- ** じゃあ?使いどころは - AnyEvent / Coro / Node.js etc - 目的特化のサーバー / ミドルウェア ---- ** シングルプロセス + イベント駆動のメリット - 今まで出来なかったことが出来る - 黒魔術 / 継続 in Web Application ---- ** Perlの場合 - AnyEvent / Coro の補完関係 - AnyEvent イベントループの抽象化 - Coro コルーチンの実装 ---- ** AnyEvent → Coro - AE: イベント駆動 / コールバックスタイル - Coro: 従来の手続き型スタイル ---- ** AnyEvent - AE::timer 0, 1, sub { ... } - 発生するイベントに対する関数を記述 ---- ** Coro - async で囲むだけ - async { Coro::Timer::sleep 1; ... } - 内部的にはAnyEventを多用 - sleepやI/O waitが発生するタイミングで自動的にyield ---- ** AnyEvent → Coro - コーディングスタイルの変化をもたらす ---- ** JavaScriptの場合 - 最初からcallbackスタイルのイベント駆動に慣れている - setTimeout(func, 1000) - sleep 1000って書きたいか ---- ** JavaScriptの場合 - 言語自体に手を入れないと無理 - DSL? CoffeeScript ---- ** JavaScriptの場合 - 遅延評価によるcallbackの直列化 - Deffered, Promise - 内容が未確定のままオブジェクトを引き回す ---- ** サーバーサイドjs - 使ってる? - あんまり・・・ - Perlでもできるので ---- ** サーバーサイドjsの今後 - コールバック地獄 -- 慣れてるで解決? - シングルプロセス + イベント駆動 -- マルチコア時代にどうする? ---- ** シンクロニティ / 共時性 - どの言語でも通る道 - みんな似たようなことを考えている - 他の言語から学ぶ - JS独自の事情: 慣れてる ---- ** 美しいアーキテクチャはどこに? - 意識しないで使える 非同期I/O や 分散処理 - そこらへんはディスカッションで ---- - 並列・分散処理アーキテクチャの話 - 終わり ---- - まとめとか ---- ** 最適なアーキテクチャの選択とは - やり方はたくさんある - 「選択肢」を増やそう - 「最適解」を選ぼう ---- ** マルチコア時代の並列処理、分散処理アーキテクチャ - コア数が増加、マルチコア、メニーコア - シングルプロセス内での協調動作を取るか - 複数サーバーにまたがった分散処理を取るか - アプリケーションの性質によって最適解が異なる ---- ** 協調動作や分散処理を透過的に行う - 他の言語やライブラリに学ぶ - 今まで出来なかったことを出来るように ---- ** 異なる言語を行き来する - 複数の言語を行き来しないと - 安全なコードや - いい感じのAPIが書けない ---- ** UIエンジニア的視点 - クライアントサイドでしかできないことの積極活用 - ユーザーのブラウザですら「使えるCPUの一つ」 - ブラウザが分散コンピューティングのノードの一つ ---- ** 良いUI / 速いUI - まだ充分じゃない - まだまだ競争力になる - 競争力にならなくなるまで ---- ** クライアントサイドへのシフト - 強大なサーバーリソースを持たなくても戦える -- クラウドもいいけど - 巨大企業による独占やロックインからの回避 - 世の中をハックしやすいように保つ ---- ** 以上 - ご清聴ありがとうございました ---- ** 宣伝 - livedoorでは - エンジニア - デザイナー - 募集しています