Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Upgrow: Railsアプリの保守性を高めるためのShopifyのアプローチ / Upgrow
Search
Daiki Miura
April 23, 2021
Technology
5.2k
6
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Upgrow: Railsアプリの保守性を高めるためのShopifyのアプローチ / Upgrow
Daiki Miura
April 23, 2021
More Decks by Daiki Miura
See All by Daiki Miura
RubyでJVMを実装してみる / Implement JVM with Ruby
daikimiura
1
3.4k
Other Decks in Technology
See All in Technology
AI時代、データエンジニアが一番おもろい
genshun9
0
660
CLIライブラリ開発を支える技術
htnabe
0
120
Claude Codeを「使うほど育つ」AI秘書にするノウハウ
minorun365
PRO
31
27k
ADKで始める業務改善 - AIエージェント開発時の考えと設計
harappa80
2
180
SREは、MCPとAutopilotをこう使え!
kazumax55
3
880
データ_AIの事業の勝敗をわけるもの
nek0128
1
440
技術的負債から考える、AI時代のエンジニアリング投資 — ビズリーチの技術的負債と向き合った経験から、変更し続けられるソフトウェアを考える/ technical-debt-con2026
visional_engineering_and_design
4
3.1k
AIで社員の自主発信に広報目線を組み込む
_mossann_t
0
120
EventBridge に「合流」はない ― サーバーレスのワークフローを育てるということ / No Join in EventBridge
yusukeshimizu
2
110
AgentCore Runtime上にAgentic Coding基盤を構築・展開する際の設計ポイントと限界点 / Design considerations and limitations when building an agentic coding platform on AgentCore Runtime
har1101
4
250
Deployment の 先にある AI Agent 基盤 - kagent vNext、Agent Substrate、Hermes から読み解く Agent Runtime の現在地 / k8s-matsuri-2-ai-agent-platform-amsy810
masayaaoyama
4
650
HRC_Frontend_Conference_Fukuoka_2026.pdf
ts020
0
740
Featured
See All Featured
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Balancing Empowerment & Direction
lara
6
1.3k
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
530
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.4k
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.8k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
850
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
540
Mobile First: as difficult as doing things right
swwweet
225
10k
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.6k
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
230
Mind Mapping
helmedeiros
1
360
Embracing the Ebb and Flow
colly
88
5.2k
Transcript
Upgrow: Railsアプリの保守性を高めるための Shopifyのアプローチ 2021-04-23 銀座Rails #32 Daiki Miura
自己紹介 ▶ 名前: 三浦 大輝 (Miura Daiki) ▶ GitHub: @daikimiura
▶ Twitter: @daikiii5555 ▶ 最近の趣味: 車輪の再発明 (自作Docker、自作OS、自作Cコンパイラ etc) ▶ PINTORという美術鑑賞アプリの会社で働いています ▶ この前のISUCONでRubyで決勝進出しました🎉
目的 1. Upgrowとはどんなアーキテクチャで、どんな課題をどう解決しようとしているのかを 説明する 2. Upgrowと既存のアプローチの共通点・相違点を明らかにする 3. 1., 2. を踏まえた上でどのようにアーキテクチャ選定を行えば良いかの方針をまと
める
目次 1. Upgrowとは何か? a. 解決しようとした課題か? b. その課題をどう解決しようとしたのか? 2. 同じ課題に対する既存のアプローチとの共通点・相違点は何か? a.
Railsでよく使われるアプローチとの違い b. Rails以外でよく使われるアーキテクチャとの違い 3. まとめ
注意 現在Upgrowの公式GitHubレポジトリ及び公式ドキュメントは非公開になっており見るこ とができません。 この発表は2021年2月25日時点での情報を元に作成しています。
1. Upgrowとは何か? 解決しようとした課題か? その課題をどう解決しようとしたのか?
ソフトウェアアーキテクチャのゴール 「そもそもなんのためにソフトウェアアーキテクチャを適用するのか?」 • 保守性の高いソフトウェアを構築するため ◦ ⇔ コードの変更・追加を素早く簡単に行える ソフトウェアを構築するため ▪ どこを変更
/ どこに追加 すればいいのかが明確 ▪ 変更・追加したことによる副作用が小さい ▪ 変更・追加する行数が少ない
Upgrowが解決しようとした課題 - “Rails Way” で開発してるといくつかの課題が生じ、保守性が下がってしまった - “Rails Way” = Railsが提供しているコンポーネントのみで開発する手法
=> Upgrowという独自のアーキテクチャを導入して解決した shopifyでは
Upgrowが解決しようとした課題 (Controller編) - 複雑化したController Filter (before_action) - 条件付きのbefore_action (:if, :unless)
- Controllerのサブセットにのみ適用される before_action (:only, :except) - Fat Controller - どこに書いたらいいか明確ではないロジックが全て Controllerに書かれる - 複数のModelを触る場合の一連の手続き - メール送信 - 外部サービス呼び出し - ジョブをエンキュー - 上のようなロジックを ControllerではなくModelに書いてFat Modelになる場合も多い
Upgrowが解決しようとした課題 (Model編) - Active RecordのCallback地獄 - 大量のcallback - 条件付きのcallback -
親クラスから継承されたcallback - Fat Model - Modelに大量のメソッドが生える - どこに書いたらいいか分からないロジック - Validation - Callback - “神Model”、”神Class” - Active RecordのAssociation - 不必要にModel同士を密結合にしている - あるModelのメソッドが別のModelのインスタンスを触る余地を常に与えている - 原則、ModelのメソッドはそのModelに関する処理のみであるべき - associationは遅延ロードされる => N+1 問題を引き起こす
そもそもRails Wayの何が問題なのか? - ControllerにもModelにも書けない (書きたくない) ロジックがある - Modelが責務を負いすぎている
そもそもRails Wayの何が問題なのか? - ControllerにもModelにも書けない (書きたくない) ロジックがある - 複数のModelを触る場合の一連の手続き - ある特定のケースでのみ行われる
Modelの処理 (特定の場合のみ行われるバリデーションなど ) - メール送信 - 外部サービス呼び出し - ジョブをエンキュー - => Clean Architectureでいうところのアプリケーションビジネスルール - ビジネスロジック (ルール) には2種類ある - エンタープライズビジネスルール - アプリケーションの都合ではないコアなルール - 特定のアプリケーション操作が変更しても影響を受けないロジック - アプリケーションビジネスルール - アプリケーション固有のルール - システムのユースケース
そもそもRails Wayの何が問題なのか? - Modelが責務を負いすぎている - Controller - アプリ外部とのインターフェース - HTTPの仕様を扱う
- View - HTTPレスポンスボディを組み立てる - Controllerの責務の一部を切り出したもの - Model - ControllerとViewが負っている責務以外の全ての責務 - ビジネスロジックの記述 - DBへの永続化 - ユーザーからの入力値のバリデーション - コールバック - etc
課題をどのように解決しようとしたか? - 「単一の責任を持つ小さなオブジェクト同士がメッセージを交換して処理を行う」よう にする - 単一責任原則 (SRP) に沿って 既存のコンポーネントを分解・新たなコンポーネントを追 加
していく - ⇔ コンポーネントに変更を加える理由がただ 1つになるように 既存のコンポーネント を分解・新たなコンポーネントを追加 していく
課題をどのように解決しようとしたか? Record Repository Action Input Model View Result Controller DB
View Controller DB Model Rails Way Upgrow
Upgrowのアーキテクチャ (Model) Record Repository Action Input Model View Result Controller
DB 責務: アプリのコアなビジネスロジックの記述 - エンタープライズビジネスルールの記述 - インスタンスはImmutable - Clean Architectureで言うところのEntity - DBとのやり取りやValidationなどの責務は負わない - ActiveRecord::Baseを継承しない
Upgrowのアーキテクチャ (Model) Record Repository Action Input Model View Result Controller
DB 責務: アプリのコアなビジネスロジックの記述
Upgrowのアーキテクチャ (Record) Record Repository Action Input Model View Result Controller
DB 責務: DBとのやりとり - データベースの値を Rubyでそのまま表現したもの - DBとのやりとり以外のロジックは一切持たない - Active Recordパターンから外れる - Row Data Gateway? - ActiveRecord::Baseを継承する
Upgrowのアーキテクチャ (Record) Record Repository Action Input Model View Result Controller
DB 責務: DBとのやりとり
Upgrowのアーキテクチャ (Repository) Record Repository Action Input Model View Result Controller
DB 責務: アプリ側から見た永続化レイヤ - 永続化技術 (DBとのやりとり) を隠蔽する - 複数の永続化技術へのやりとりを共通化する - immutableなオブジェクトを返す (Model) - Recordからの返り値 (ARインスタンス) を immutableな別のオブジェクトにマッピングする
Upgrowのアーキテクチャ (Repository) Record Repository Action Input Model View Result Controller
DB 責務: アプリ側から見た永続化レイヤ
Upgrowのアーキテクチャ (Input) Record Repository Action Input Model View Result Controller
DB 責務: ユーザーの入力を検証しオブジェクト化する - 入力のバリデーションを行う - ActiveModel::Modelをincludeすることで validationのための便利メソッドやviewとのシーム レスな統合が行える
Upgrowのアーキテクチャ (Input) Record Repository Action Input Model View Result Controller
DB 責務: ユーザーの入力を検証しオブジェクト化する - 入力のバリデーションを行う - ActiveModel::Modelをincludeすることで validationのための便利メソッドやviewとのシーム レスな統合が行える
Upgrowのアーキテクチャ (Action) Record Repository Action Input Model View Result Controller
DB 責務: アプリケーション固有のロジックを記述する - ユースケースを記述 - リクエストと1対1対応する - パブリックなメソッドはただ1つのみ (Action#perform) - Result (後述) を返す
Upgrowのアーキテクチャ (Result) Record Repository Action Input Model View Result Controller
DB 責務: Actionの結果を表すオブジェクト - いくつかの決まったフィールドを持つ Struct - successかfailureのいずれか状態を表す - failureのときはerrorsフィールドに値が入る
Upgrowのアーキテクチャ (Result) Record Repository Action Input Model View Result Controller
DB
Upgrowのアーキテクチャ (Action)
Upgrowのアーキテクチャ (Controller)
Upgrowのアーキテクチャ Record Repository Action Input Model View Result Controller DB
Upgrowのアーキテクチャ (Association)
Upgrowのアーキテクチャ (Transaction)
2. 同じ課題に対する既存のアプローチ との共通点・相違点何か?
“同じ課題” - Controller - 複雑化したController Filter (before_action) - Fat Controller
- Model - Active Recordのcallback地獄 - Fat Model
同じ課題に対する既存のアプローチ Rails Developers Meetup 2019 「Ruby on Railsの正体と向き合い方」 by @yasaichi
さん
同じ課題に対する既存のアプローチ Rails Developers Meetup 2019 「Ruby on Railsの正体と向き合い方」 by @yasaichi
さん
Upgrowと既存のアプローチとの比較 - 課題の分析 (なぜ課題が生じるか?) - Upgrow - ControllerにもModelにも書けない (書きたくない) ロジックがあるから
- Modelが責務を負いすぎているから - 既存のアプローチ - 特定のユースケースと密結合した処理を書く場所がないから
同じ課題に対する既存のアプローチとの比較 Record Repository Action Input Model View Result Controller DB
Model View Controller DB アプリケーション ビジネスルールを記述するレイヤ (Service, Form, Interactor) 共通点: アプリケーションビジネスルールを記述するコンポーネントを追加したこと 相違点: Upgrowの方が既存のアプローチよりもコンポーネントの粒度が細かい 既存のアプローチ Upgrow
UpgrowとClean Architecture (同心円状アーキテクチャ) との比較 - UpgrowのアーキテクチャはClean Architecture (の一例である同心円状アーキテクチャ ) と似
ている Clean Architecture Upgrow Entities Model Use Cases Action Controllers Controller Gateways Repository DB Record
UpgrowとClean Architecture (同心円状アーキテクチャ) との比較 - UpgrowのアーキテクチャはClean Architecture (の一例である同心円状アーキテクチャ ) と似
ている - => Clean Architectureに従うメリットを享受できる - フレームワーク非依存 - システムをフレームワークの制約で縛るのではなく、フレームワークをツールとして利 用できる - データベース非依存 - DBを簡単に差し替え可能 - ビジネスルールはデータベースに束縛されない - 外部エージェント非依存 - ビジネスルールは外界のインターフェイスに束縛されない - REST API, GraphQL, gRPC - テスト可能 - UI, DB, Webサーバーなどの外部要素がなくてもビジネスロジックのテストを行える
Railsの思想とClean Architectureの思想 (Upgrow) との比較 - Clean Architectureに従うメリットはRailsの思想と反している部分が多い - フレームワーク非依存 -
システムをフレームワークの制約で縛るのではなく、フレームワークをツールとして利用でき る => Railsは「設定より規約」 システム全体として規約にのっとってプログラミングすることで、余計なプログラ ミングや設定を省く - データベース非依存 - ビジネスルールはデータベースに束縛されない => RailsはURLからDBまでを密結合にする - 外部エージェント非依存 - ビジネスルールは外界のインターフェイスに束縛されない => RailsはRESTなwebアプリケーションを作るためのフレームワーク
Railsの思想とClean Architectureの思想 (Upgrow) との比較 Rails Clean Architecture (Upgrow) フレームワークに対する考え 方
フルスタックフレームワーク 基本的にはRails Wayに 沿って作ればいい (Rails is omakase) フレームワークは詳細 (詳細 には依存しない) システム全体の設計思想 全体として密結合な設計に し、規約で縛ることでコード 量を減らす 全体として疎結合な設計に するが、コード量は増える
Railsの思想とClean Architectureの思想 (Upgrow) との比較 このドキュメント(Upgrow) は私を当惑させる。私は Upgrowが 今の形のまま長く使われるようになるとは思わない。
3. まとめ
Railsの課題にどう立ち向かうのか? - 「これを使えば未来永劫問題なし」のような万能アーキテクチャはない - Rails Wayが価値を発揮する状況と他のアプローチが価値を発揮する状況は異なる - プロダクト (ビジネス) の複雑さの増大に従ってリアーキテクチャが必要
- 課題を感じた時に初めてRails Wayから外れる - Rails Wayで課題を感じていない場合はRails Wayに乗っかるのが最適 - まだビジネスがそこまで複雑化しておらずビジネス的な不確実性が大きいので、長期的なアプリの保守性の高さよりも 短期的なスピードが求められる - 課題を感じたらまずは課題を明確にする - なぜFat Modelなのか?なぜFat Controllerなのか? - プログラミング (設計) の原則に従って、その課題を解決するような新たな必要最小限のコンポーネントを追加する - SOLID原則 - オブジェクト指向設計の原則 - 「課題を感じる => コンポーネント追加 => 課題を感じる => コンポーネントを追加 => ....」を繰り返す - 新たに追加したコンポーネントをチーム全員が正しく使えるようにする - 設計を明文化して (ドキュメントに落として) 周知する - gemでインターフェースを縛る
Thank you for listening!