Upgrade to Pro — share decks privately, control downloads, hide ads and more …

大型フロントエンド開発におけるTypeScriptとDDD

 大型フロントエンド開発におけるTypeScriptとDDD

2016/3/5, FRONTEND CONFERENCE 2016にて発表した資料です。

OKUNOKENTARO

March 05, 2016
Tweet

More Decks by OKUNOKENTARO

Other Decks in Programming

Transcript

  1. 自己紹介 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. • 奥野

    賢太郎 @armorik83 • ChatWork株式会社 サービスデザイン部 • フロントエンドチーム • 京都市出身 • ng-kyoto代表 2
  2. チャットワークの規模 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. 4 •

    累計メッセージ数(2011年3月〜2016年1月) • 10億メッセージ以上 • 導入企業数(2016年2月末) • 92,000社 • 導入国・地域数(2016年2月末) • 205
  3. 本日お話しすること 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. • 現行の問題点と


    次の技術選定 5 過 去 現 在 未 来 • 大型開発での
 チーム運営 • TypeScriptとDDDの
 工夫 • Viewフレームワーク
 との付き合い方 • 二槽式アーキテクチャ
  4. 現行のWeb版チャットワーク 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. • まだmoduleという概念が無い

    • グローバル変数に名前空間を切る • そこに神オブジェクト • jQuery • ノンフレームワーク • 繰り返される機能拡張 = 増築 • 変わっていかねばならない 7
  5. TypeScript 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. • ES2015は弊社フロントエンド全員が習得済み

    • 初期はBabel • 試行錯誤していた • 型が無いと今後厳しいと悟る • TypeScriptに全て書き直し 8
  6. AngularJS 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. • なぜAngularJS

    • プロトタイピングに採用 • チームがすでに慣れていた • 私自身の経験が豊富(2年半) • 問題への対策・提案が素早く行えた • Angular 2が控えていることは承知 9
  7. チームは日々拡大 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. • 最初はワンマン

    • 1ヶ月後に1人 • 2週間後にさらに1人加入 • 現在は8〜10人程度 • 構成 • プロジェクト・マネージャ: 1人 • フロントエンド・エンジニア: 3人 + 2人(外注) • バックエンド・エンジニア: 1人 • UIデザイナー: 2人 11
  8. コメント 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. • 指針を持つ

    • 各行の日本語訳のようなコメントは極力残さない • なぜそう書かざるを得なかったのか、意図をたくさん残す • だいたい思い出せなくなる 13
  9. ドキュメント、コーディング規約 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. • 初期は少人数で、暗黙知が多かった

    • チームが大きくなってきた際に疑問点のヒアリングを行った • ヒアリングの結果 • 開発環境構築の手順をドキュメント化 • 主要な処理はエントリポイントからコメント付きでフォロー • コーディング・スタイル統一にはtslintを使用 14
  10. デザイナーとの連携 (1) 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. •

    デザイナーがSCSSを扱う頻度が高い • JS側には原則としてスタイルを書かない • 逆にデザイナーがHTMLテンプレートを触ることはない • SCSS, BEMを採用 (block__element--modifier) • 手書きだとメンテナンスしにくいのでBEMライブラリを使用 • github.com/axross/bemmer • BEMで影響範囲を特定できリファクタリングは進めやすい 15
  11. デザイン仕様書の取り扱い 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. • 最初はGitHub

    Wiki • 全文検索できない • 更新に気付かない • 全てをMarkdownにしてPR必須とした • リポジトリ内で検索しやすい! • 更新に気付くだけでなくレビューで必ず目を通す! • dialog/dialog.ts, dialog.scss, dialog.mdのように
 ひとまとめにしている 16
  12. 単体テスト 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. 17 •

    mocha + power-assert • モックを扱ったり、型違反を意図的に扱ったりする • テストはES 2015で記述 • 不安なロジックはしっかりテスト • ただし盲目的にカバレッジ100%を目指したりはしない • もし実装を変更するたびにテストも修正していたら
 「そもそも何をテストしたい?」に立ち返る • テスト自体も負債化する • テスト内の負債を無視しない
  13. E2Eテスト 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. 18 •

    PageObjectパターンを導入 • テストのシナリオと、そのための実現方法を分離 • すべてをPageObjectのメソッド内に隠蔽 • it()の中でElement取得やEventの発火を行わない • テスト側は数行のコードとassert()のみになる • CI上でのE2E実行はSauce Labsで
  14. Karmaテスト 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. 19 •

    開発初期のテストはmochaとE2Eだけだった • 徐々に書ききれない領域が出た • Karmaを追加 • ただしモックのメンテナンス量も増えてしまう • どういうときにKarmaか • やむを得ずViewがステートを保持する場合の検証 • イベントハンドリング周りの検証 • なるべくmochaの単体テストに寄せたほうがいい
  15. タスクランナー 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. 20 •

    gulpを使用 • 属人性に気をつける • あっという間に秘伝のタレ化 • gulpファイルの差分を追えるように工夫 • タスクをファイルごとに分割 • 各オプションも細かく行ごとに分ける
  16. 検証環境の構築 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. 21 •

    検証は環境構築のコストが高い • VM保守、DBのダミーデータ構築、更新、誰がやる? • 検証環境へのデプロイもgulpで構築 • 弊社@kyo_ago謹製 • 実際のAPIレスポンスを用いて開発できるようになった • フロントエンド・エンジニア内で完結 • CIが回るごとにデプロイを実行 • PR単位でデプロイ、全PRのbundle.jsが残る • バグを追いやすい • 社内の非エンジニアにもドッグフーディングしてもらいやすい
  17. ビルド 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. 22 •

    ビルド時間はモチベーションに直結 • 約400ファイルあるTypeScriptのビルド時間が開発上問題に • トータル約60秒! • Browserifyをwebpackに替えたら5分の1! • tsc: 7秒 • Browserify: 30秒 → webpack: 6秒 • tslint: 20秒 • ストレス無くビルドできるよう改善 • SCSSのコンパイルを分ける • tslintの実行順を変える
  18. TypeScriptとDDDが必要になったワケ 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. • 約400のソース

    • Component, Service, Utility, API... • 一人で全て把握するなんて無理 • チーム全員で漏れなく共有するのも大変 • TypeScriptの型はチームメンバープロダクト全体の把握を助け、
 揺るぎない情報となる • 大きなシステムほど「膨大な知識」が要求される • Domain-Driven Design ドメイン駆動設計 • チーム内で関心事を掘り下げ共通言語の定義が必要 24
  19. TypeScript 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. • TypeScript

    1.8 • 全ソースがES2015ベース + 型付け • Generics, abstract classの使用 • import前提、namespace(旧: 内部モジュール)は不使用 • tsconfig.jsonでのオプション管理 • 型定義ファイルは全てリポジトリにPush • 微妙に.d.tsを手修正している • 型定義管理ツールよりPullする方がチーム開発において確実という判断 • 強行なので、美しい手段とはいえない 25
  20. 型の恩恵 (1) 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. •

    一ヶ月後の自分は他人 • コンパイラはJSDocと違って嘘をつかない • むしろ@paramに型情報を書かない • 短いコメントを付けるくらいなら型名を • IDEでのメリット • 全員がIDE "WebStorm"を使用 • ショートカットやクリックでファイルを辿れる • 型名を打つとメソッドが補完される → 開発効率アップ! • TypeScriptの導入コストと、Docs・コメントの保守コスト
 どっちがいい? 26
  21. 型の恩恵 (2) 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. •

    テストの捉え方が変わる • ロジックの振る舞いそのものの検証に集中できる • サーバレスポンス値など、稀にtscをすり抜けて型違反が起こる場合 • 実行時assertで拾う • 自信を持ってリファクタリングできる • 複雑な計算を含むならばテストを書くことが前提 • スコープが狭ければ型違反が起こらない限り維持できている • コンパイラが守ってくれる安心感 27
  22. ドメイン駆動設計 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. 28 •

    バックエンドチームが採り入れている • Vaughn Vernon (実践本) • Eric Evans (原典) • 完璧なDDDの実践は難しい • 言語的な側面もあるし、チーム共有の側面も • フロントエンドチームは、まだDDDが実践できている
 とは言いがたい • TypeScriptを活かすために触れた
  23. ユビキタス言語とコンテキスト 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. • ユビキタス言語

    • エンジニア、デザイナー、ビジネス間での共通言語 • User, Message, Task • 「顔アイコンはIconではなくAvatar」などの共通認識 • 人によって記述がブレないように • コメント、Docs、仕様書、議事録 • コンテキストを分ける • Viewフレームワークに適したデータ構造と抽象概念は必ずしも一致しない • これは開発側の事情 29
  24. Coreドメイン 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. • User,

    Message, Taskなどのドメインモデル • すべてAbstractEntityを継承 • コレクションごとのclass • Array<User>ではなくUsersというclassを作成 • ユビキタス言語内の語彙を増やす • OOP的利点でみると、実装の隠蔽とユニットテストの容易化 • AbstractEntitiesを継承 30
  25. Applicationドメイン (1) 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. •

    フレームワーク寄りのデータ構造を定義 • CoreのUserに対する、BindableUser classを定義 • たとえば • 正規化されてIDしか持たないCoreに対して、文字列の値を持つBindable • 画面上でチェックマークが付いているかどうかのbool値 • Iteration protocolsは実装せずJS Arrayとして扱う • Array<BindableUser>とする 31
  26. Applicationドメイン (2) 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. •

    UI上のラベルは、原則Viewレイヤーで計算しない • 「3人」という文字列 • "{{users.length}}人"とせずに"{{labelUsersCount}}"とする • 事前にApplicationドメイン・レイヤーで生成する • 多言語表示に対応しやすい • テストを書きやすい • 頑なに守るとパフォーマンスが出ない箇所もあるので、そこは柔軟に 32
  27. TypeScriptとDDD - プリミティブを型で表現 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved.

    • たとえば、myidというグローバル変数 • TypeScript上でもnumberとしてしか表現できず貧弱 • 追えない! • Myid classとMyidServiceを実装 • MyidService.getMyid() • Myidインスタンスはvalueプロパティにmyid値を持つ • 引数はmyid: numberにせず、myid: Myidとする • Scalaサイドの知見 • TypeScriptで全てに適用しようとすると煩雑 • 今回は、仕様上やむを得ないグローバル変数にのみ適用 • 追える! 33
  28. TypeScriptとDDD - Generics活用 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved.

    34 class AbstractService<T extends AbstractEntities<U>,
 U extends AbstractEntity> { constructor() { // ... } } • F-Bounded Polymorphism • TypeScript 1.8で動くようになった • 型クラス!!
  29. Angular? React? 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. •

    どれがいい? • 今どれがオワコン? • その考え自体を改める 37
  30. Angular? React? 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. •

    どれがいい? • 今どれがオワコン? • その考え自体を改める • 長期で取り扱っていくプロダクトほど界隈の変動には巻き込まれる • フレームワークの変動に強いアーキテクチャの検討が必要 • 恐れない • 焦らない 38
  31. フレームワーク・ロックインへの考え方 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. • 今回はAngularJS

    1.5 • いつでもAngular 2へ進めるように • 極端な言い方をすると、いつフレームワークを
 捨てても大丈夫な状態を保つ • Applicationドメインに表示用・描画用のロジックを集約 • window, document絡みの処理も全て抽象化 • AngularJSからは単に切り出された処理を使うのみ 39
  32. Angular 2化 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. •

    実はすでにAngular 2化も進行中 • 様々な検証を進めている 40
  33. 二槽式アーキテクチャ 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. • 二槽が独立して成立することを目指したアーキテクチャ

    • @kyo_agoが提唱 • フロントエンド・フロントエンド • テンプレート記述、表示要素のトグル、CSSクラスの動的な変更 • windowやdocumentの絡む箇所、DOM, Elementの操作 • フロントエンド・バックエンド • Coreドメイン、Applicationドメイン • サーバへリクエストを発行、レスポンスを加工 • ゆくゆくはScala.jsで…? 42
  34. 二槽式アーキテクチャ 図解 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. 43

    View Action Controller API Store Application Domain Core Domain Component Frontend-Frontend Frontend-Backend
  35. まとめ 大型フロントエンド開発におけるTypeScriptとDDD 2016/03/05 © ChatWork All rights reserved. • チームが大きくなると

    • デザイン、ドキュメント、テスト、ビルド…いたるところで問題が見つかる • アプリ開発だけでなくチーム全体が上手く回る仕組みづくりも必要 • アプリケーションが大きくなると • 人間の管理が追いつかなくなる • 機械の支援を受ける • コンパイラのエラー • IDEの補完・ジャンプ • いくつもの共通認識を育てながら大型フロントエンド開発を進める 44