• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
FIRST STEP to Haxe/JavaScript
 

FIRST STEP to Haxe/JavaScript

on

  • 10,709 views

 

Statistics

Views

Total Views
10,709
Views on SlideShare
9,947
Embed Views
762

Actions

Likes
35
Downloads
28
Comments
0

9 Embeds 762

http://terurou.hateblo.jp 370
https://twitter.com 346
http://cloud.feedly.com 17
http://tweetedtimes.com 16
http://kred.com 8
http://localhost 2
http://digg.com 1
http://www.kred.com 1
http://leaderboards.kred.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    FIRST STEP to Haxe/JavaScript FIRST STEP to Haxe/JavaScript Presentation Transcript

    • 目次 • 自己紹介 • Haxeとは • なぜJavaScriptコードを生成したいのか • Haxeと他のJavaScript生成言語 • Haxe/JavaScriptの開発環境 • Hello World • 基本的な構文・構造 • JavaScriptとの連携 • Haxeならではの機能・構文 • まとめ
    • 得意な技術領域 • ギョーム系DataGridの実装に定評があります。 • JavaScriptで2回 • Haxe/JavaScriptで1回 • Silverlightで1回 • ここ数年はクライアントサイド開発が中心。 • でもシステムアーキテクチャ設計がたぶん本業。 • キーワード Windows 8, .NET, WinRT, MSIL, F#, JavaScript, Haxe, TypeScript, Android, 分散システム, Cassandra, …
    • Haxeと私 • Haxe歴は1年ほど。 • わりと大きなプロジェクトにHaxeを投入。 • 大規模なギョームシステムにHaxeを採用してみた話 http://www.slideshare.net/terurou/haxe-15006171 • はてブ 200超え • でもこのスライド、発表当日に実質2時間ぐらいで 書き上げたヤツなんだよね… • 今も開発継続中、Haxe部分だけで5-6万行程度。 • Pure JavaScriptで書いている部分も数万行規模。 • サーバサイドも数万から10万程度はあるはず。
    • Haxeとは • JavaScriptコードを生成することができる プログラミング言語 • C#やJavaに似た「慣れ親しんだ」構文 • 詳細な説明は後ほど • この資料ではHaxe 3.0を前提に解説を行う
    • なぜJavaScriptを生成したいのか JavaScriptで開発するのが しんどい
    • なぜJavaScriptで開発はしんどいのか • 生産性・品質とメンテナンス性が両立しにくい。 • チーム開発しづらい。 • 学習コストが高い。
    • 原因1: JavaScriptの言語仕様が良くない • モジュールシステムが存在しない。 • ライブラリや実行環境(ブラウザ、Node.jsなど)に よって書き方が大きく変わる。 • prototypeベースオブジェクト指向を筆頭にして、 言語仕様が柔らかすぎる。 • 初心者がprototypeチェーンを覚えることが大変 • 「classのようなもの」の書き方がたくさんある。 • グローバルオブジェクトのprototype上書き問題 • グローバル汚染+varの付け忘れバグ • strictモードを使えばある程度マシになるが…。
    • 原因2: JavaScript界隈の文化が良くない • 他の言語から見るとバッドノウハウに近いような コーディングテクニックが氾濫している。 • 即時関数でスコープを限定化 • オブジェクトのnull判定 • 「単独varパターン」ってみんな使っている? • そのほか色々… • コーディングテクニックの流行り廃りが激しい。
    • JavaScripterほこたて • テクニックを駆使しないと書くのがしんどい。 • JavaScriptの言語仕様上、仕方がない。 • テクニックを駆使しすぎると他人が読めない。 • スキル・好み・ライブラリ・実装時期などによって コードの差異が激しくなりすぎる。 • チーム開発や保守でオーバーヘッドが大きくなる。 • チームメンバを教育しても次に生かせる保障がない。
    • JavaScriptは大変ですね 素直にあきらめて JavaScriptは生成しましょう。
    • JavaScriptコードを生成するプログラミング言語 2013年6月時点で現実的な選択肢 • Haxe • TypeScript • CoffeeScript 他にもjs_of_ocaml、Dart、JSXなどがあるが、 ユーザ数やとりまく環境を考えると選択しづらい。
    • Haxe • 慣れ親しんだ構文+高度な型システム • 基本構文はC#やJavaに似ている。 • 多少冗長ではあるが、万人に読みやすい。 • OCaml由来の型システム • 型推論、代数的データ型、パターンマッチなど • 簡潔に型安全なコードを書ける。 • マルチプラットフォーム • JavaScript以外の様々な言語・環境に出力可能。 • コンパイルが超速い • 歴史が長く(2005年~)、安定している
    • TypeScript • JavaScriptの構文拡張 • 静的型付け+型推論、クラス、モジュールなど • 型システムはHaxeほど高度ではないが、モダンな 言語としては最低限の機能は備えている。 • 将来的には一番人気になりそう • Microsoftが本気で開発・プロモーションしている。 • まだまだ安定していない • 2012年10月公開。 • 2013年6月にver 0.9.0 alphaが出たばかり。 • 1.0以後もAsync/Awaitなどの、インパクトの大きい 仕様追加が予定されている。
    • CoffeeScript • 軽量構文に特化 • JavaScriptと比較してコード量が1/3程度削減できる • Rubyの影響が強い構文 • 記述しやすい反面、人によって書き方がばらつく。 • 動的型付け • 型安全なコードは書きづらい…。 • 安定しているが、先行きを心配する声もある • TypeScriptと直接競合しており、世間の流行は 静的型付け言語に向いてきている。 • とはいえ現在も開発が活発なので、数年は大丈夫?
    • Haxeを選択する理由 • 型安全な方が良い • 品質、メンテナンス性に直結する。 • どうせ事前コンパイルが必要なので、コンパイル時に できることが多い方が良い → Haxeが有利 • コーディングスタイルのばらつきを抑えたい • CoffeeScriptは練度の高いチームなら良いが…。 • 今すぐに使える • TypeScriptは1.0まで待った方が無難。
    • 補足:型安全とは • 自分も詳しくないので引用でお茶を濁す https://twitter.com/camloeba/status/248734702062686208
    • 補足:型安全なコードを書くと… • UnitTestを簡素にできる • 型で表現/制限できることは、コンパイルが通れば バグがないことが保障される。 • Haxeの型システムで表現できることは多い。 • コンパイルすること自体がテストであるともいえる。 • UnitTestより確実 • コンパイラが静的に解釈(100%網羅) vs 全てのコードパスを通るテストコード • 人がテストを書く以上、テストケースにバグや漏れが 発生する可能性がある。
    • Haxeコンパイラ • Haxeプログラミングするためには必須。 • 現行バージョンは3.0(2013年6月時点) • インストール • Windows, Mac, Linux用バイナリを公式で配布。 http://haxe.org/download • インストール時に難しいことは特になし。
    • エディタ・IDE • おすすめ • Flash Develop(Windowsのみ) • Sublime Text(有償) + haxe-sublime-bundle • 実用レベルだが少し動作が重い • IntelliJ IDEA Ultimate(有償) + haXe plugin • FDT(Eclilseベース、フリー版と有償版がある) • 使ったことはないがイケてそう • Vim + vim-haxe • Vim + Vaxe • Emacs + haxe-mode
    • Flash Developのインストール • 公式ページ http://www.flashdevelop.org/ • インストーラの注意点 • .NET Framework 3.5が必要。 • Windows 8の場合は別途インストール fondue.exe /enable-feature:netfx3 • Java未インストールの場合、インストーラ起動時に 警告ダイアログが出るが、無視して構わない。 • Flex SDK, AIR SDK, Flash Playerは選択不要。
    • Flash Developのロケールを日本語に設定 • 日本語環境が良い場合は設定する。 • 後述の手順は日本語設定を前提にしている。 • 設定手順 • Tools→Program Settings • 右上のFilter settingに locale と入力 • Selected Localeを ja_JP に変更 • Flash Developを再起動
    • 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 と入力して選択するだけで パッケージがインストールされる。
    • ブラウザ(デバッグ環境) Haxeコードをそのままデバッグするには Source Mapsに対応したブラウザが必要 Chrome OK Internet Explorer 未対応(IE11でも×) Firefox v23で対応予定 Safari 未対応 Opera 未対応
    • ChromeでSource Mapsを有効にする • 設定方法(初期値は無効) • Developer Toolsを開く • menu→ツール→Developer Tools もしくは Ctrl+Shift+I • 右下の歯車アイコンをクリック • Generalタブ→Sources→Enable source maps
    • 基本的な流れ • プロジェクト(.hxmlファイル)の作成 • hxml = Haxe標準の簡易ビルドスクリプト • Flash Developの場合は、.hxmlファイルがなくても 開発できるが、他環境を考えると作成した方が良い。 • ここではFlash DevelopとSublime Textの手順を解説。 • プログラムを記述 • とりあえず alert() を表示するだけ。 • ビルド・実行 • ついでにデバッガを使ってみる。
    • プロジェクトの作成(Flash Develop)- 1 • Flash Developプロジェクトの作成 • menu→プロジェクト→新規プロジェクト • Haxe/JS Projectを選択して作成 • パッケージは未入力、その他は任意設定で可。
    • プロジェクトの作成(Flash Develop)- 2 • ビルド設定の変更 • menu→プロジェクト→プロジェクト設定 • 書き出しタブ→コンパイルターゲット • カスタムビルドに変更 • ビルドコマンドタブ →ビルド前に実行するコマンドライン $(CompilerPath)¥haxe.exe $(ProjectDir)¥build.hxml
    • プロジェクトの作成(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>
    • プロジェクトの作成(Sublime Text)- 1 • プロジェクトのディレクトリツリー • プロジェクトファイルの作成 • menu→Project→Save Project As ... • プロジェクトのルートディレクトリに保存 $project_root/ src/ bin/
    • プロジェクトの作成(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"] } ] }
    • プロジェクトの作成(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>
    • プログラムを記述 • src/Main.hxを作成 • haxeでは { を行頭に置くことが多い(C#風) • Flash Develop、Sublime Text共にデフォルト設定 • 普通に行末に { 置くことも多いので好みで。 package; import js.Lib; class Main { static function main() { Lib.alert("hello"); } }
    • ビルド・実行 • ビルド • Flash Develop • menu→プロジェクト→プロジェクトをビルド • F8 • ツールバーの歯車アイコン • Sublime Text • Ctrl + B • 実行 • bin/index.htmlをブラウザで開く。 • alert()が表示されれば成功。
    • Chromeのデバッガの使い方 • Developer Toolsを開く • menu→ツール→Developer Tools or Ctrl+Shift+I • Sourcesタブの左上の をクリック • ソースツリーが表示されるので、breakpointを 仕掛けたい位置を設定 • ソースツリーペイン右上の をクリックすると ペインを開いたままにしておくことが可能。
    • スタートアップクラス(エントリーポイント) • プログラム起動時に最初に呼び出される部分 • 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"); } }
    • trace() • trace() = console.log() package; import js.Lib; class Main { static function main() { trace("hello"); } }
    • 変数の宣言 • var 変数名 : 型名; • var 変数名 : 型名 = 初期値; • 型推論により、var 変数名 = 初期値; でも可。 var foo : Int; foo = 1; foo = "abc"; //コンパイルエラー var foo : Int = 100; var foo = 100;
    • 基本型とリテラル • 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
    • 文字列リテラルの注意点 • シングルクォーテーションは変数展開を行う。 • いわゆるフォーマット文字列 • ダブルクォーテーションでは変数展開しない。 var foo = 123; trace('foo'); trace('foo = $foo'); trace('foo = ${foo * 100}');
    • 配列と匿名オブジェクト • 配列は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; //コンパイルエラー
    • Dynamic • 変数の型にDynamicを指定するとなんでもできる。 • JavaScriptと同等の型制御(動的型付け)になる。 • コンパイラが型チェックできなくなるので注意。 • 以下のコードはすべてコンパイルが通る。 var foo : Dynamic = 100; foo = "abc"; var foo : Dynamic = { name: "foo", value: 123 }; foo.value2 = -200;
    • クラス • クラス名は必ず先頭を大文字にする 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 + ")"; } }
    • newとメソッドの呼び出し class Main { static function main() { var point = new Point(10, 20); trace(point.toString()); } } class Point { // 省略... }
    • プロパティ • 詳細はhttp://haxe.org/ref/properties class Foo { var valueField = 100; public var value(get, null) : Int; function get_value() { return valueField; } }
    • 継承 class Foo { public function new() {} public function method() {} } class Bar extends Foo { public function new() { super(); } override public function method() { super.method(); } }
    • 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() { /* ... */ } }
    • ジェネリクス • クラスに型パラメータをつける • 関数(メソッド)に型パラメータをつける 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>() { /* ... */ }
    • 定数(inline) • Haxeには定数(const)に該当するものはないが、 inlineを使うことで代用可能。 • その名の通り、コンパイル時にインライン展開される。 class Main { static inline var PI = 3.14; static function main() { var r = 5.0; trace(r * r * PI); } }
    • package(namespace)とimport • パッケージ名は必ず小文字のみで構成する。 • パッケージ名とパスは必ずマッチさせる。 • 詳細はhttp://haxe.org/ref/packages // src/mypackage/sample/Foo.hx package mypackage.sample; class Foo { // ... } import mypackage.sample.Foo; class Main { // ... }
    • アクセス修飾子(クラス・型) • publicとprivateの2種類 • 記述を省略するとpublic • privateを付けると、同じファイルからのみ参照可。 • 詳細はhttp://haxe.org/manual/modules class Foo { // ... } // importしても参照できない private class Bar { // ... }
    • アクセス修飾子(フィールド・メソッド) • publicとprivateの2種類 • 記述を省略するとprivate • privateは他の言語のprotectedに該当 class Foo { var value1 = 100; private var value2 = 200; public var value3 = 300; public function new() {} function privateMethod() {} }
    • 条件分岐 • 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; }
    • ループ構造 • for, while, do-while • breakも利用可能 • forにはiteratorしか指定できないので注意 for (i in 0...100) { } while (cond) { } do { } while (cond);
    • 例外 • どんな値でもthrowできる • Haxeの文化的にはStringを投げること多い? • でもデバッグが面倒なのでError投げた方が良いかも。 • finallyは存在しない • 詳細はhttp://haxe.org/doc/cross/exceptions try { throw "error"; } catch (msg : String) { } catch (ex : Dynamic) { }
    • 標準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
    • 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"); });
    • 通信(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();
    • JSON • haxe.Json • JavaScriptそのままのAPI import haxe.Json; var str = Json.stringify({foo: "bar"}); var data = Json.parse(str);
    • 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) { /* ... */ });
    • 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; }
    • インライン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)");
    • JavaScriptからHaxeコードの呼び出し • @:exposeを付けると、グローバルにクラスが 公開される。 • コンパイル後は普通にJavaScriptライブラリとして 利用可能になる。 • exporseに文字列を指定すると別名で公開できる @:expose class Foo { /* ... */ } @:expose("sample.Bar") class Foo { /* ... */ }
    • 代数的データ型(enum)とパターンマッチ これのためだけに Haxeを使っていると言っても 過言ではない。
    • 代数的データ型(enum)とパターンマッチ TypeScriptにはこれがないので 積極的に触る気が起きない…。
    • enumとswitch • caseはenumの要素を全て書かないとダメ • コンパイラが記述漏れをチェックしてくれる enum TextAlign { Left; Right; Center; } switch (align) { case Left: //... case Right: //... case Center: //... }
    • 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): //... }
    • 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));
    • 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); }
    • 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
    • パターンマッチ • Haxe 3.0の目玉機能の一つ • 使いこなすと非常に便利 • パターンマッチの使い方だけで20分ぐらいは 話せそうなので、今回は説明を省略…。 • http://haxe.org/manual/pattern_matching?lang=jp
    • その他(今回は説明を省略) • 構造的部分型(Structural Subtyping) • 型安全なダックタイピング。 • interfaceを使う機会がかなり減る。 • http://haxe.org/manual/struct • using mixin • C#の拡張メソッドそのもの。 • http://haxe.org/manual/using • マクロ • コンパイルタイムにゴニョゴニョする。 • ASTで弄れるので高度なゴニョりが可能。 • http://haxe.org/manual/macros
    • まとめ • JavaScriptはいろいろつらい • 特にメンテナンス性が低すぎる。 • Haxeを使えば大抵の問題が解決する • 「なじみの深い」構文のおかげで、開発時に必要な 最低限度の構文を学習するコストも低い。 • Haxeの型システムやマクロなどをうまく使えば メンテナンス性とパフォーマンスを更に高められる。 • Haxeの構文・機能について書きたいことは たくさんあるが、全てを書ききれずに力尽きた。 • 公式ドキュメント見てね http://haxe.org/doc
    • ご清聴ありがとうございました