flow による型のある世界入門
TRANSCRIPT
Copyright © DeNA Co.,Ltd. All Rights Reserved.
flow による型のある世界入門
株式会社 DeNA Games Osaka 技術部 人西 聖樹 [email protected]
Copyright © DeNA Co.,Ltd. All Rights Reserved.
自己紹介
人西 聖樹(ひとにし まさき)
Twitter: @sairoutine
株式会社 DeNA Games Osaka
Web アプリケーションエンジニア
Copyright © DeNA Co.,Ltd. All Rights Reserved.
今日話すこと
型とは
なぜ静的型付けが必要か
flow とは
flow と TypeScript の比較
Copyright © DeNA Co.,Ltd. All Rights Reserved.
型
Copyright © DeNA Co.,Ltd. All Rights Reserved.
「型システムとは、プログラムの各部分を、それが計算する値の種類に沿って分類することにより、プログラムがある種の振る舞いを起こさないことを保証する、計算量的に扱いやすい構文的手法である。」
Pierce, B. C. (2013) 『型システム入門 プログラミング言語と型の−理論 』住井英二郎 − ( 監訳 ), 遠藤他 ( 訳 ), オーム社 .
Copyright © DeNA Co.,Ltd. All Rights Reserved.
例えば Java ( 型のある言語 ) とかだと
int a = 1; // ← ここでの int が型
static int square(int param) // ← 返り値に int 型を宣言、引数に int 型の param を宣言
{
int value; // ← ローカル変数に int 型の value を宣言。
value = param * param; return value;}
Copyright © DeNA Co.,Ltd. All Rights Reserved.
静的型付けと動的型付け
静的型付け
⁃ コンパイル時に型をチェックする
⁃ 型がおかしいとそもそも実行すらできない
⁃ Java 、 C 、 C# などの言語
動的型付け
⁃ プログラム実行時にチェックする
⁃ 型がおかしくてもプログラムが実行されるまでわからない
⁃ JavaScript 、 Python 、 Ruby 、 Perl などの言語
Copyright © DeNA Co.,Ltd. All Rights Reserved.
JavaScript で使われるデータ型一覧
数値
文字列
論理値
null undefined オブジェクト
Copyright © DeNA Co.,Ltd. All Rights Reserved.
JavaScript は動的型付け
動的型付けなので変数にはどんな型を入れてもよい
関数の引数や返り値も柔軟に修正/変更できる 簡単! 静的型付けの言語では、変数にいれるデータの型
は決まっている 関数の引数や返り値の型を変更すると、関数の呼
び出し側も修正しなければならない 大変……
Copyright © DeNA Co.,Ltd. All Rights Reserved.
JavaScript は動的型付けのメリットを選択したプログラミング言語
Copyright © DeNA Co.,Ltd. All Rights Reserved.
しかし、今日では JavaScript に静的型付けの必要性が叫ばれています。
今回お話する flow も JavaScript に静的型付けを導入するツールです
Copyright © DeNA Co.,Ltd. All Rights Reserved.
なぜか
Copyright © DeNA Co.,Ltd. All Rights Reserved.
大規模なフロントエンド開発、開発したフロントエンドシステムの長期的保守が必要になってきた。
Copyright © DeNA Co.,Ltd. All Rights Reserved.
長期的に保守されるシステム
大規模で複雑なシステム
継続的にリファクタしていくシステム
ミッションクリティカルなシステム
保守するエンジニアが入れ替わっていくシステム
→ 動的型付け言語のメリットが活かせない
Copyright © DeNA Co.,Ltd. All Rights Reserved.
フロントエンドにも静的型付けが必要。ただし現状フロントエンドを実装できる言語は JavaScript の一択
Copyright © DeNA Co.,Ltd. All Rights Reserved.
JavaScript に静的型付けを導入したい
Copyright © DeNA Co.,Ltd. All Rights Reserved.
flow
Copyright © DeNA Co.,Ltd. All Rights Reserved.
Flow
JavaScript のコードに型定義 (annotation) を追加できるようになる
By Facebook 型のチェックのみしてくれる
コンパイラというより型チェッカー
本番コードでは、 Babel 等の仕組みで型定義をコードから削除する
日本では flowtype という呼称が一般的ですが、本スライド内では flow で呼称を統一します。
Copyright © DeNA Co.,Ltd. All Rights Reserved.
Google Trend
「 flowtype 」で検索 (2017/03/14 現在 )
Copyright © DeNA Co.,Ltd. All Rights Reserved.
静的型付けのメリット コードがより読みやすくなる
⁃ 型定義を読むことで関数を使う際にどんな引数が必要で、どんな値が返ってくるか想像をつけることができる
⁃ 引数や返り値の型が決まっているので、予想外の値が引数や返り値に含まれることを想像しなくてよい
コードのバグを事前に発見しやすくなる⁃ 型定義の誤りはコンパイル時にわかる⁃ 運用して初めて型の誤りによるバグに気づくということが
減る IDE のサポートを受けやすくなる
⁃ エディタの補完などが便利に リファクタしやすくなる
⁃ リファクタによって、関数の引数や返り値のデータ構造を破壊してしまっても、コンパイル時に気づくことができる
Copyright © DeNA Co.,Ltd. All Rights Reserved.
静的型付けが有利なシステムとは
長期間保守されることが想定されるシステム⁃ コードが後から読みやすいメリット⁃ コードは書かれる時間より読まれる時間の方が圧倒的に多い
大規模なシステム⁃ 複数人で開発する場合⁃ クラスや関数のインターフェイスを型定義により明確にできる
継続的にリファクタされるシステム⁃ リファクタによるデータ定義の破壊に気づくことができる
ミッションクリティカルなシステム⁃ 型定義の違いによるバグはコンパイル時に発見できる⁃ 型というルールを設けることでバグを減らせる
システムに関わる人が入れ替わるシステム⁃ 人が入れ替わっても型定義はコードに残る⁃ 関数の引数や戻り値を、コードを読み解いて調べなくても良い
Copyright © DeNA Co.,Ltd. All Rights Reserved.
実際のコード例
Copyright © DeNA Co.,Ltd. All Rights Reserved.
flow を使う準備
# babel の準備npm install -g browserifynpm install --save-dev [email protected] babel-preset-es2015# flow の準備npm install --save-dev flow-bin babel-plugin-transform-flow-strip-typesecho '{"presets": ["es2015"],"plugins": ["babel-plugin-transform-flow-strip-types"]}' > .babelrc
flow-bin がチェッカー本体で、babel-plugin-transform-flow-strip-types が、Babel によるトランスパイル時にコード上の型定義を除去してくれるプラグイン
Copyright © DeNA Co.,Ltd. All Rights Reserved.
flow を使う準備
"scripts": { "flow": "$(npm bin)/flow", },
package.json に flow チェッカーを追加
[ignore].*/node_modules/.*[include]
[libs]
[options]
.flowconfig を作成して node_modules 配下を無視する設定を追加
Copyright © DeNA Co.,Ltd. All Rights Reserved.
サンプルコード
// @flow
(function() { function foo(x) { return x * 10;}
foo('Hello, world!');});
文字列「 Hello, World! 」に掛け算をおこなっている、いかにも怪しいコード
// @flow を追加することで、 flow のチェック対象となる
Copyright © DeNA Co.,Ltd. All Rights Reserved.
$ npm run flow
5: return x * 10; ^ string. The operand of an arithmetic operation must be a number.
特にまだ型定義は追加していないが、flow がエラーを吐いてくれる。
→ 引数に String を渡しているにも関わらず、関数内で数値として扱っているのをFlow が発見してエラーにしている。
→ flow の 型推論 機能
Copyright © DeNA Co.,Ltd. All Rights Reserved.
サンプルコード
// @flow
(function() { function foo(x: string, y: number): number { return x.length * y;}
foo('Hello', 42);});
関数の引数に型定義を追加するパターン
Copyright © DeNA Co.,Ltd. All Rights Reserved.
サンプルコード
// @flow
function total(numbers: Array<number>) { var result = 0; for (var i = 0; i < numbers.length; i++) { result += numbers[i]; } return result;}
total([1, 2, 3, 4]);
配列の型定義
Copyright © DeNA Co.,Ltd. All Rights Reserved.
サンプルコード
// @flow
// 独自の型type Comment = { author: string; text: string;};
const comment: Comment = { author: "sai", text: "hello, world!",};
function create_text (comment : Comment) : string { return comment.author + " says " + comment.text;}
console.log(create_text(comment));
独自の型定義も可能
Copyright © DeNA Co.,Ltd. All Rights Reserved.
サンプルコード
// @flow
(function() { function length(x) { return x.length;}
var total = length('Hello') + length(null);})
Null が入る場合
Copyright © DeNA Co.,Ltd. All Rights Reserved.
$ npm run flow
7: return x.length; ^ property `length`. Property cannot be accessed on possibly null value7: return x.length; ^ null
Null が入る可能性があるため、エラーになる。flow は Null 安全
Copyright © DeNA Co.,Ltd. All Rights Reserved.
// @flow
(function() { function length(x) { if (x !== null) { return x.length; } else { return 0; }}
var total = length('Hello') + length(null);});
Null であることをきちんとチェックすれば OK
Copyright © DeNA Co.,Ltd. All Rights Reserved.
(function() { function length(x : ?string) : number { if (x != null) { return x.length; } else { return 0; }}
var total = length('Hello') + length(null);});
型推論に任せず、 Null を許容する型を定義する方法も flow にはある
Copyright © DeNA Co.,Ltd. All Rights Reserved.
React や Flux, Redux との連携
容易にできるらしい
React 周りに詳しくないので詳細は別の方の資料にお任せします。
【 Electron + react + flowtype】 TweetDeck ライクなpixiv クライアント PixivDeck をつくった
http://qiita.com/akameco/items/fa80b9a325e3d1e8fd5b
Type-Safe Flux Using Flowtype https://speakerdeck.com/joere/type-safe-flux-using-fl
owtype
Copyright © DeNA Co.,Ltd. All Rights Reserved.
JavaScript に静的型付けを導入するには、TypeScript を使う選択肢もある
Copyright © DeNA Co.,Ltd. All Rights Reserved.
TypeScript
AltJS By Microsoft ES6 ベース 型定義を追加することができる コンパイラが型定義をチェックしてくれる JavaScript というより TypeScript という言語 WebStorm や Visual Studio Code などの IDE による
サポートがある Null 安全でない (TypeScript 2.0 から strictNullChecks
オプションで Null 安全に ) 静的型付けの恩恵を受けたい場合、 TypeScript を採用す
る手もある
Copyright © DeNA Co.,Ltd. All Rights Reserved.
flow と TypeScript の比較
flow⁃ 既存の JavaScript コードにも適用できる
⁃ 一部のコードにだけ静的型付けを適用することもできる
⁃ JavaScript + 型定義なので、学習コスト低
⁃ あくまで型チェッカー。それ以上のことはしない
TypeScript⁃ 型定義以外の恩恵 ( クラス定義構文など ) が受けられる
⁃ 導入するとなると、全コードを TypeScript に置き換える覚悟
⁃ TypeScript の文法などの学習が必要
⁃ IDE のサポートが豊富 (Visual Studio Code や WebStorm など )
Copyright © DeNA Co.,Ltd. All Rights Reserved.
まとめ
フロントエンド開発の大規模化、長期的な保守に伴い、静的型付けの重要性が認識されてきた
JavaScript に静的型付けを導入するには、 flow と TypeScript のおおまかに二種類が存在する。
flow は既存のシステムに追加する場合に、 TypeScript は新規のシステムに追加する場合に便利
両者とも型定義は非常に似通っている。
Null 安全についての扱いが両者は異なる
プロジェクトやチームにとって最適な選択で、静的型付けを導入しよう
Copyright © DeNA Co.,Ltd. All Rights Reserved.
ご清聴ありがとうございました