Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

FIRST STEP to Haxe/JavaScript

11,823 views

Published on

  • Be the first to comment

FIRST STEP to Haxe/JavaScript

  1. 1. 目次 • 自己紹介 • Haxeとは • なぜJavaScriptコードを生成したいのか • Haxeと他のJavaScript生成言語 • Haxe/JavaScriptの開発環境 • Hello World • 基本的な構文・構造 • JavaScriptとの連携 • Haxeならではの機能・構文 • まとめ
  2. 2. 得意な技術領域 • ギョーム系DataGridの実装に定評があります。 • JavaScriptで2回 • Haxe/JavaScriptで1回 • Silverlightで1回 • ここ数年はクライアントサイド開発が中心。 • でもシステムアーキテクチャ設計がたぶん本業。 • キーワード Windows 8, .NET, WinRT, MSIL, F#, JavaScript, Haxe, TypeScript, Android, 分散システム, Cassandra, …
  3. 3. Haxeと私 • Haxe歴は1年ほど。 • わりと大きなプロジェクトにHaxeを投入。 • 大規模なギョームシステムにHaxeを採用してみた話 http://www.slideshare.net/terurou/haxe-15006171 • はてブ 200超え • でもこのスライド、発表当日に実質2時間ぐらいで 書き上げたヤツなんだよね… • 今も開発継続中、Haxe部分だけで5-6万行程度。 • Pure JavaScriptで書いている部分も数万行規模。 • サーバサイドも数万から10万程度はあるはず。
  4. 4. Haxeとは • JavaScriptコードを生成することができる プログラミング言語 • C#やJavaに似た「慣れ親しんだ」構文 • 詳細な説明は後ほど • この資料ではHaxe 3.0を前提に解説を行う
  5. 5. なぜJavaScriptを生成したいのか JavaScriptで開発するのが しんどい
  6. 6. なぜJavaScriptで開発はしんどいのか • 生産性・品質とメンテナンス性が両立しにくい。 • チーム開発しづらい。 • 学習コストが高い。
  7. 7. 原因1: JavaScriptの言語仕様が良くない • モジュールシステムが存在しない。 • ライブラリや実行環境(ブラウザ、Node.jsなど)に よって書き方が大きく変わる。 • prototypeベースオブジェクト指向を筆頭にして、 言語仕様が柔らかすぎる。 • 初心者がprototypeチェーンを覚えることが大変 • 「classのようなもの」の書き方がたくさんある。 • グローバルオブジェクトのprototype上書き問題 • グローバル汚染+varの付け忘れバグ • strictモードを使えばある程度マシになるが…。
  8. 8. 原因2: JavaScript界隈の文化が良くない • 他の言語から見るとバッドノウハウに近いような コーディングテクニックが氾濫している。 • 即時関数でスコープを限定化 • オブジェクトのnull判定 • 「単独varパターン」ってみんな使っている? • そのほか色々… • コーディングテクニックの流行り廃りが激しい。
  9. 9. JavaScripterほこたて • テクニックを駆使しないと書くのがしんどい。 • JavaScriptの言語仕様上、仕方がない。 • テクニックを駆使しすぎると他人が読めない。 • スキル・好み・ライブラリ・実装時期などによって コードの差異が激しくなりすぎる。 • チーム開発や保守でオーバーヘッドが大きくなる。 • チームメンバを教育しても次に生かせる保障がない。
  10. 10. JavaScriptは大変ですね 素直にあきらめて JavaScriptは生成しましょう。
  11. 11. JavaScriptコードを生成するプログラミング言語 2013年6月時点で現実的な選択肢 • Haxe • TypeScript • CoffeeScript 他にもjs_of_ocaml、Dart、JSXなどがあるが、 ユーザ数やとりまく環境を考えると選択しづらい。
  12. 12. Haxe • 慣れ親しんだ構文+高度な型システム • 基本構文はC#やJavaに似ている。 • 多少冗長ではあるが、万人に読みやすい。 • OCaml由来の型システム • 型推論、代数的データ型、パターンマッチなど • 簡潔に型安全なコードを書ける。 • マルチプラットフォーム • JavaScript以外の様々な言語・環境に出力可能。 • コンパイルが超速い • 歴史が長く(2005年~)、安定している
  13. 13. TypeScript • JavaScriptの構文拡張 • 静的型付け+型推論、クラス、モジュールなど • 型システムはHaxeほど高度ではないが、モダンな 言語としては最低限の機能は備えている。 • 将来的には一番人気になりそう • Microsoftが本気で開発・プロモーションしている。 • まだまだ安定していない • 2012年10月公開。 • 2013年6月にver 0.9.0 alphaが出たばかり。 • 1.0以後もAsync/Awaitなどの、インパクトの大きい 仕様追加が予定されている。
  14. 14. CoffeeScript • 軽量構文に特化 • JavaScriptと比較してコード量が1/3程度削減できる • Rubyの影響が強い構文 • 記述しやすい反面、人によって書き方がばらつく。 • 動的型付け • 型安全なコードは書きづらい…。 • 安定しているが、先行きを心配する声もある • TypeScriptと直接競合しており、世間の流行は 静的型付け言語に向いてきている。 • とはいえ現在も開発が活発なので、数年は大丈夫?
  15. 15. Haxeを選択する理由 • 型安全な方が良い • 品質、メンテナンス性に直結する。 • どうせ事前コンパイルが必要なので、コンパイル時に できることが多い方が良い → Haxeが有利 • コーディングスタイルのばらつきを抑えたい • CoffeeScriptは練度の高いチームなら良いが…。 • 今すぐに使える • TypeScriptは1.0まで待った方が無難。
  16. 16. 補足:型安全とは • 自分も詳しくないので引用でお茶を濁す https://twitter.com/camloeba/status/248734702062686208
  17. 17. 補足:型安全なコードを書くと… • UnitTestを簡素にできる • 型で表現/制限できることは、コンパイルが通れば バグがないことが保障される。 • Haxeの型システムで表現できることは多い。 • コンパイルすること自体がテストであるともいえる。 • UnitTestより確実 • コンパイラが静的に解釈(100%網羅) vs 全てのコードパスを通るテストコード • 人がテストを書く以上、テストケースにバグや漏れが 発生する可能性がある。
  18. 18. Haxeコンパイラ • Haxeプログラミングするためには必須。 • 現行バージョンは3.0(2013年6月時点) • インストール • Windows, Mac, Linux用バイナリを公式で配布。 http://haxe.org/download • インストール時に難しいことは特になし。
  19. 19. エディタ・IDE • おすすめ • Flash Develop(Windowsのみ) • Sublime Text(有償) + haxe-sublime-bundle • 実用レベルだが少し動作が重い • IntelliJ IDEA Ultimate(有償) + haXe plugin • FDT(Eclilseベース、フリー版と有償版がある) • 使ったことはないがイケてそう • Vim + vim-haxe • Vim + Vaxe • Emacs + haxe-mode
  20. 20. Flash Developのインストール • 公式ページ http://www.flashdevelop.org/ • インストーラの注意点 • .NET Framework 3.5が必要。 • Windows 8の場合は別途インストール fondue.exe /enable-feature:netfx3 • Java未インストールの場合、インストーラ起動時に 警告ダイアログが出るが、無視して構わない。 • Flex SDK, AIR SDK, Flash Playerは選択不要。
  21. 21. Flash Developのロケールを日本語に設定 • 日本語環境が良い場合は設定する。 • 後述の手順は日本語設定を前提にしている。 • 設定手順 • Tools→Program Settings • 右上のFilter settingに locale と入力 • Selected Localeを ja_JP に変更 • Flash Developを再起動
  22. 22. Sublime Text + haxe-sublime-bundle • Sublime Text • 公式ページ http://www.sublimetext.com/ • インストール時に難しいことは特になし。 • haxe-sublime-bundle • Sublime Package Controlからのインストールが楽。 • インストール方法と使い方 http://wbond.net/sublime_packages/package_control/installation • Package Controlで haxe と入力して選択するだけで パッケージがインストールされる。
  23. 23. ブラウザ(デバッグ環境) Haxeコードをそのままデバッグするには Source Mapsに対応したブラウザが必要 Chrome OK Internet Explorer 未対応(IE11でも×) Firefox v23で対応予定 Safari 未対応 Opera 未対応
  24. 24. ChromeでSource Mapsを有効にする • 設定方法(初期値は無効) • Developer Toolsを開く • menu→ツール→Developer Tools もしくは Ctrl+Shift+I • 右下の歯車アイコンをクリック • Generalタブ→Sources→Enable source maps
  25. 25. 基本的な流れ • プロジェクト(.hxmlファイル)の作成 • hxml = Haxe標準の簡易ビルドスクリプト • Flash Developの場合は、.hxmlファイルがなくても 開発できるが、他環境を考えると作成した方が良い。 • ここではFlash DevelopとSublime Textの手順を解説。 • プログラムを記述 • とりあえず alert() を表示するだけ。 • ビルド・実行 • ついでにデバッガを使ってみる。
  26. 26. プロジェクトの作成(Flash Develop)- 1 • Flash Developプロジェクトの作成 • menu→プロジェクト→新規プロジェクト • Haxe/JS Projectを選択して作成 • パッケージは未入力、その他は任意設定で可。
  27. 27. プロジェクトの作成(Flash Develop)- 2 • ビルド設定の変更 • menu→プロジェクト→プロジェクト設定 • 書き出しタブ→コンパイルターゲット • カスタムビルドに変更 • ビルドコマンドタブ →ビルド前に実行するコマンドライン $(CompilerPath)¥haxe.exe $(ProjectDir)¥build.hxml
  28. 28. プロジェクトの作成(Flash Develop)- 3 • ビルドスクリプトの作成 • プロジェクトルート直下にbuild.hxmlを作成 • bin/index.html の修正 • build.hxml-jsで設定したJavaScriptファイル名を 指定する。 –main Main -cp src -js bin/main.js -debug <script src="main.js"></script>
  29. 29. プロジェクトの作成(Sublime Text)- 1 • プロジェクトのディレクトリツリー • プロジェクトファイルの作成 • menu→Project→Save Project As ... • プロジェクトのルートディレクトリに保存 $project_root/ src/ bin/
  30. 30. プロジェクトの作成(Sublime Text)- 2 • プロジェクトファイルの編集 • menu→Project→Edit Project http://qiita.com/amay077/items/570beb096056d6f16f2a • folders.older_exclude_patterns は好みで追加。 { "folders": [ { "path":"." //, "folder_exclude_patterns": ["bin"] } ], "build_systems": [ { "name":"haxe", "working_dir":"${project_path:Default}", "cmd":["haxe", "build.hxml"] } ] }
  31. 31. プロジェクトの作成(Sublime Text)- 3 • ビルドスクリプトの作成 • プロジェクトルート直下にbuild.hxmlを作成 • bin/index.html を作成 • build.hxml -jsで設定したJavaScriptファイル名を 指定する。 -main Main -cp src -js bin/main.js -debug <!DOCTYPE html> <script src="main.js"></script>
  32. 32. プログラムを記述 • src/Main.hxを作成 • haxeでは { を行頭に置くことが多い(C#風) • Flash Develop、Sublime Text共にデフォルト設定 • 普通に行末に { 置くことも多いので好みで。 package; import js.Lib; class Main { static function main() { Lib.alert("hello"); } }
  33. 33. ビルド・実行 • ビルド • Flash Develop • menu→プロジェクト→プロジェクトをビルド • F8 • ツールバーの歯車アイコン • Sublime Text • Ctrl + B • 実行 • bin/index.htmlをブラウザで開く。 • alert()が表示されれば成功。
  34. 34. Chromeのデバッガの使い方 • Developer Toolsを開く • menu→ツール→Developer Tools or Ctrl+Shift+I • Sourcesタブの左上の をクリック • ソースツリーが表示されるので、breakpointを 仕掛けたい位置を設定 • ソースツリーペイン右上の をクリックすると ペインを開いたままにしておくことが可能。
  35. 35. スタートアップクラス(エントリーポイント) • プログラム起動時に最初に呼び出される部分 • build.hxml -mainで指定したクラスの static function main() メソッドが該当 -main Main -cp src -js bin/main.js -debug package; import js.Lib; class Main { static function main() { Lib.alert("hello"); } }
  36. 36. trace() • trace() = console.log() package; import js.Lib; class Main { static function main() { trace("hello"); } }
  37. 37. 変数の宣言 • var 変数名 : 型名; • var 変数名 : 型名 = 初期値; • 型推論により、var 変数名 = 初期値; でも可。 var foo : Int; foo = 1; foo = "abc"; //コンパイルエラー var foo : Int = 100; var foo = 100;
  38. 38. 基本型とリテラル • Haxeではnullはどんな型の変数にも代入できる。 • 型安全の考え方とは矛盾があるので注意。 • 実行環境が動的型付けなので仕方がない。 型名 リテラル Int 0, -123, 0xFF00 Float 123.0, .456, 12e-5 Bool true, false String "abc", "hello,¥nworld", 'hello "world"' EReg(正規表現) ~/[a-z]+/i null
  39. 39. 文字列リテラルの注意点 • シングルクォーテーションは変数展開を行う。 • いわゆるフォーマット文字列 • ダブルクォーテーションでは変数展開しない。 var foo = 123; trace('foo'); trace('foo = $foo'); trace('foo = ${foo * 100}');
  40. 40. 配列と匿名オブジェクト • 配列はJavaScriptとほぼ同じ • 匿名オブジェクトもJavaScriptとほぼ同じ var foo = [1, 2, 3]; foo.push(100); trace(foo[1]); trace(foo.length); var foo = {name: "foo", value: 12345}; trace(foo.name); trace(foo.hoge); //コンパイルエラー foo.value = 100; foo.valueX = 123; //コンパイルエラー
  41. 41. Dynamic • 変数の型にDynamicを指定するとなんでもできる。 • JavaScriptと同等の型制御(動的型付け)になる。 • コンパイラが型チェックできなくなるので注意。 • 以下のコードはすべてコンパイルが通る。 var foo : Dynamic = 100; foo = "abc"; var foo : Dynamic = { name: "foo", value: 123 }; foo.value2 = -200;
  42. 42. クラス • クラス名は必ず先頭を大文字にする class Point { // インスタンス変数 var x : Int; var y : Int; // コンストラクタ public function new(x, y) { this.x = x; this.y = y; } // メソッド public function toString() : String { return "Point(" + x + "," + y + ")"; } }
  43. 43. newとメソッドの呼び出し class Main { static function main() { var point = new Point(10, 20); trace(point.toString()); } } class Point { // 省略... }
  44. 44. プロパティ • 詳細はhttp://haxe.org/ref/properties class Foo { var valueField = 100; public var value(get, null) : Int; function get_value() { return valueField; } }
  45. 45. 継承 class Foo { public function new() {} public function method() {} } class Bar extends Foo { public function new() { super(); } override public function method() { super.method(); } }
  46. 46. interface interface IPoint { var x : Int; var y : Int; function toString() : String; } class Foo implements IPoint { public x : Int; public y : Int; public function new() {} public function toString() { /* ... */ } }
  47. 47. ジェネリクス • クラスに型パラメータをつける • 関数(メソッド)に型パラメータをつける class Queue<T> { var items : Array<T>; public function enqueue(entry : T) : Void { } public function dequeue() : T { } } var queue = new Queue<String>(); function foo<T>() { /* ... */ }
  48. 48. 定数(inline) • Haxeには定数(const)に該当するものはないが、 inlineを使うことで代用可能。 • その名の通り、コンパイル時にインライン展開される。 class Main { static inline var PI = 3.14; static function main() { var r = 5.0; trace(r * r * PI); } }
  49. 49. package(namespace)とimport • パッケージ名は必ず小文字のみで構成する。 • パッケージ名とパスは必ずマッチさせる。 • 詳細はhttp://haxe.org/ref/packages // src/mypackage/sample/Foo.hx package mypackage.sample; class Foo { // ... } import mypackage.sample.Foo; class Main { // ... }
  50. 50. アクセス修飾子(クラス・型) • publicとprivateの2種類 • 記述を省略するとpublic • privateを付けると、同じファイルからのみ参照可。 • 詳細はhttp://haxe.org/manual/modules class Foo { // ... } // importしても参照できない private class Bar { // ... }
  51. 51. アクセス修飾子(フィールド・メソッド) • publicとprivateの2種類 • 記述を省略するとprivate • privateは他の言語のprotectedに該当 class Foo { var value1 = 100; private var value2 = 200; public var value3 = 300; public function new() {} function privateMethod() {} }
  52. 52. 条件分岐 • if, switch, 三項演算子(cond ? a : b) • switchのcaseには break は書かない。 • 全て式なので、代入式の右辺にもできる if (foo > 0) { } else if (foo == 0) { } else { } switch (foo) { case "abc": //... case "xyz": //... default: //... } var foo = (cond) ? 100 : 0; var bar = if (cond) 100 else 0; var baz = switch (x) { case "abc": 100; default: 0; }
  53. 53. ループ構造 • for, while, do-while • breakも利用可能 • forにはiteratorしか指定できないので注意 for (i in 0...100) { } while (cond) { } do { } while (cond);
  54. 54. 例外 • どんな値でもthrowできる • Haxeの文化的にはStringを投げること多い? • でもデバッグが面倒なのでError投げた方が良いかも。 • finallyは存在しない • 詳細はhttp://haxe.org/doc/cross/exceptions try { throw "error"; } catch (msg : String) { } catch (ex : Dynamic) { }
  55. 55. 標準API JavaScript関係の主要クラス • http://haxe.org/api/js • js.Browser • windowオブジェクトのラッパー • js.Lib • alert(), eval() • js.Cookie • js.JQuery • http://haxe.org/api • haxe.Json • haxe.Http • haxe.Timer
  56. 56. DOM • js.Browserクラスが起点となる • http://haxe.org/api/js/browser import js.Browser; var elem1 = Browser.document.getElementById("foo"); var elem2 = Browser.document.querySelector("div"); elem1.addEventListener("click", function (e) { trace("click"); });
  57. 57. 通信(XMLHttpRequest) • haxe.Httpクラス • XMLHttpRequestのラッパー • 生のXMLHttpRequestが必要な場合は、 js.Browser.createXMLHttpRequest()を使う import haxe.Http; var http = new haxe.Http("/test"); http.async = true; http.onData = function (data) {} http.onError = function (msg) {} http.request();
  58. 58. JSON • haxe.Json • JavaScriptそのままのAPI import haxe.Json; var str = Json.stringify({foo: "bar"}); var data = Json.parse(str);
  59. 59. jQuery • js.JQuery • jQueryのextern • jQueryをHTMLにインクルードしておく必要あり • ただし、コンパイルオプション(build.hxml)に -D embed_js を追加すると自動で生成物にjQueryを 埋め込む(はず、ソースを見ただけで未確認) import js.JQuery; var btn = new JQuery("button"); btn.click(function (e) { /* ... */ });
  60. 60. JavaScriptライブラリのexternを作成 • 外部JavaScriptライブラリを使いたい場合、 extern(+typedef)さえ用意すれば、 コンパイラチェックとエディタで入力補完が。 • http://haxe.org/doc/js/extern_libraries package; extern class ExtraComponent { public function new(); public var visible(default, null) : Bool; public function hide() : Void; public function show() : Void; }
  61. 61. インラインJavaScript • untyped __js__() • JavaScriptのif文を組み立てることも可能 • JavaScriptから戻り値を受け取る untyped __js__("alert('hello')"); var count = 100; untyped __js__("for (var i = 0; i < count;++i) {"); trace("hello"); untyped __js__("}"); var text = "100px"; var num = untyped __js__("parseInt(text, 10)");
  62. 62. JavaScriptからHaxeコードの呼び出し • @:exposeを付けると、グローバルにクラスが 公開される。 • コンパイル後は普通にJavaScriptライブラリとして 利用可能になる。 • exporseに文字列を指定すると別名で公開できる @:expose class Foo { /* ... */ } @:expose("sample.Bar") class Foo { /* ... */ }
  63. 63. 代数的データ型(enum)とパターンマッチ これのためだけに Haxeを使っていると言っても 過言ではない。
  64. 64. 代数的データ型(enum)とパターンマッチ TypeScriptにはこれがないので 積極的に触る気が起きない…。
  65. 65. enumとswitch • caseはenumの要素を全て書かないとダメ • コンパイラが記述漏れをチェックしてくれる enum TextAlign { Left; Right; Center; } switch (align) { case Left: //... case Right: //... case Center: //... }
  66. 66. enumに値を持たせる enum Color { Red; Blue; Green; Glay(level : Int); Rgb(r : Int, g : Int, b: Int); } var orange = Rgb(0xFF, 0xA5, 0x00); switch (color) { case Red: //... case Blue: //... case Green: //... case Gray(level): //... case Rbg(r, g, b): //... }
  67. 67. enumの再帰構造 enum Color { Red; Blue; Green; Glay(level : Int); Rgb(r : Int, g : Int, b: Int); Alpha(aplha : Int, color : Color); } var color = Alpha(0xA0, Rgb(0xFF, 0xA5, 0x00));
  68. 68. enumとジェネリクス • 関数型言語で頻出するOption/Eitherも定義可能 • http://d.hatena.ne.jp/mzp/20120613/jsx enum Option<T> { Some(value : T); None; } enum Either<TLeft, TRight> { Left(value : TLeft); Right(value : TRight); }
  69. 69. enumでツリー構造(よくある例) enum TreeNode<T> { Node(children : Array<TreeNode<T>>); Leaf(value : T); } var root = Node(children: [ Node(children: [ Leaf("A"), Leaf("B") ]), Leaf("C") ]); function visit<T>(tree : TreeNode<T>) { switch (tree) { case Node(children): for (x in children) visit(x); case Leaf(value): trace(value); } } C A B
  70. 70. パターンマッチ • Haxe 3.0の目玉機能の一つ • 使いこなすと非常に便利 • パターンマッチの使い方だけで20分ぐらいは 話せそうなので、今回は説明を省略…。 • http://haxe.org/manual/pattern_matching?lang=jp
  71. 71. その他(今回は説明を省略) • 構造的部分型(Structural Subtyping) • 型安全なダックタイピング。 • interfaceを使う機会がかなり減る。 • http://haxe.org/manual/struct • using mixin • C#の拡張メソッドそのもの。 • http://haxe.org/manual/using • マクロ • コンパイルタイムにゴニョゴニョする。 • ASTで弄れるので高度なゴニョりが可能。 • http://haxe.org/manual/macros
  72. 72. まとめ • JavaScriptはいろいろつらい • 特にメンテナンス性が低すぎる。 • Haxeを使えば大抵の問題が解決する • 「なじみの深い」構文のおかげで、開発時に必要な 最低限度の構文を学習するコストも低い。 • Haxeの型システムやマクロなどをうまく使えば メンテナンス性とパフォーマンスを更に高められる。 • Haxeの構文・機能について書きたいことは たくさんあるが、全てを書ききれずに力尽きた。 • 公式ドキュメント見てね http://haxe.org/doc
  73. 73. ご清聴ありがとうございました

×