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
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
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
LLMによるContent Moderationの本番運用の裏側と品質担保への挑戦
suikabar
3
690
The NotImplementedError Problem in Ruby
koic
1
810
AI 時代のソフトウェア設計の学び方
masuda220
PRO
29
13k
dRuby over BLE
makicamel
2
340
DynamoDBには集計系のクエリがないけどなんとかしたい
musan
1
140
そのテスト、説明できますか?~LWテスト戦略FW~のご紹介
nakahara
0
140
Webフレームワークの ベンチマークについて
yusukebe
0
170
Spring Security 実践 ─ GraphQL APIで実務に役立つ 認証・認可 を学ぶ
wagyu
0
240
脅威をエンジニアリングの糧にして――現場編 / Turning Threats into Engineering Fuel — Field Edition
nrslib
0
280
LLM本来の能力を解き放つサンドボックス技術とAI民主化への適用
yukukotani
3
4.1k
Performance Engineering for Everyone
elenatanasoiu
0
140
正しくソフトウェアを作る、前提を疑うための認知の視点 / doubt-premise
minodriven
21
6.7k
Featured
See All Featured
Navigating Weather and Climate Data
rabernat
0
220
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
410
First, design no harm
axbom
PRO
2
1.2k
We Have a Design System, Now What?
morganepeng
55
8.2k
Unsuck your backbone
ammeep
672
58k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
290
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
240
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
11k
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
230
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
460
Un-Boring Meetings
codingconduct
0
320
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-