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
450
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.4k
crates.io にライブラリを公開してみた / publish-on-crates-io
haco
0
990
Other Decks in Programming
See All in Programming
Haskell/Servantを通してWebミドルウェアを捉え直す
pizzacat83
1
580
信頼性について考えてみる(SRE NEXT 2026 miniLT)
hayama17
0
190
Laravel Boostに学ぶ、AIにPHPを書かせる技術 〜OSSの実装から蒸留するエージェント制御の王道〜
kentaroutakeda
3
400
Claude Opus 4.6以後の受託開発エンジニアの変化(Claude Code開発ノウハウ大公開スペシャルbyクラスメソッド)
iidatakuma
1
740
【SRE NEXT 2026 Lunch Session】一人目専任SREの立ち上げを加速する ― AIと進めたオンボーディングで2分を0.04秒にした話
pkshadeck
PRO
0
2.6k
PHP に部分適用が来るぞ!……ところで何それ?おいしいの? #phpcon / phpcon-2026
shogogg
0
180
Welcome to the "Parametricity" 🏙️ − Generic だけど Specific な世界 −
guvalif
PRO
1
170
トークンをケチるな、設計しろ:GitHub Copilotを賢く使うコンテキスト戦略
ochtum
0
320
【やさしく解説 設計編 #0】DDDのコード、読めるのに分からない人へ
panda728
PRO
2
270
AWS CDK を「作」ってみた 〜フルスクラッチで見えた CDK の裏側〜 / aws-cdk-from-scratch
gotok365
3
360
言語を使う側から、作る側へ。 自作 Lisp で得た新たな気づき。
andpad
0
120
【やさしく解説 設計編・中級 #6】良いアーキテクチャとは ~ 一本の登り道の、行き先 ~
panda728
PRO
0
160
Featured
See All Featured
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
170
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.6k
GraphQLとの向き合い方2022年版
quramy
50
15k
Balancing Empowerment & Direction
lara
6
1.2k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.6k
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
67
56k
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
1
420
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
340
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.8k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
210
The #1 spot is gone: here's how to win anyway
tamaranovitovic
3
1.1k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
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-