>100 Views
September 25, 17
スライド概要
2023年10月からSpeaker Deckに移行しました。最新情報はこちらをご覧ください。 https://speakerdeck.com/lycorptech_jp
Developers Summit 2017 KYUSHU 2017年9月22日@アクロス福岡 ヤフー株式会社 穴井宏幸 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
自己紹介 • 穴井宏幸 • @pirosikick • JavaScriptが好きです • https://mentaico-js.connpass.com/ • 2 そろそろ1年経つので2回目をやりたい。。。 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
所属 • 長いのでページを変えましたw • ヤフー株式会社 • メディアグループマーケティングソリューションズカンパニー 開発本部広告フロントエンド開発部 リッチメディア/広告R&D • • リッチラボ株式会社 エンジニア(主業務) • 3 第6代黒帯(JavaScript) リッチラボについては後述 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
ヤフーと九州 4 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
ヤフオクドームがある! 5 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
拠点が4つある! • 大分(CS) • 北九州(CS、メディア) • 博多(営業、決済金融) • 中洲川端 (営業、ヤフオク、私、IDCF) 6 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
https://about.yahoo.co.jp/pr/release/2016/01/18a/ 7 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
https://about.yahoo.co.jp/pr/release/2017/09/06a/ 8 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
リッチラボ株式会社 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
http://richlab.co.jp/ Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
リッチラボ株式会社 • ヤフーの社内起業制度で設立した 子会社 • 2017/9で設立3年! • 社員数19名 • エンジニア9名、デザイナー5名 • 社長、経理部長も 元エンジニア・デザイナー • スマフォのリッチ広告が軸 11 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
よろしく お願い致します Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
Webフロントエンド、改善 の積み重ね Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
質問 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
Q1. 仕事でJavaScriptを書い ている人? Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
Q2. 仕事で Webフロントエンドを担当 している人? Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
前提知識 • JavaScript • Node.js、npm • 最後に質疑応答の時間を 取ります • Ask the speakerブースも あるようです 17 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
今日話すこと • KAIZENアワーについて • Webフロントエンドの 具体的な改善例 18 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
KAIZENアワーに ついて Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
KAIZENアワーとは? • 1時間で各々が改善する会 • 毎週金曜日17:00〜18:00 • 改善であれば何をしてもよい • コードを書く • ドキュメントを書く etc • 最後の5分で成果発表 お互いを称え合う 20 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
きっかけ • 東京Node学園祭2016で↓を見た • サイボウズの開発を支える KAIZEN文化 https://www.slideshare.net/teppeis/ kaizen-68803503 • KAIZEN DAY、KAIZEN合宿など • 丸1日開催が厳しそうだったので、 毎週1時間開催に。 21 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
現状 • 今年2月から開始 • ほぼ毎週開催、平均4人参加 • 累計88時間の改善! • 各会の参加人数 * 1h • 改善活動が定着してきた 感じがある • 真似をするチームが出てきた! 22 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
Webフロントエンドの 具体的な改善例 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
リッチラボでの自分の担当範囲 • リッチラボでは2つの B2Bツールを開発・運用 • そのフロントエンドを ほぼ一人で担当 • 改善も自ずと それに関連したことが多い 24 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
KAIZENアワーでの個人的な方針 • • 1hできりが着くようにやる PRは小さく、分かりやすい単位で • Webフロントエンドの人員が少なく、 レビューワーの負荷が高いため • 大きめの課題は段階的にやっていく 25 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
1hでコツコツできる改善例 • コーディングスタイルの統一 • Errorを包む • 徐々に型を導入する 26 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
コーディングスタイルの統 一 27 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
コーディングスタイルの統一 • 2つのPJのコーディング スタイルが違う • 古いPJ: 独自のESLintルール • 新しいPJ: eslint-config-airbnb • 新しいPJに統一したい • 独自ルールは網羅性が無い 28 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
コーディングスタイルの統一 • 単純に切り替えると 大量のエラーが出る • レビュアーの手間も考え、 手作業での移行を断念 29 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
段階的に直していく 1. prettierの導入 2. エラーになる部分を 全て無効にする 3. jscodshiftで機械的に直す 30 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
prettierの導入 • モダンなコードフォーマッター • https://github.com/prettier/prettier • “Prettier is an opinionated code formatter.” • サポートしているファイルが多い • eslint --fixで直らないルールを直す 31 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
prettierのインストール # インストール $ npm install --save-dev ¥ prettier ¥ prettier-eslint ¥ prettier-eslint-cli ¥ eslint-config-prettier ¥ eslint-plugin-prettier 32 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
prettierのインストール • prettier • • prettier-eslint • • 被っているルールを無効にする eslint-plugin-prettier(任意) • • 33 prettier-eslintをCLIで動かす eslint-config-prettier • • prettier後、eslint --fixに流す prettier-eslint-cli • • prettier本体 prettierをESLintのルールとして実行 エラーをエディタに連携したい場合に使う Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
.eslintrc.json
eslint-config-prettierの設定
1 // .eslintrc.json
2{
3 ...,
4
5 "extends": [
6 "airbnb",
7 "plugin:flowtype/recommended",
8 "prettier",
9 "prettier/react",
被っているルールの無効化
10 "prettier/flowtype"
11 ],
12
13 ...,
14 }
34
Co p yrig ht © 2 0 1 7
Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
.eslintrc.json
eslint-plugin-prettierの設定(任意)
1{
2 ...,
3
ESLintのルールとして実行することで
4 "plugins": ["prettier"],
エラーをエディタに連携できる
5 "rules": {
6 ...,
7 "prettier/prettier": ["error", { "singleQuote": true }],
8 ...,
9 }
10
11 ...
12 }
35
Co p yrig ht © 2 0 1 7
Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
prettier-eslintの実行 # フォーマットの実行 $ prettier-eslint --write ¥ "src/**/*.js" ¥ "src/**/*.jsx" 36 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
コミット時に自動フォーマット
$ npm install -D lint-staged pre-commit
1 // package.json
2{
3 ...,
4 "pre-commit": ["lint-staged", ...],
5 "lint-staged": {
6 "*.@(js|jsx)": [
7
"prettier-eslint --write",
8
"git add",
9
...
10 ]
11 },
12 ...,
13 }
37
Co p yrig ht © 2 0 1 7
package.json
Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
それでも直らないルールは
一旦全部無効にする
1 // .eslintrc.json
2{
3 ...,
4 "rules": {
5 ...,
6 "prettier/prettier": ["error", { "singleQuote": true }],
7
8 // 機械的に修正できず一旦無効にしたルール
9 "class-methods-use-this": 0,
10 "no-unused-vars": 0,
11 "no-useless-escape": 0,
12 ...,
13 }
14 }
38
Co p yrig ht © 2 0 1 7
Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
無効にしたルールはコツコツ直す • 別のKAIZENアワーの時間や 何かのついでに直す • TDD的に出来てよい 1. 直したいルールを有効にする 2. ESLintを実行 3. エラーになった箇所を直す 4. 2〜3をエラーが無くなるまで繰り返す • 機械的に直せそうな部分はjscodeshiftを 使う 39 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
jscodeshift • Facebook製のリファクタツール • https://github.com/facebook/jscodes hift • 変換処理をJSで記述して 機械的にリファクタリング • ASTでコード変換 • テスト用のユーティリティが 提供されており動作検証が簡単 40 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
jscodeshiftの インストール&実行 # インストール $ npm install -g jscodeshift # 変換の実行 $ jscodeshift src/**/*.js -t 変換処理.js # -dでドライラン $ jscodeshift src/**/*.js ¥ -t 変換処理.js -d 41 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
変換処理のIF 1 // 変換処理.js 2 module.exports = function (file, api, options) { 3 // 変換対象のパスとソースコード 4 console.log(file.path, file.source); 5 6 return 変換後のソースコード; 7 8 // 変更なしの場合は、何も返さない or nullを返す 9 return; 10 return null; 11 } 42 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
AST • コードをパースした抽象構文木 • JSの場合、JSONオブジェクト として表現される • 色々なところで利用されている • • Babel(babylon) ESLint(espree) etc • 正規表現による置換よりも、 正確に変換できる 43 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
例)import文 import React from 'react'; 44 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
例)import文 ImportDeclaration specifiers[] source ImportDefaultSpecifier Literal import React from 'react'; 45 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
例)import文 import React from 'react'; ImportDclaration specifiers[] ImportDefaultSpecifier local Identifier source Literal value: 'react' 木構造 value: React 46 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
例)import文 1{ 2 "type": "ImportDeclaration", 3 "specifiers": [{ 4 "type": "ImportDefaultSpecifier", 5 "local": { 6 "type": "Identifier", 7 "name": "React" 8 } 9 }], 10 "local": { 11 "type": "Literal", 12 "value": "react" 13 } ※いくつかのフィールドは省略しています 14 } 47 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
AST Explorer https://astexplorer.net/ 48 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
jscodeshiftにおける ASTの操作 • api.jscodeshift • • • • • 49 • 変換処理の第2引数 ソースコードをASTにパース ノードの検索 新しいノードの構築 ツリー・ノードの加工 ASTからソースコードを生成 etc... Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
ソースコードをASTにパース 1 // 変換処理 2 module.exports = function (file, api, options) { 3 // 長いので j に代入 4 const j = api.jscodeshift; 5 6 // ソースコードをASTに変換 7 // jscodeshift/src/Collection.jsのインスタンス 8 const root = j(file.source); 9 50 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
ノードの検索
1 // ノードの検索
2 // 例:「import ... from 'react'」のノードを取得
3 const imports = root.find(
4 // ImportDecralationを検索
5 j.ImportDecralation,
6 // フィルター
7 // sourceが'react'のImportDecralation
8 {
9 source: { value: 'react' }
10 }
11 );
12 console.log(import.length);
51
Co p yrig ht © 2 0 1 7
Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
新しいノードの構築 1 // 例: 「import React from 'react'」を構築 2 3 // ImportDecralation 4 const newImportDecl = j.importDeclaration( 5 // ImportDecralation.specifiers[] 6 [ 7 // ImportDefaultSpecifier 8 j.ImportDefaultSpecifier(j.identifier('React')) 9 ], 10 11 // ImportDecralation.source 12 j.literal('react') 13 ); 52 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
ツリー・ノードの加工 1 const importDecls = root.find(j.ImportDeclaration); 2 const newImportDecl = j.importDeclaration(...); 3 4 // 検索したノードの直前に新しいノードを追加 5 importDecls.insertBefore(newImportDecl); 6 // 検索したノードの直後に新しいノードを追加 7 importDecls.insertAfter(newImportDecl); 8 // ノードの置換 9 importDecls.replaceWith(newImportDecl); 10 // ノードの削除 11 importDecls.remove(); 53 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
ASTからソースコードを生成 1 // ASTからソースコードを生成 2 console.log(root.toSource({ quote: 'single' })); 54 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
実例)Reactのimport文の追加 • 毎回Reactをimportするのが面倒だっ たのでグローバル変数に定義してい た • global.React = React; • よくないパターンなので、 JSXを使っているファイルは 必ずReactをimportするように修正し たい 55 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
①reactのimport文が無い
変換前
1 // JSXを記述しているがreactのimportがない
2 function SomeComonent() {
3 return <h1>Hello, JSX</h1>;
4}
こうしたい
変換後
1 import React from 'react'; // <= 挿入する
2
3 function SomeComonent() {
4 return <h1>Hello, JSX</h1>;
5}
56
Co p yrig ht © 2 0 1 7
Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
②既にreactのimport文があるが
Reactがimportさていない
変換前
1 import { Component } from 'react'; // <= Reactが無い
2
3 class SomeComponent extends Component {
4 ...
5}
こうしたい
変換後
1 import React, { Component } from 'react'; // <= Reactを追加
2
3 class SomeComponent extends Component {
4 ...
5}
57
Co p yrig ht © 2 0 1 7
Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
③変換不要 • JSXの記述がない • 既に正しくimportされている • import React from 'react'; • import React, { ... } from 'react'; 58 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
JSXが記述されているか? • JSXのタグはJSXElement • findでJSXElementを探す 1 // JSXがあるか? 2 // JSXのタグはJSXElementなので 3 // JSXElementがあるかどうか 4 if (!root.find(j.JSXElement).length) { 5 // JSXElementがない場合は何もしない 6 return; 7} 59 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
import React from 'react'を探す
1 // 「import React from 'react';」を探す
2 const importReact = root.find(
3 j.ImportDeclaration,
4 // フィルター
5 node =>
6 // sourceが'react'
7 node.source.value === 'react' &&
8 // specifiersにReactのImportDefaultSpecifierがある
9 node.specifiers.some(specifier =>
10
j.ImportDefaultSpecifier.check(specifier) &&
11
specifier.local.name === 'React'
12 )
13 );
14
15 if (importReact.length) {
16 return; // 変換不要
17 }
60
Co p yrig ht © 2 0 1 7
Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
①②の処理分岐
1 // パターン1, 2の分岐
2 // 「import ... from 'react';」を探す
3 const importFromReact = root.find(
4 j.ImportDeclaration,
5 { source: { value: 'react' } }
6 );
7
8 if (!importFromReact.length) {
9 // パターン1. import文をファイルに追加
10 ..
11 } else {
12 // パターン2. 既存のimport文にImportDefaultSpecifierを追加
13 ...
14 }
61
Co p yrig ht © 2 0 1 7
Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
①import文の構築・追加 1 // パターン1. import文をファイルに追加 2 // ファイルの先頭(Program.bodyの第1要素)に追加 3 root 4 .find(j.Program).get('body') 5 .unshift( 6 // 「import React from 'react';」を構築 7 j.importDeclaration( 8 [ 9 j.importDefaultSpecifier( 10 j.identifier('React') 11 ) 12 ], 13 j.literal('react') 14 ) 15 ); 62 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
②既存import文にReactを追加 1 // パターン2. 既存のimport文にImportDefaultSpecifierを追加 2 // Collecitionインスタンスからノードを取得 3 const node = importFromReact.get(0).node; 4 5 // ノードのspecifiersにImportDefaultSpecifierを追加 6 node.specifiers.unshift( 7 // ImportDefaultSpecifierを構築 8 j.importDefaultSpecifier(j.identifier('React')) 9 ); 63 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
ASTをソースコードに変換 1 return root.toSource({ quote: 'single' }); 64 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
参考になるプロジェクト • • ドキュメントがあまり無いので、 他のプロジェクトの変換処理を見ると 参考になる wikiにまとまっています • • recast、ast-typesのラッパーなので、 それらへの理解があると楽 • • 65 https://github.com/facebook/jscodeshift/wiki https://github.com/benjamn/ast-types https://github.com/benjamn/recast Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
変換処理のテスト • Jest用のテスト関数がある • 入力データ・期待値データを 用意すればテストが出来る 66 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
ディレクトリ構造 • • ___tests__以下にテストファイル ___testfixtures__にテスト用データ • • *.input.js → 入力データ *.output.js → 期待値データ 1. 2 ├── 変換処理.js 3 ├── __testfixtures__ ... テストデータ 4 │ ├── test-data.input.js ... 入力データ 5 │ ├── test-data.output.js ... 期待値データ 6 │ └── ... 7 └── __tests__ 8 └── 変換処理-test.js ... Jestのテストファイル 67 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
テスト
1 // jscodeshiftのテストユーティリティ
2 const { defineTest } = require('jscodeshift/dist/testUtils');
3
4 describe('変換処理', () => {
5 defineTest(
6 __dirname,
7
8 // テスト対象のファイル名
9 // 下記の場合、変換処理.js
10 '変換処理',
11
12 // 変換処理に渡すオプション
13 null,
14
15 // テストデータ
16 // 入力 ... __testfixtures__/test-data.input.js
17 // 期待値 ... __testfixtures__/test-data.output.js
18 'test-data'
19 );
20 });
68
Co p yrig ht © 2 0 1 7
Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
テストの実行 # Jestのインストール $ npm install -D jest # Jestの実行 $ ./node_modules/.bin/jest # watchモードで実行 $ ./node_modules/.bin/jest --watch 69 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
テストがパスした時 70 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
テストが失敗した時 71 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
Errorを包む 72 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
JSのErrorの不便さ • • 73 JSのErrorは拡張しづらい Errorの発生箇所が分かりづらい • npmパッケージが多い時、 トランスパイルしている時、 err.stackから追うのが辛い場合がある Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
Golangのerrors.Wrapが便利
1 import (
2 "github.com/pkg/errors"
3)
4
5 func FuncB() error {
6 err := FuncA()
7 if err != nil {
8
// Errorに情報を付加して返す
9
return errors.Wrap(err, "SomeFunc failed")
10 }
11 }
Co p yrig ht © 2 0 1 7
Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
verror • https://github.com/joyent/node-verror • "rich JavaScript errors" • npm install -S verror • Errorに付加情報を付けたり、 ErrorからErrorを作成したりできる • ※ブラウザでは動きません 75 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
Errorを包む 1 const VError = require('verror'); 2 3 throw new VError( 4 // 原因のError 5 err, 6 7 // エラーメッセージ 8 // %sなどのプレースホルダーを利用可能 9 // (内部ではextsprintfを使っている) 10 'error message: %s', 11 'hoge.txt' 12 ); 76 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
情報を付加する
1 throw new VError(
2 {
3 // 原因のエラー
4 cause: err,
5 // エラー名
6 name: 'SomeError',
7 // 任意の付加情報
8 info: { ... }
9 },
10 // エラーメッセージ
11 'error message: %s',
12 'string1'
13 );
77
Co p yrig ht © 2 0 1 7
Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
通常のErrorと同じように扱える 1 const e = new VError(...); 2 3 console.log(e instanceof Error); // => true 4 5 // メッセージ 6 // => error message: string1: 原因のErrorのメッセージ 7 console.log(e.message); 8 9 // スタックトレース 10 console.log(e.stack); 78 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
情報を取り出す 1 // 原因のErrorの取得 2 console.log(VError.cause(e)); 3 4 // 含まれる全てErrorのスタックトレース 5 console.log(VError.fullStack(e)); 6 7 // infoの取得 8 console.log(VError.info(e)); 9 10 // 含まれているErrorをnameで検索 11 VError.findCauseByName(e, 'SomeError'); 79 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
verrorの良い点 • Errorがネストしている場合も 見やすく表示できる • VError.fullStack • JSON系のログ出力と相性がよい • • bunyanを使っています 付加情報もまるっとログに 出力できる • 通常のErrorと同じ扱いができる • 80 導入が楽、混在していても問題ない Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
徐々に型を入れる Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
JSに型を導入したい • 堅牢なコードを書きたい • 改善を加速したい • 候補 • TypeScript • Flowtype • Flowtypeを採用 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
TypeScript • • "TypeScript is a typed superset of JavaScript that compiles to plain JavaScript" いわゆるAltJS tsc .ts .js 静的型チェック&変換 TypeScript 83 JavaScript Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
Flowtype • • • "FLOW IS A STATIC TYPECHECKER FOR JAVASCRIPT." 静的型チェッカー、AltJSではない 「静的型チェック」と「変換」が分離 flow 静的型チェック Babel or flow-removetypes .js 型注釈付きの JavaScript 84 Co p yrig ht © 2 0 1 7 型注釈を取り除く Yaho o Jap an Co rp o ratio n. All Rig hts Reserved . .js JavaScript
Flowtypeの良し悪し • 良い点 • 部分的に導入できる • Babelと相性がよい • Reactへの対応がよい • 悪い点 • ライブラリが型定義を 用意していないことが多い 85 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
Flowtypeの導入 1. 型チェックできる状態 1. 2. 3. 4. flow-binのインストール 設定ファイル 型注釈を削除する 型チェックの実行 2. 型注釈を書いていく 1. 2. 3. 86 ESLintの設定 コツコツと書いていく ライブラリの型定義 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
1.1. flow-binのインストール # flow-binのインストール $ npm install -D flow-bin # flowコマンドが使えるようになる $ ./node_modules/.bin/flow --help 87 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
1.2. 設定ファイルの記述 # 設定ファイルの雛形を生成 $ ./node_modules/.bin/flow init # .flowconfigが生成される $ ls .flowconfig 88 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
.flowconfig 1 # 無視する対象 2 [ignore] 3 ./lib 4 .*node_modules/fbjs.* 5 6 # 型チェックの対象 7 [include] 8 ./src 9 10 # 型定義ファイルの指定 11 [libs] 12 13 # Lintの設定 14 [lints] 15 16 # オプション 17 [options] 18 # 有効なモジュールの拡張子 19 module.file_ext=.scss 20 module.file_ext=.js 21 module.file_ext=.jsx 89 詳しくはドキュメントを見てください https://flow.org/en/docs/config/ Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
1.3. 型注釈を削除する # Babelの場合 # babel-preset-flowのインストール # - 型注釈の文法を解釈できるようにする # - 型注釈を取り除く変換をする $ npm i -D babel-preset-flow # CLI(babel-cli)の場合 $ babel --presets flow 90 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
1.3. 型注釈を削除する # flow-remove-typesの場合 # flow-remove-typesのインストール $ npm install -D flow-remove-types # 実行 $ ./node_modules/.bin/flow-remove-types ¥ src/ ¥ -d lib/ 91 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
1.4. 型チェックの実行 # バックグラウンドでプロセスが起動するので、 # 2度目以降はかなり早い $ ./node_modules/.bin/flow Launching Flow server for /xxx/xxx/xxxx Spawned flow server (pid=xxxx) Logs will go to /xxx/xxx/xxx.log No errors! # 「No errors!」が出ればOK 92 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
コミット時に実行
1 // package.json
2{
3 ...,
4 "pre-commit": ["flow", ...],
5 ...,
6}
• $ npm install -D pre-commit
• CIのプロセスにも入れておく
93
Co p yrig ht © 2 0 1 7
Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
2.1 ESLintの設定(任意) • eslint-plugin-flowtype • https://github.com/gajus/eslintplugin-flowtype • Flowtype周りの静的チェック • 必須ではないが、あった方がいい • 94 とりあえず、推奨設定を有効にする Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
.eslintrc.json
1 // .eslintrc.json
2{
3 ...,
4 // eslint-plugin-flowの有効化
5 "plugins": ["flow"],
6
7 // 推奨設定を継承
8 "extends": ["plugin:flowtype/recommended"],
9 ...,
10 }
95
Co p yrig ht © 2 0 1 7
Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
2.2 型注釈を書く 1 function sum(a, b) { 2 return a + b; 3} 1 // @flow 2 function sum(a, b: number): number { 3 return a + b; 4} 96 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
2.2 型注釈を書く • ファイルの先頭に「// @flow」 • • • 全ては解説できないので、 ドキュメント見てください>< • 97 チェック対象かの判定に使われる 「/* @flow */」でもOK https://flow.org/en/docs/types/ Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
2.3 ライブラリの型定義 • *.js.flowファイルが提供されていれば 勝手に読み込む • • 98 感覚的にはまだそんなに多くない 提供されていない場合 • flow-typedから持ってくる • 自分で書く Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
flow-typed • • • • 99 https://github.com/flowtype/flow-typed ライブラリの型定義が集まっている リポジトリ • TypeScriptのDefinitelyTypedみたいなやつ CLIから型定義ファイルをダウンロード可能 • flow-typed/以下にダウンロード 有志で作っているので、 全てのパッケージがあるわけではない Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
flow-typed # flow-typedのインストール $ npm install -g flow-typed # rxjs5系の型定義ファイルをダウンロード # flow-typed/npm以下にダウンロードされる $ flow-typed install [email protected] 100 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
自分で書く • • • • 101 https://flow.org/en/docs/libdefs/creation/ ライブラリの型定義が無い場合は、 ライブラリのドキュメントやソースを見ながら自分 で書くしかない 全てを書く必要はない ライブラリの中で使っている箇所だけ書く 書いた型定義ファイルはflow-typed/以下に置く と自動で読み込んでくれる Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
After Flowtype導入 • リファクタ時の恐怖心が軽減 • 部分的導入でも十分に効果がある • 同ファイル内の矛盾に気づくことも • コードがシンプルになる • 型無しで堅牢に書こうとすると if文で溢れるがち • 補完が効くのでファイルを 行き来することが少なくなった 102 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
まとめ Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
KAIZENアワーを導入して よかったこと • 単純に楽しい👍🏻 • 案件の進みが悪い時でも、 週1でアウトプットできる☝🏻 • 金曜をスッキリとした 気持ちで帰宅できる🍺 104 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
成長の場として機能してそう • 技術負債の解消だけでなく、 • 納期などの関係で一度放置した 問題にちゃんと向き合って 解決することで、 • 次に同じような問題が 出てきた時にはすぐ解決できる 105 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
さいごに Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
https://www.nikkei.com/article/DGKKASDZ31I1S_04092017TJ2000/ Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
We are hiring • ポテンシャル採用 (福岡配属の可能性あり) • https://about.yahoo.co.jp/hr/jobinfo/potential/ • キャリア採用(福岡での募集) • https://about.yahoo.co.jp/hr/jobinfo/career/0191/ 108 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
質疑応答 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .
ありがとう ございました 🍣 Co p yrig ht © 2 0 1 7 Yaho o Jap an Co rp o ratio n. All Rig hts Reserved .