Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
新タクシー配車システムの裏側/dispatcher-background
Search
haco
May 23, 2017
Programming
460
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
新タクシー配車システムの裏側/dispatcher-background
haco
May 23, 2017
More Decks by haco
See All by haco
コードファースト vs スキーマファースト on Rust / code-first-vs-schema-first
haco
0
2.5k
crates.io にライブラリを公開してみた / publish-on-crates-io
haco
0
1k
Other Decks in Programming
See All in Programming
XP祭りでしか伝わらないフリップネタ #xpjug
murabayashi
0
110
Laravelのアプリケーションをどこにデプロイするか #ツナギメオフライン.9
akase244
0
110
自分的「カンファレンスの楽しみ方」
syumai
0
190
初心者DevRelとして参加者だった私が、DevRel Talks!#2に登壇するまでにしてきたこと
sokohirai
0
330
Kiroで創り、AgentCoreで繋ぐ!AWSで実践する「AI-DLC」から「AIエージェント統合」までの最新地図
licux
2
300
Seeing Through Serverless: Observability for AWS Lambda with ADOT and CloudWatch Application Signals
seike460
PRO
1
120
まずはプロンプトガイドを読もう、話はそれからだ
kiakiraki
1
260
承認済みなのに差戻しできてしまうバグ、型で潰せます
shinchit
0
140
思考垂れ流し開発 ~音声入力 × AIエージェント × 開発ハーネスによる試行錯誤~
npostring
0
810
Hono + Inertia + React で LP を構築した話
oukayuka
2
210
이 함수, 실패하면 어떻게 되나요? null부터 Rich Errors까지, Kotlin 에러 처리 15년
haeti2
0
130
AI駆動開発にグラフDBを重ねてみた
satoshi256kbyte
2
730
Featured
See All Featured
SEO for Brand Visibility & Recognition
aleyda
0
4.7k
Tell your own story through comics
letsgokoyo
1
1.1k
My Coaching Mixtape
mlcsv
0
300
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
720
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
660
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
68
57k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.6k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
840
So, you think you're a good person
axbom
PRO
2
2.1k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.5k
Mobile First: as difficult as doing things right
swwweet
225
10k
Transcript
新タクシー配車システムの裏側 2017-05-23 : ヒカラボ発表資料 JapanTaxi : 相田 岳彦
自己紹介 2016-06 JapanTaxi 入社 06-07 月 某 API サーバ /
Golang 07-11 月 全国タクシー Android / Java 10-12 月 Google Maps 対応 12-01 月 某バッチサーバ / Scala 12-02 月 全国タクシー API / Rails 03 月- 新タクシー配車システム / ES6, Rails いろいろやってます
今回話すこと 新タクシー配車システムの紹介 技術的負債を避けるための取り組み Rails API 開発編 React フロントエンド開発編
今回話さないこと Rails や React アプリの構築方法 CI/CD の構築方法
そもそも配車システムって何さ ざっくりまとめると
お客さんからの注文を受けて オペレータが空車状況などを確認して タクシーを配車するためのシステム
今回話すところ API は Rails で作られていて フロントは React で作られているサービス
ということで技術的な話
まずは Rails の話から
Rails 開発で防いでおきたかったこと とりあえず ID パターン テーブルモデル中毒
とりあえず ID パターン ( ご存知の方)
あらゆるテーブルに ID を入れてしまう症状 詳細は "SQL アンチパターン" 参照
大前提 ウェブフレームワークの都合で テーブル設計を歪める判断は基本的にありえない
対処 Rails にはきちんと primary key を 明示する仕組みが用意されてる
Q. そうはいっても "id" がないと 冗長になるコードはあるよね? A. それでもプロダクト根幹の DB 設計を歪めるほうがダメ
テーブルモデル中毒 ( ご存知の方)
先週名付けました ( 聞いたことがなくても安心してください)
テーブルと 1:1 で紐付いた「モデル」で 全てを表現しようとする症状
行き着く先は 典型的なファットモデル… !
これが rails-way なのだという誤解を 頻繁に見かける超要注意パターン
テーブルモデル中毒を 予防するには… ?
レビューで解決… ? レビュアーが全員 毎回忘れずに チェックするのは現実的だろうか(反語)
開発者全員が危険性と 回避方法を理解すればいい… ?
しかし未経験の負債への対処はとても難しい ファットモデルのヤバさは ファットになるまで気付けない ファットになってしまったら もうすでに遅かったりして…
あらためて テーブルモデル中毒を 予防するには一体どうしたら… ?
私たちの答え 「モデリングを開発フローに組み込もう」
具体的には? アクションごとの仕様を宣言するための 言語内 DSL をコントローラに用意
個々のリクエストとレスポンスに 対応するクラスをまず最初に定義する それぞれのクラスに対応する JSON Schema ファイルも生成する
コード例 update アクションの仕様を宣言する場合 api :update, :request => Requests::V1::Hello::CreateParameter :response =>
Resources::V1::Greeting::Hello
これによって テーブルモデルを引き回すコードや view で巨大な JSON を構築するようなコード が生まれてしまう余地を取り除いた
さらに 指定した型にならないリクエストは 400 指定した型にならないレスポンスは 500 も自動化できた!
副次的な効果
JSON Schema を導入したことで : API 仕様が自動的にバージョン管理される うっかり破壊的変更を入れても簡単に気付ける (スキーマファイルも変更されるため)
リソースのモデリングによって : リソースの型をバージョニングできる 安全にバージョンアップできる 機能拡張に対する心理的障壁の除去
言語内 DSL の表現力によって リソースを今まで通りに抽象化できる JSON Schema の手作業記述を回避 正規表現のコピペ問題なども回避
次は React の話 というよりは React-Redux の話
React-Redux で防いでおきたかったこと implicit state implicit action fat dispatcher
implicit state 実装者の頭の中だけに state の定義がある状態
implicit state 「どのような状態が正しいのか」が コードで表現されていない状態 フィールドの更新漏れ・追加忘れといった 人的ミスが誘発される
解決方法 全ての state をクラスとして明示的に定義 初期状態や更新方法をクラス内で完結させる
implicit action 実装者の頭の中だけに action の定義がある状態
implicit action 「この action にはどのような値があるのか」 「この action はどの type と紐付いているのか」
抱えている問題は implicit state とほぼ同じ
解決方法 対処策も implicit state とほぼ同じ ( ただし action の場合はクラス化の必要なし)
具体的には… ? action と type を紐付ける ActionFactory を用意
これによって : factory に action の定義が明文化される reducer の依存先を action-factory だけにできる
文字列定数の type を羅列する苦行の回避
コード例 actions.js // 該当する顧客が見つかった場合のアクション export const CustomerFound = ActionFactory({ type:
'OrderEditor/CustomerFound', /** * @param {CustomerOutline} customer */ currentCustomer: customer => customer, });
reducer.js // 注文編集フォームの reducer export const editorReducer = ReducerFactory.create({ initializer:
() => { return EditorState.empty(); }, /** * @param {EditorState} state * @param {Object} action - see ./actions.js */ handlers: (state, action) => ({ [CustomerFound]: () => { return state.updateState({ customer: action.currentCustomer, }); }, }), ... });
fat dispatcher 文字通り dispatcher が肥大化する症状 fat model や fat controller
と同種のもの
解決方法 dispather の責務を絞る
具体的には? dispatcher は 文字通り action を dispatch するだけに留める 各種データの取得処理は他のモジュールに切り出す 典型例は
API リクエスト レイヤードアーキテクチャを導入して責務を分担
レイヤー構造 layouts 画面内の component に紐づく処理 domain 複数の component で共有するロジック repository
API リクエスト ストレージ (cookie, LocalStorage) 操作 dispatcher が利用する多くのモジュールは ほとんどの場合はこのレイヤにある (相対パス地獄は webpack の resolve.root 指定で回避)
まとめ Rails Rails Way をダメな設計の弁明手段にしない ダメなのは必ずしも Rails のせいではない React (Redux)
サンプルコードはそのまま真似してはいけない プロジェクトに適した方法で抽象化しよう - n-